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

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

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

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

[復(fù)制鏈接]

660

主題

660

帖子

4567

積分

四級會員

Rank: 4

積分
4567
跳轉(zhuǎn)到指定樓層
樓主
發(fā)表于 2024-12-10 08:00:00 | 只看該作者 |只看大圖 回帖獎勵 |倒序瀏覽 |閱讀模式

$ P' ~' ?5 G' @0 t& L點擊上方藍色字體,關(guān)注我們# T6 s* D6 Y1 H6 e% r- z/ Z- V
' O8 }; `" g2 U0 X7 N
1.1、UNIX IPC
- S$ F) K, L, J( L( F0 p% N0 y4 lUNIX 傳統(tǒng)的 IPC 機制包括管道、FIFO 和信號,這些機制最早由 UNIX 系統(tǒng)引入,適用于簡單的單機進程間通信。
# Q8 [! p/ D+ u
  • 管道(Pipe)' k  e; X  w$ I- w) D/ A# K6 \
    一種單向、半雙工的通信機制,通常用于父子進程間的數(shù)據(jù)傳遞。
    / G8 M5 X! u# ]/ s* q. j. Q父進程可以寫入數(shù)據(jù),子進程可以讀取。
  • FIFO(命名管道)
    + V& I! U0 r$ _! \1 ]# d6 z! z7 |類似于管道,但通過文件系統(tǒng)實現(xiàn),任何進程都可以通過路徑訪問該管道,實現(xiàn)雙向通信。
  • 信號(Signal)
    ) e) V  a, `1 d- X/ ~% I$ H: M信號是一種用于進程間異步通知的機制,可以用于進程之間的簡單通信或事件通知,例如 SIGINT(Ctrl+C 發(fā)送的中斷信號)。
    7 T, [1 M( n6 [4 J) z. r0 Z
    5 [) v  z# ~) J& |' e: v
    1.2、System V IPC
    / M9 k8 B' }# w9 Z9 ?* hSystem V IPC 是 UNIX 的增強版本,主要包括信號量、消息隊列和共享內(nèi)存,適合需要更復(fù)雜的進程同步與數(shù)據(jù)共享的場景。
    + x' \% d* U: o: R  O! Z
  • 信號量(Semaphore)
    & g+ E* X/ W8 g用于進程間的同步,通常用于控制對共享資源的訪問。
    $ S# w2 r2 z1 H/ Q: I信號量用于防止多個進程同時訪問同一資源,避免資源爭用問題。
  • 消息隊列(Message Queue)
    7 ^, i# v) b) j& u4 o* Z允許進程以消息的形式發(fā)送和接收數(shù)據(jù)。
    8 w3 t4 ]5 H7 v+ y! A消息隊列是一種先進先出(FIFO)的結(jié)構(gòu),支持不同類型的消息,使得進程可以基于消息類型進行處理。
  • 共享內(nèi)存(Shared Memory)
    3 @% [7 a+ F: E& U# ^7 F  G, l進程之間共享同一塊內(nèi)存區(qū)域,允許它們直接讀寫數(shù)據(jù)。
    9 e; `( m( i4 {" x5 C這是最有效的 IPC 方式,因為數(shù)據(jù)不需要在進程之間復(fù)制。
    7 K0 j" q8 m" R
    # V" N0 S. E. k
    1.3、POSIX IPC
    3 C2 ~3 V% f$ P) E4 lPOSIX IPC 是 System V IPC 的改進版本,旨在解決 System V IPC 在靈活性和可移植性上的一些不足。
    8 f" A3 T8 V( ^! L
    0 p3 X& K6 {8 ~& {POSIX 標(biāo)準(zhǔn)為 UNIX 系統(tǒng)間的兼容性提供了統(tǒng)一的接口,使得程序可以更方便地在不同的 UNIX 系統(tǒng)間移植。9 F; ^1 z( ^8 I& j
  • POSIX 信號量- |  r/ v6 z' s" O) O
    與 System V 信號量類似,用于進程同步,但提供了更靈活的接口和更強的實時性支持。
  • POSIX 消息隊列) {+ u0 W( B; w! L9 r
    改進了 System V 消息隊列,允許指定消息的優(yōu)先級,并提供更簡單的接口。
  • POSIX 共享內(nèi)存; n3 @# g8 I1 \8 ~; f) [
    與 System V 共享內(nèi)存類似,但具有更好的兼容性和可移植性,接口設(shè)計更加現(xiàn)代化。# L" D4 K7 f4 C7 U/ g

    * u( ?% n. y- U5 y: o/ o1.4、套接字(Socket)通信
    9 x& E( i2 g" F" m6 ^/ c: {套接字是一種既可以用于本地進程間通信,也可以用于網(wǎng)絡(luò)通信的機制,支持雙向數(shù)據(jù)傳輸。+ B# ]7 r4 G: M7 }4 M
    0 e6 T- b5 i0 q! r
    基于套接字的 IPC 可以實現(xiàn)非常靈活的通信模式,例如客戶端-服務(wù)器架構(gòu),適合在多臺計算機之間傳遞數(shù)據(jù)。
    8 z  e+ R- a9 p& Q" g, o
    : e' S3 a0 k4 P" f' F& M; |各類 IPC 機制的對比和應(yīng)用場景:/ x( S9 m9 {7 M' P
    " P! F3 y5 l2 g% N/ }  g
    6 O: {% e) Z7 N7 c+ _" G

    ' W" _- L1 l9 C) M2- [; h  m* u/ v3 [! w: N) ~
    管道(Pipe)
    6 N5 i* y) U6 ?管道是一種半雙工(單向)的通信方式,通常用于父子進程之間的通信。一個進程可以向管道寫入數(shù)據(jù),另一個進程從管道讀取數(shù)據(jù)。3 ]) W! D# x4 Z- i6 R0 w$ v* V# }
    6 [/ c4 D, E9 B( M7 n" q
    Linux 提供了無名管道和命名管道兩種類型。
    1 K  h' ~. G  f3 P+ i  a4 w
  • 無名管道(Anonymous Pipe)
    4 k" B! c: d1 ~, M6 Q% K% K只能在具有親緣關(guān)系的進程間使用,比如父進程和子進程。
  • 命名管道(Named Pipe 或 FIFO)
    - w+ e' w/ ]  x: J3 }通過文件系統(tǒng)中的路徑來創(chuàng)建,任意進程都可以訪問。9 i# b7 i4 e+ I6 {( E, J

    ' ?8 |6 P/ u: c  A  ~) k+ {5 i

    " p! y# {8 j6 J8 w示例
    8 X5 X. a" g6 E9 U+ ?+ W- k+ L2 J: d) Q% k' J; W6 E4 z- L
  • int main() {    int fd[2];    pipe(fd); // 創(chuàng)建無名管道9 \9 b3 I, @# C
        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! l- {3 f3 H6 l, e
    ", buffer);        close(fd[0]);    }    return 0;}$ F& A: j* j+ D- Z) I
    3
    ! X' w, k+ W5 C, J  F消息隊列(Message Queue)
    / ?, y$ _; `' l. E$ v) k消息隊列是一種先進先出的隊列,允許進程以消息的形式發(fā)送和接收數(shù)據(jù)。8 {5 j: ~5 F: P- r

    5 p  W$ v- D- |+ x; T  H+ _6 x消息隊列可以支持多種類型的消息,通過消息類型實現(xiàn)多種目的的通信。
    8 J+ `- H; {2 M9 Q* _" R7 W$ _6 V( b8 [0 q2 r
    示例:進程A可以向隊列發(fā)送一個帶有特定類型的消息,而進程B可以根據(jù)消息類型進行處理。
    1 F3 o, p8 j" g6 \. z
    + m. d- Z/ a8 r' X  `& E) J
  • struct msgbuf {    long mtype;    char mtext[100];};
    ( u/ P: y+ ]% e( Fint main() {    key_t key = ftok("msgqueue", 65);    int msgid = msgget(key, 0666 | IPC_CREAT);    struct msgbuf message;
    / H" Z1 {' j) L' H* D    message.mtype = 1; // 消息類型    snprintf(message.mtext, sizeof(message.mtext), "Hello Message Queue");    msgsnd(msgid, &message, sizeof(message.mtext), 0);. m3 o( v$ m# k7 c1 }; x
        return 0;}
    3 E8 M: X4 u! T; p  Q) _* q0 `& G/ O4$ I: x6 A+ u6 T$ x+ p
    共享內(nèi)存(Shared Memory)
    3 e2 h# s9 Z% G: m) |2 T; K$ q共享內(nèi)存是最快的 IPC 機制之一,因為進程之間直接訪問同一塊內(nèi)存區(qū)域,而不需要拷貝數(shù)據(jù)。( Y, |' g9 i& U0 g* z, @
    + C1 M4 Q$ A' `7 g& H+ T
    通常使用 shmget()、shmat() 和 shmdt() 函數(shù)進行共享內(nèi)存的創(chuàng)建和訪問。4 j4 x+ v0 d( V: S4 S1 }" B

    ! U) M7 a2 f5 A' f示例
    1 w1 z; y) m: e! e5 Q' H+ H6 |+ b0 d! D* a; c
  • int main() {    key_t key = ftok("shmfile",65);    int shmid = shmget(key, 1024, 0666|IPC_CREAT);    char *str = (char*) shmat(shmid, (void*)0, 0);" h8 }3 j& u/ e* w
        strcpy(str, "Hello Shared Memory");
    0 Q; j& @* P% @1 w, n+ U! `    printf("Data written in memory: %s/ k2 p: Z8 K& o. S
    ", str);    shmdt(str);
    % j4 D1 R) C0 \$ B0 u# y3 U    return 0;}) S4 A2 m6 m  A$ L8 Q$ x( O4 }
    5  A) N- \; s' T# ^9 o
    信號量(Semaphore)
    8 A1 I: q% J% |2 @' h" I+ y! R, `信號量是一種用于進程同步的機制,通常用于控制多個進程對共享資源的訪問。2 ^8 S4 b, z, O( G/ y

    ) P8 {: V7 d- B/ ]* F嵌入式系統(tǒng)中,信號量通常用來避免多個進程同時訪問同一資源,防止數(shù)據(jù)競爭。
    2 {, G" P/ C4 W- D- x
    3 o$ R* B* m. }% _示例:信號量可以通過 semget() 和 semop() 函數(shù)來操作,用于鎖定或解鎖資源。5 a4 l/ J% t0 a, s5 F1 P/ Z
    ! }; F' y/ }6 W2 H4 Z3 a4 a
  • 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操作
      W" U3 A% D! U    semop(semid, &sem_lock, 1); // 上鎖    printf("Critical section
    ) p: C/ K0 {% U");    semop(semid, &sem_unlock, 1); // 解鎖4 Q( J4 b9 E$ ~& W
        return 0;}8 q2 b+ `' a7 o) ], w3 h9 h
    6, F# F5 s9 V- Y% b
    套接字(Socket)
    0 v- y( ^. J; ]. ~' p* k* q套接字不僅支持本地進程間通信,還可以用于網(wǎng)絡(luò)通信。4 z- n" B1 U/ ^
    $ g, H" f* v1 X# N" H
    基于套接字的 IPC 支持雙向通信,比較靈活,適合嵌入式系統(tǒng)中進程之間需要頻繁且復(fù)雜的數(shù)據(jù)交互的情況。
    * i1 k: D, A  F2 m
    9 A* x: C% B$ \7 P8 C1 c. b示例" l' Q2 s: z' p

    * E, D. k$ k2 c' q
  • int main() {    int sv[2];    socketpair(AF_UNIX, SOCK_STREAM, 0, sv);
    9 T7 J$ w! @* C  ?7 ^" g* P) s, c    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
    + D! L/ }( W- r", buffer);        close(sv[0]);    }    return 0;}
    / v' ]7 z( }6 S' B& r" M; E+ u8 H7, |" C4 E) r" d) N+ [
    信號(Signal)
    1 b0 ~# k$ }. `' x信號是用來通知進程發(fā)生某種事件的機制。進程可以捕獲、忽略或處理信號,典型的信號包括 SIGINT(中斷信號)和 SIGKILL(殺死進程信號)。
    : u6 D0 i  d0 a0 W6 y( R% E0 p& K& l: k2 H; X" T
    示例:處理 SIGINT 信號(Ctrl+C)。' l7 M( S0 m1 \1 D2 g7 D

    $ b" {+ o0 N0 W" r8 K8 z7 U4 i( s+ y
  • void sigint_handler(int sig) {    printf("Caught signal %d
    ; W6 T7 M& J" d$ P' O5 Z", sig);}
    4 `' S7 ~2 {5 m9 Zint main() {    signal(SIGINT, sigint_handler);    while (1) {        printf("Running...9 y$ j" i9 D% n( Y. o
    ");        sleep(1);    }    return 0;}
    : P2 s( z/ a: F進程間通信的機制多種多樣,選擇合適的方式取決于應(yīng)用場景的需求。3 o) ]! Q6 x! A. u7 a6 k* z

    4 O' r1 V$ `9 S6 r" `5 P . e% S$ `! j( U# w2 S& R
    點擊閱讀原文,更精彩~
  • 回復(fù)

    使用道具 舉報

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

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

    本版積分規(guī)則


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