電子產(chǎn)業(yè)一站式賦能平臺

PCB聯(lián)盟網(wǎng)

搜索
查看: 67|回復(fù): 0
收起左側(cè)

嵌入式Linux:進(jìn)程間通信機(jī)制

[復(fù)制鏈接]

660

主題

660

帖子

4567

積分

四級會員

Rank: 4

積分
4567
跳轉(zhuǎn)到指定樓層
樓主
發(fā)表于 2024-12-10 08:00:00 | 只看該作者 |只看大圖 回帖獎勵 |倒序瀏覽 |閱讀模式
0 d& c. c* v5 E& ^& l4 s" s
點擊上方藍(lán)色字體,關(guān)注我們
* i: _6 k0 d; G
, V: p+ k3 Q2 ]1.1、UNIX IPC
! I" ~, B$ @" ?# x* R  OUNIX 傳統(tǒng)的 IPC 機(jī)制包括管道、FIFO 和信號,這些機(jī)制最早由 UNIX 系統(tǒng)引入,適用于簡單的單機(jī)進(jìn)程間通信。( b* g! J' _( k5 c9 c: s/ x& L% J
  • 管道(Pipe)$ J2 G/ M: |  p$ w; C) Y
    一種單向、半雙工的通信機(jī)制,通常用于父子進(jìn)程間的數(shù)據(jù)傳遞。3 [) w/ L4 w* |( j' z; L/ w
    父進(jìn)程可以寫入數(shù)據(jù),子進(jìn)程可以讀取。
  • FIFO(命名管道)! Q( i6 U7 [3 T6 Q  S7 X
    類似于管道,但通過文件系統(tǒng)實現(xiàn),任何進(jìn)程都可以通過路徑訪問該管道,實現(xiàn)雙向通信。
  • 信號(Signal)
    3 e& o8 A; R, b+ P信號是一種用于進(jìn)程間異步通知的機(jī)制,可以用于進(jìn)程之間的簡單通信或事件通知,例如 SIGINT(Ctrl+C 發(fā)送的中斷信號)。
    $ W, ^2 J/ o8 R' s5 `: _/ y

    % C/ p: ?+ w& q0 c, L: D- ^5 C5 p2 m1.2、System V IPC
    ; _# Y! L# w# j6 H* U7 mSystem V IPC 是 UNIX 的增強(qiáng)版本,主要包括信號量、消息隊列和共享內(nèi)存,適合需要更復(fù)雜的進(jìn)程同步與數(shù)據(jù)共享的場景。2 S* d% ]8 A% j5 v9 _  l' b
  • 信號量(Semaphore)
    ( c1 u, ]0 u* Z  A" t. E6 [用于進(jìn)程間的同步,通常用于控制對共享資源的訪問。
    * \3 g3 X, i8 w& Y. ?; i3 m信號量用于防止多個進(jìn)程同時訪問同一資源,避免資源爭用問題。
  • 消息隊列(Message Queue)
    1 i" [  C/ W3 p! w允許進(jìn)程以消息的形式發(fā)送和接收數(shù)據(jù)。9 R7 R# D5 y$ y1 j* p
    消息隊列是一種先進(jìn)先出(FIFO)的結(jié)構(gòu),支持不同類型的消息,使得進(jìn)程可以基于消息類型進(jìn)行處理。
  • 共享內(nèi)存(Shared Memory)
    - @; j: Z+ N# U" a% G進(jìn)程之間共享同一塊內(nèi)存區(qū)域,允許它們直接讀寫數(shù)據(jù)。
    ( d. E! s$ t; d' L' v- t這是最有效的 IPC 方式,因為數(shù)據(jù)不需要在進(jìn)程之間復(fù)制。
    ( z( w$ d  x5 ^4 v0 _

    2 o/ p6 N2 J( y; d1 p+ A! E' x1.3、POSIX IPC
    2 J  P. F% m7 R1 C+ ]POSIX IPC 是 System V IPC 的改進(jìn)版本,旨在解決 System V IPC 在靈活性和可移植性上的一些不足。4 a* p# \+ `' E1 f

    ; K% |" X  Z$ OPOSIX 標(biāo)準(zhǔn)為 UNIX 系統(tǒng)間的兼容性提供了統(tǒng)一的接口,使得程序可以更方便地在不同的 UNIX 系統(tǒng)間移植。
    & d3 }  j5 O* S" ]
  • POSIX 信號量
    0 M; o4 a# U5 i( j2 e7 i+ }與 System V 信號量類似,用于進(jìn)程同步,但提供了更靈活的接口和更強(qiáng)的實時性支持。
  • POSIX 消息隊列
    ' x9 j: J& `) g) F, A, B改進(jìn)了 System V 消息隊列,允許指定消息的優(yōu)先級,并提供更簡單的接口。
  • POSIX 共享內(nèi)存
    ) T3 `% r+ R0 L1 F% X與 System V 共享內(nèi)存類似,但具有更好的兼容性和可移植性,接口設(shè)計更加現(xiàn)代化。& k" \: h9 g2 Y1 X9 Y5 A1 v

    * w! I( ?: H( C6 q1.4、套接字(Socket)通信
    . G6 a" n* O# C- C/ F9 \套接字是一種既可以用于本地進(jìn)程間通信,也可以用于網(wǎng)絡(luò)通信的機(jī)制,支持雙向數(shù)據(jù)傳輸。' _& e# K# g' t8 |& i1 @

    % n6 h' D4 N) C# c7 y7 _; X) y) [! j基于套接字的 IPC 可以實現(xiàn)非常靈活的通信模式,例如客戶端-服務(wù)器架構(gòu),適合在多臺計算機(jī)之間傳遞數(shù)據(jù)。+ S& E8 G& c) ?5 p8 e( l' D3 i

    5 |+ e: O; v& H6 T各類 IPC 機(jī)制的對比和應(yīng)用場景:& v( ?9 O/ G" y6 s6 l: [" M

    + v' t& ?, T% f0 N9 S8 y7 @5 L
    9 ~  Q' c$ I8 M7 B% {* R6 I& [' a) I
    2% q7 B2 r3 I% p1 }8 O& i$ ~
    管道(Pipe)/ N6 ]# w4 l  W4 B* f0 ~0 l
    管道是一種半雙工(單向)的通信方式,通常用于父子進(jìn)程之間的通信。一個進(jìn)程可以向管道寫入數(shù)據(jù),另一個進(jìn)程從管道讀取數(shù)據(jù)。
    9 q/ a& k" y6 s8 u$ v
    2 k; h- h- J+ ~) X; \Linux 提供了無名管道和命名管道兩種類型。
      j- t9 W; U2 A& v# A
  • 無名管道(Anonymous Pipe)! L/ L: t2 n! ]9 I; d$ c+ W  {
    只能在具有親緣關(guān)系的進(jìn)程間使用,比如父進(jìn)程和子進(jìn)程。
  • 命名管道(Named Pipe 或 FIFO); q+ D* h. S" u" y" U
    通過文件系統(tǒng)中的路徑來創(chuàng)建,任意進(jìn)程都可以訪問。6 E" m. V: C& M  Y& x' _2 t
    $ L3 [6 `2 o' z* y6 [
    4 H0 g  a: D) C! G$ D+ W
    示例2 [$ F# [; Z6 }, I2 R

    9 ?5 G9 L+ Q% q) |0 n
  • int main() {    int fd[2];    pipe(fd); // 創(chuàng)建無名管道8 k8 D# f- S: k' f! G
        if (fork() == 0) { // 子進(jìn)程        close(fd[0]); // 關(guān)閉讀取端        write(fd[1], "Hello, parent!", 15);        close(fd[1]);    } else { // 父進(jìn)程        char buffer[20];        close(fd[1]); // 關(guān)閉寫入端        read(fd[0], buffer, sizeof(buffer));        printf("Received: %s
    ) d. |2 _+ y: |3 a# b; ]", buffer);        close(fd[0]);    }    return 0;}8 D. Q' b2 ]$ `0 J6 E: I3 a
    3. [. T: u" A, A7 D$ h6 f- j6 N
    消息隊列(Message Queue)
    / t) `3 K! e4 j消息隊列是一種先進(jìn)先出的隊列,允許進(jìn)程以消息的形式發(fā)送和接收數(shù)據(jù)。
    5 ]. N$ F, B0 F) J, x& P7 \( q0 u- Q4 }& D( f, d
    消息隊列可以支持多種類型的消息,通過消息類型實現(xiàn)多種目的的通信。
    . x5 D1 P( u3 L" f( W$ n7 I' b; G
    + x3 r$ W' A  x& i4 _* |/ \& q示例:進(jìn)程A可以向隊列發(fā)送一個帶有特定類型的消息,而進(jìn)程B可以根據(jù)消息類型進(jìn)行處理。- H/ @) C, r3 `0 n9 {

    ' e. m- ~& E) H% l( p
  • struct msgbuf {    long mtype;    char mtext[100];};4 c( b7 ?& W# q) Z0 X& C, M: W
    int main() {    key_t key = ftok("msgqueue", 65);    int msgid = msgget(key, 0666 | IPC_CREAT);    struct msgbuf message;
    + I9 \0 I7 B4 [% H    message.mtype = 1; // 消息類型    snprintf(message.mtext, sizeof(message.mtext), "Hello Message Queue");    msgsnd(msgid, &message, sizeof(message.mtext), 0);! `" X( I7 r5 L( O* F+ @
        return 0;}
    ! o1 o  N; n3 @4* H) T1 b% ]: L  ~1 k( z& [
    共享內(nèi)存(Shared Memory)) }% Z4 i. j, T* e2 k5 U* \4 @
    共享內(nèi)存是最快的 IPC 機(jī)制之一,因為進(jìn)程之間直接訪問同一塊內(nèi)存區(qū)域,而不需要拷貝數(shù)據(jù)。
    3 b# |& m9 Z8 z$ a# X7 d& M2 k8 C" G% C
    通常使用 shmget()、shmat() 和 shmdt() 函數(shù)進(jìn)行共享內(nèi)存的創(chuàng)建和訪問。
    + a9 p9 [) c- _2 q4 |' M" Q# N5 c3 N4 Z2 B: D
    示例, r9 z/ [9 t  @& D3 y* g
    : r6 l& |3 [; f$ G2 p% r
  • int main() {    key_t key = ftok("shmfile",65);    int shmid = shmget(key, 1024, 0666|IPC_CREAT);    char *str = (char*) shmat(shmid, (void*)0, 0);: m: F4 u, x- e8 g" z) O5 K) b' s9 Q
        strcpy(str, "Hello Shared Memory");
    : v$ f" z( |; v' d% p0 |    printf("Data written in memory: %s
    3 Z# h1 O% W. U- h. l$ Z", str);    shmdt(str);9 h3 {0 h  Z+ ]% ^: A+ I
        return 0;}
    ( x. w- o5 |+ a* _! h5 K; G51 D5 e- A1 f5 q( ^
    信號量(Semaphore)
    ! L! F) @/ t7 [/ c, i信號量是一種用于進(jìn)程同步的機(jī)制,通常用于控制多個進(jìn)程對共享資源的訪問。
    . b* ^0 V, k4 T9 e) b% z+ W
    ; x: P' L0 i, M. N6 ~+ T嵌入式系統(tǒng)中,信號量通常用來避免多個進(jìn)程同時訪問同一資源,防止數(shù)據(jù)競爭。; ^' j$ K8 K* C9 S2 \

    5 I9 X4 R, g% S+ I( x" U示例:信號量可以通過 semget() 和 semop() 函數(shù)來操作,用于鎖定或解鎖資源。
    7 x1 m* q# r) o" C$ |2 C6 e& y7 s9 Z! J
  • int main() {    key_t key = ftok("semfile",65);    int semid = semget(key, 1, 0666 | IPC_CREAT);    struct sembuf sem_lock = {0, -1, 0}; // 減1操作    struct sembuf sem_unlock = {0, 1, 0}; // 加1操作
    1 K, [9 I0 A& g& p/ p& g9 l    semop(semid, &sem_lock, 1); // 上鎖    printf("Critical section+ P0 k* q- U$ ^  Y+ [3 B: F+ w
    ");    semop(semid, &sem_unlock, 1); // 解鎖
    + K6 ?8 P# u/ ]/ V7 C! E, k1 X    return 0;}
    3 Z# ~/ T* x) @3 ~68 P( f8 ^) `3 q3 R
    套接字(Socket)
    ' E* }! Q/ ^0 z3 }套接字不僅支持本地進(jìn)程間通信,還可以用于網(wǎng)絡(luò)通信。
    $ D+ ^4 _' W- M. [* z* d. Y& C
    基于套接字的 IPC 支持雙向通信,比較靈活,適合嵌入式系統(tǒng)中進(jìn)程之間需要頻繁且復(fù)雜的數(shù)據(jù)交互的情況。
    . c: U  f; V7 m; W% H3 d
    & h3 @  R5 ~* Y' ]7 v) r. A3 i示例( P7 ?3 H, z  i' h* H
    ) ~2 c* i$ `5 g6 l& y, n5 r
  • int main() {    int sv[2];    socketpair(AF_UNIX, SOCK_STREAM, 0, sv);3 b7 z$ J5 S% Q+ z$ _7 }! _
        if (fork() == 0) { // 子進(jìn)程        close(sv[0]);        write(sv[1], "Hello from child", 16);        close(sv[1]);    } else { // 父進(jìn)程        char buffer[20];        close(sv[1]);        read(sv[0], buffer, sizeof(buffer));        printf("Received: %s3 I' I( e1 ~6 e2 M- B* [
    ", buffer);        close(sv[0]);    }    return 0;}& A. c9 w3 \5 y  l
    73 G0 h* g$ ]- @1 m6 P
    信號(Signal)
      K3 I- p! o/ `/ L2 V& p% a信號是用來通知進(jìn)程發(fā)生某種事件的機(jī)制。進(jìn)程可以捕獲、忽略或處理信號,典型的信號包括 SIGINT(中斷信號)和 SIGKILL(殺死進(jìn)程信號)。* ]5 Y6 b0 O0 M8 o
    4 Z8 \% f5 }7 g' K$ x! Q0 S
    示例:處理 SIGINT 信號(Ctrl+C)。: A3 k' z, o1 H, U0 z: a# u5 ^. y; N
      T! G! h: T. p
  • void sigint_handler(int sig) {    printf("Caught signal %d* B: u" E1 J. a- X3 q
    ", sig);}% |; [" H# k, v5 V) L8 l  M' i
    int main() {    signal(SIGINT, sigint_handler);    while (1) {        printf("Running...
    $ }. Y8 {% y. ?( O' X: T$ Q");        sleep(1);    }    return 0;}
    9 H5 J4 A% y+ [! m6 G3 F4 D進(jìn)程間通信的機(jī)制多種多樣,選擇合適的方式取決于應(yīng)用場景的需求。5 R( B. i# T2 a! _+ r5 f

    " m/ G; o# c5 l1 e. `' F9 S. b
      D: |5 [8 A3 K; d- t# e點擊閱讀原文,更精彩~
  • 回復(fù)

    使用道具 舉報

    發(fā)表回復(fù)

    您需要登錄后才可以回帖 登錄 | 立即注冊

    本版積分規(guī)則


    聯(lián)系客服 關(guān)注微信 下載APP 返回頂部 返回列表