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

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

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

嵌入式Linux:進程間通信機制

[復(fù)制鏈接]

660

主題

660

帖子

4567

積分

四級會員

Rank: 4

積分
4567
跳轉(zhuǎn)到指定樓層
樓主
發(fā)表于 2024-12-10 08:00:00 | 只看該作者 |只看大圖 回帖獎勵 |倒序瀏覽 |閱讀模式
6 ]# h( x8 _0 r
點擊上方藍色字體,關(guān)注我們
& |( u8 C& E. t2 I+ {6 g7 K; P% Q' O1 `6 M
1.1、UNIX IPC9 m; K9 u: x7 b  u, L
UNIX 傳統(tǒng)的 IPC 機制包括管道、FIFO 和信號,這些機制最早由 UNIX 系統(tǒng)引入,適用于簡單的單機進程間通信。9 ?2 N* F9 \1 r/ @( ]* q+ U9 q
  • 管道(Pipe)
    3 R8 R1 L& Z3 J) }' ]' z( Q一種單向、半雙工的通信機制,通常用于父子進程間的數(shù)據(jù)傳遞。* V; H8 v' t/ D, W3 o$ W
    父進程可以寫入數(shù)據(jù),子進程可以讀取。
  • FIFO(命名管道)6 p! p5 [' m3 ]1 Y* p+ U! ?& z
    類似于管道,但通過文件系統(tǒng)實現(xiàn),任何進程都可以通過路徑訪問該管道,實現(xiàn)雙向通信。
  • 信號(Signal)
    1 i" T+ r, ?. r+ }: n" M信號是一種用于進程間異步通知的機制,可以用于進程之間的簡單通信或事件通知,例如 SIGINT(Ctrl+C 發(fā)送的中斷信號)。+ x. s; _% j4 X4 j

    9 o( a- }/ A. ?5 `6 f& x# j1.2、System V IPC
    2 A4 Y9 E+ c0 @, T, eSystem V IPC 是 UNIX 的增強版本,主要包括信號量、消息隊列和共享內(nèi)存,適合需要更復(fù)雜的進程同步與數(shù)據(jù)共享的場景。$ v  h- G# o0 @
  • 信號量(Semaphore)
    - c: S  W) y* g# E& l5 c用于進程間的同步,通常用于控制對共享資源的訪問。
    5 |4 R: K! J3 r信號量用于防止多個進程同時訪問同一資源,避免資源爭用問題。
  • 消息隊列(Message Queue): a, g: q9 s" J3 j  l" \
    允許進程以消息的形式發(fā)送和接收數(shù)據(jù)。
    3 i/ a- k3 R% V9 z! {# a消息隊列是一種先進先出(FIFO)的結(jié)構(gòu),支持不同類型的消息,使得進程可以基于消息類型進行處理。
  • 共享內(nèi)存(Shared Memory)1 v( F* U- }# E6 q, r7 s
    進程之間共享同一塊內(nèi)存區(qū)域,允許它們直接讀寫數(shù)據(jù)。" ^, O5 q0 h% ]+ ?9 x7 W- n
    這是最有效的 IPC 方式,因為數(shù)據(jù)不需要在進程之間復(fù)制。9 y& x6 C- k; a1 ?( [

    9 x  V5 B9 o  o4 ^) N; T' T1.3、POSIX IPC
    % i* G" P' M" f" N; d0 F6 t. cPOSIX IPC 是 System V IPC 的改進版本,旨在解決 System V IPC 在靈活性和可移植性上的一些不足。
    7 i3 E0 ~: r+ T
    4 z) t$ n8 A6 _; f+ p( ?7 VPOSIX 標準為 UNIX 系統(tǒng)間的兼容性提供了統(tǒng)一的接口,使得程序可以更方便地在不同的 UNIX 系統(tǒng)間移植。6 \7 [8 \/ @) L  X  V
  • POSIX 信號量& u- T+ z2 e) k7 {$ [$ W- E8 u
    與 System V 信號量類似,用于進程同步,但提供了更靈活的接口和更強的實時性支持。
  • POSIX 消息隊列) o9 h4 U; F9 C, n" ~4 v
    改進了 System V 消息隊列,允許指定消息的優(yōu)先級,并提供更簡單的接口。
  • POSIX 共享內(nèi)存
    8 |% Z- y9 p% X# f與 System V 共享內(nèi)存類似,但具有更好的兼容性和可移植性,接口設(shè)計更加現(xiàn)代化。
    8 A$ _4 H; M( i' D

    " f7 Y  ?3 w/ M) E3 _0 _, g! w1.4、套接字(Socket)通信" n$ |( _0 v: M' c) e
    套接字是一種既可以用于本地進程間通信,也可以用于網(wǎng)絡(luò)通信的機制,支持雙向數(shù)據(jù)傳輸。! k0 H' Q% s% Y4 I& x

    ( w2 D) f& g% ?- M- i  E  P基于套接字的 IPC 可以實現(xiàn)非常靈活的通信模式,例如客戶端-服務(wù)器架構(gòu),適合在多臺計算機之間傳遞數(shù)據(jù)。
    0 E5 F1 m2 ^/ D; _, N9 J
    6 J& H# @; j4 j, |, I% X各類 IPC 機制的對比和應(yīng)用場景:  @( j7 s' O" E9 M: ]

    6 {' `& y$ O& b7 O! h/ L& r3 Q
    ( ]/ H# {6 h, }6 D+ H* M$ d" _6 K# \; P4 l) {7 s* U  r" u+ f% c
    20 o: e8 {% [' u. s9 @
    管道(Pipe)
    ' e3 \5 S. n2 M& O0 q4 D) n- H管道是一種半雙工(單向)的通信方式,通常用于父子進程之間的通信。一個進程可以向管道寫入數(shù)據(jù),另一個進程從管道讀取數(shù)據(jù)。1 m/ }; s# |3 s* X. V5 I
    ( Q+ ]3 L; I3 Z/ U" n2 A4 e
    Linux 提供了無名管道和命名管道兩種類型。) d9 G7 n. I1 Z" w' z+ q6 m' Z
  • 無名管道(Anonymous Pipe), j. [- o& ^1 a# V6 ~
    只能在具有親緣關(guān)系的進程間使用,比如父進程和子進程。
  • 命名管道(Named Pipe 或 FIFO)
    . r8 W0 _& U: L* M) A5 D通過文件系統(tǒng)中的路徑來創(chuàng)建,任意進程都可以訪問。4 k: {# r* ]: t$ g5 Z
    5 }$ C) a" c! k2 \  B- i

    8 Z# j. I8 I1 I" r  M" C$ \示例, X! c! \( T# p. [" w; z, z" y
    $ k+ x1 Z, c. h$ e7 H
  • int main() {    int fd[2];    pipe(fd); // 創(chuàng)建無名管道
    / B. r! W/ j: V) O2 I3 U: B- R    if (fork() == 0) { // 子進程        close(fd[0]); // 關(guān)閉讀取端        write(fd[1], "Hello, parent!", 15);        close(fd[1]);    } else { // 父進程        char buffer[20];        close(fd[1]); // 關(guān)閉寫入端        read(fd[0], buffer, sizeof(buffer));        printf("Received: %s
    , j% T: _/ ~8 q& r6 H" O3 A", buffer);        close(fd[0]);    }    return 0;}
    & x9 x0 ?3 L/ i5 `5 A3. @  }3 C& R7 h5 w$ u, o. y
    消息隊列(Message Queue)4 H- C% \/ x/ I1 l5 a7 G
    消息隊列是一種先進先出的隊列,允許進程以消息的形式發(fā)送和接收數(shù)據(jù)。
    & U& Q. E! p8 ?* A2 `# O( h
    6 K! ~8 f& S; z1 z: Z消息隊列可以支持多種類型的消息,通過消息類型實現(xiàn)多種目的的通信。
    . M5 D  T/ O' v6 U8 b" A, A* C' M( |4 T+ @7 j/ y
    示例:進程A可以向隊列發(fā)送一個帶有特定類型的消息,而進程B可以根據(jù)消息類型進行處理。/ t/ Z* H9 }! L* t/ K$ Y5 P4 m6 _

    7 a% Q5 ~, X0 g
  • struct msgbuf {    long mtype;    char mtext[100];};
    1 W  H% Q% B  P  H2 M9 E2 F- p3 Sint main() {    key_t key = ftok("msgqueue", 65);    int msgid = msgget(key, 0666 | IPC_CREAT);    struct msgbuf message;
    / l6 ]. Q/ C3 g" t    message.mtype = 1; // 消息類型    snprintf(message.mtext, sizeof(message.mtext), "Hello Message Queue");    msgsnd(msgid, &message, sizeof(message.mtext), 0);
    # M. {; z) F- {6 A! V! k% \    return 0;}/ E! E9 t. p2 o2 |- I
    4
    ) {2 Y6 K; U( c1 {( b1 }共享內(nèi)存(Shared Memory)! N  [$ i8 ^8 P& ?1 r
    共享內(nèi)存是最快的 IPC 機制之一,因為進程之間直接訪問同一塊內(nèi)存區(qū)域,而不需要拷貝數(shù)據(jù)。
    ; F8 {' g. l; B% p  s  \/ H0 r" @+ i$ O- g
    通常使用 shmget()、shmat() 和 shmdt() 函數(shù)進行共享內(nèi)存的創(chuàng)建和訪問。
    9 J, T; x$ s$ E, Y/ Z% r/ j! q$ ^: A0 `9 ?
    示例
    $ e8 `$ T' Z  l/ i; X$ ~
    - K5 g* O# V4 @1 l) L
  • int main() {    key_t key = ftok("shmfile",65);    int shmid = shmget(key, 1024, 0666|IPC_CREAT);    char *str = (char*) shmat(shmid, (void*)0, 0);
    4 S/ J) m- r6 g+ L    strcpy(str, "Hello Shared Memory");
    3 k$ v5 t7 v, |0 g# h0 R1 Z  r0 h8 ^    printf("Data written in memory: %s" W1 n, G( `$ C  N# a
    ", str);    shmdt(str);5 w0 ~5 D5 E" V6 L# S, H6 k& o
        return 0;}
    : w9 ]& ^- r6 V4 k5$ t8 h7 H" c6 ]! ^% s% [: L2 d
    信號量(Semaphore)
    3 l1 ?( v9 k: v% D3 }2 S- u信號量是一種用于進程同步的機制,通常用于控制多個進程對共享資源的訪問。3 y3 G/ U4 O* K
    5 I# s8 ?4 h1 M0 E- ]# e& n  N
    嵌入式系統(tǒng)中,信號量通常用來避免多個進程同時訪問同一資源,防止數(shù)據(jù)競爭。
    : H" h. i2 u. V# d& _9 d* }) o& A2 j% y% g: J
    示例:信號量可以通過 semget() 和 semop() 函數(shù)來操作,用于鎖定或解鎖資源。0 l3 P1 D9 w2 P1 `& E  X
    . o2 z: i. K1 v  ]
  • 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操作
    " S( x' k- w5 N$ ], j- V    semop(semid, &sem_lock, 1); // 上鎖    printf("Critical section
      s  w+ d8 M2 h6 |3 n");    semop(semid, &sem_unlock, 1); // 解鎖0 d# w* b# h/ v* [0 N, a
        return 0;}
    , Z* t& l5 ?7 T( l3 n6; L$ Z: [1 J2 l( L. c, W
    套接字(Socket)
      i2 M8 }5 k+ U+ o  e  S+ x' V套接字不僅支持本地進程間通信,還可以用于網(wǎng)絡(luò)通信。  \  a# t! C9 N
      [( }* R" g" _0 E  g
    基于套接字的 IPC 支持雙向通信,比較靈活,適合嵌入式系統(tǒng)中進程之間需要頻繁且復(fù)雜的數(shù)據(jù)交互的情況。& ?) p7 a2 \" J% J
    5 x( R: i- O5 V" y  P1 S' B
    示例; z. q; _- K9 W
    $ {- H" S3 E1 @4 ~  D) a2 D, P: ~+ P
  • int main() {    int sv[2];    socketpair(AF_UNIX, SOCK_STREAM, 0, sv);
    ! A$ Q9 K& n. F% y: ^& o* q    if (fork() == 0) { // 子進程        close(sv[0]);        write(sv[1], "Hello from child", 16);        close(sv[1]);    } else { // 父進程        char buffer[20];        close(sv[1]);        read(sv[0], buffer, sizeof(buffer));        printf("Received: %s
    : g2 f+ P2 ?8 F6 A7 P" P) r3 X", buffer);        close(sv[0]);    }    return 0;}
    / R: Y% [$ |3 m9 x/ f5 E8 a7' P/ S+ A" x4 Z6 z% Q
    信號(Signal)
    . ^7 d5 N7 w. X* Z" l) o& G信號是用來通知進程發(fā)生某種事件的機制。進程可以捕獲、忽略或處理信號,典型的信號包括 SIGINT(中斷信號)和 SIGKILL(殺死進程信號)。
    9 u* ~! `/ y6 {+ P7 c  d, _6 t6 T/ z) h; Y5 D, H
    示例:處理 SIGINT 信號(Ctrl+C)。5 d$ D6 P- L8 }# N

    # Y3 t! N, \2 G3 E0 K4 [1 G
  • void sigint_handler(int sig) {    printf("Caught signal %d2 p# d) x6 N  I8 D6 ?8 w" l
    ", sig);}
      S# k; v$ T0 }! l9 L  eint main() {    signal(SIGINT, sigint_handler);    while (1) {        printf("Running...
    7 N* Q6 A9 i: d+ r");        sleep(1);    }    return 0;}
    ' t% D. s4 d) v5 v0 X進程間通信的機制多種多樣,選擇合適的方式取決于應(yīng)用場景的需求。
    - M' M! ^" K- b& I- o
    6 i+ P' D  ~( z4 g9 F
    : Y* R7 Z7 f6 R; p點擊閱讀原文,更精彩~
  • 回復(fù)

    使用道具 舉報

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

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

    本版積分規(guī)則


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