|
3rqolratvad64088525943.gif (60.41 KB, 下載次數(shù): 0)
下載附件
保存到相冊(cè)
3rqolratvad64088525943.gif
2024-12-10 21:53 上傳
+ c/ d0 F0 J* {( H/ `7 s/ b點(diǎn)擊上方藍(lán)色字體,關(guān)注我們
% K( [/ M! K- S$ R6 }& ]7 F% Q( e. V& D U3 @, @
1.1、UNIX IPC% E" X+ B# L1 z) F! W1 z" i( v& t
UNIX 傳統(tǒng)的 IPC 機(jī)制包括管道、FIFO 和信號(hào),這些機(jī)制最早由 UNIX 系統(tǒng)引入,適用于簡(jiǎn)單的單機(jī)進(jìn)程間通信。
5 k# e9 r' ]& F- n7 k管道(Pipe):' h( D- ^2 ^) x$ D
一種單向、半雙工的通信機(jī)制,通常用于父子進(jìn)程間的數(shù)據(jù)傳遞。
/ D. A1 I4 a R0 u, P父進(jìn)程可以寫入數(shù)據(jù),子進(jìn)程可以讀取。FIFO(命名管道):2 r$ k( X# r$ N: w# E
類似于管道,但通過(guò)文件系統(tǒng)實(shí)現(xiàn),任何進(jìn)程都可以通過(guò)路徑訪問(wèn)該管道,實(shí)現(xiàn)雙向通信。信號(hào)(Signal):
+ R3 V4 U7 a: c( o" Z信號(hào)是一種用于進(jìn)程間異步通知的機(jī)制,可以用于進(jìn)程之間的簡(jiǎn)單通信或事件通知,例如 SIGINT(Ctrl+C 發(fā)送的中斷信號(hào))。
2 S; H! L' K1 x) m$ I5 }( D& C' h1 C) n6 `4 H
1.2、System V IPC' K- L! k! _* F, U
System V IPC 是 UNIX 的增強(qiáng)版本,主要包括信號(hào)量、消息隊(duì)列和共享內(nèi)存,適合需要更復(fù)雜的進(jìn)程同步與數(shù)據(jù)共享的場(chǎng)景。
) C: T( m. ]9 \/ o( ?信號(hào)量(Semaphore):
6 F$ d: Q D' a; N2 ?' h用于進(jìn)程間的同步,通常用于控制對(duì)共享資源的訪問(wèn)。- e; ?1 v, O, f0 S @; R2 P# K
信號(hào)量用于防止多個(gè)進(jìn)程同時(shí)訪問(wèn)同一資源,避免資源爭(zhēng)用問(wèn)題。消息隊(duì)列(Message Queue):
5 A( n X& _6 R& s+ D; Z; T- z允許進(jìn)程以消息的形式發(fā)送和接收數(shù)據(jù)。7 P$ G0 e$ g5 v3 z! F
消息隊(duì)列是一種先進(jìn)先出(FIFO)的結(jié)構(gòu),支持不同類型的消息,使得進(jìn)程可以基于消息類型進(jìn)行處理。共享內(nèi)存(Shared Memory):" C* X: N! T: ]2 _7 E+ c
進(jìn)程之間共享同一塊內(nèi)存區(qū)域,允許它們直接讀寫數(shù)據(jù)。
' p# P% B7 `* ~/ ^" F. k這是最有效的 IPC 方式,因?yàn)閿?shù)據(jù)不需要在進(jìn)程之間復(fù)制。
, ~! q) A4 f& M J1 z7 A3 ]' {6 A) H* \8 Q ~) q3 m" p
1.3、POSIX IPC0 u {0 @- J' [7 ]4 ]8 w
POSIX IPC 是 System V IPC 的改進(jìn)版本,旨在解決 System V IPC 在靈活性和可移植性上的一些不足。7 `0 U8 H& p' U
! y' D! b1 E! L
POSIX 標(biāo)準(zhǔn)為 UNIX 系統(tǒng)間的兼容性提供了統(tǒng)一的接口,使得程序可以更方便地在不同的 UNIX 系統(tǒng)間移植。0 P, u5 _! B* x9 H) I+ ~
POSIX 信號(hào)量:; _. Q5 k) p' K' v$ W
與 System V 信號(hào)量類似,用于進(jìn)程同步,但提供了更靈活的接口和更強(qiáng)的實(shí)時(shí)性支持。POSIX 消息隊(duì)列:
$ W: l) `; \: S; r2 {改進(jìn)了 System V 消息隊(duì)列,允許指定消息的優(yōu)先級(jí),并提供更簡(jiǎn)單的接口。POSIX 共享內(nèi)存:
4 ~1 p3 ~8 Z% V6 E與 System V 共享內(nèi)存類似,但具有更好的兼容性和可移植性,接口設(shè)計(jì)更加現(xiàn)代化。8 |- u) w& v# d
; P- X( a7 Y d+ ~, \5 s6 J/ @1.4、套接字(Socket)通信
2 Z" q) w2 Z) Y) N% d4 M+ f K- ?套接字是一種既可以用于本地進(jìn)程間通信,也可以用于網(wǎng)絡(luò)通信的機(jī)制,支持雙向數(shù)據(jù)傳輸。3 z& A6 z! n3 q" Z% ^0 G
4 Y9 I) ]( a# X; `( @$ m" _基于套接字的 IPC 可以實(shí)現(xiàn)非常靈活的通信模式,例如客戶端-服務(wù)器架構(gòu),適合在多臺(tái)計(jì)算機(jī)之間傳遞數(shù)據(jù)。( v& Q' N# N- Z% F- ?% x
' c* Z- r e0 t& J' {+ ~. R/ d
各類 IPC 機(jī)制的對(duì)比和應(yīng)用場(chǎng)景:
$ G! @$ h& l, [* g) R& R9 Q0 s$ ? d) S r4 ~* N4 \
bsbbcgpudkr64088526043.png (106.85 KB, 下載次數(shù): 0)
下載附件
保存到相冊(cè)
bsbbcgpudkr64088526043.png
2024-12-10 21:53 上傳
' W: v. C" N* h9 w, O4 ?, w
: K* U2 P' d' w5 C9 }. A. n: U1 u2
# B& {. p5 R' @5 t5 u管道(Pipe)
2 M9 l6 y* m5 p+ W/ y( r管道是一種半雙工(單向)的通信方式,通常用于父子進(jìn)程之間的通信。一個(gè)進(jìn)程可以向管道寫入數(shù)據(jù),另一個(gè)進(jìn)程從管道讀取數(shù)據(jù)。
& P7 F0 a" U% t7 |
5 H ^2 g; B& t8 C0 l5 zLinux 提供了無(wú)名管道和命名管道兩種類型。
[! o. g5 T1 O6 M: F# ^3 Z無(wú)名管道(Anonymous Pipe):. B% M2 |; ]( F0 C
只能在具有親緣關(guān)系的進(jìn)程間使用,比如父進(jìn)程和子進(jìn)程。命名管道(Named Pipe 或 FIFO):! i& [$ k% d' x8 f! o
通過(guò)文件系統(tǒng)中的路徑來(lái)創(chuàng)建,任意進(jìn)程都可以訪問(wèn)。/ q) v" y1 L5 T+ C
, e0 y2 B& Q. n4 d5 |' N
( r$ k1 I) m1 _" \示例:2 L8 J# j+ I# h0 }% ~
) \6 s) Q6 S* D) Nint main() { int fd[2]; pipe(fd); // 創(chuàng)建無(wú)名管道
3 T; h+ G; p" S 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
: I+ V O4 t4 P& R", buffer); close(fd[0]); } return 0;}' O& l" U, n4 d$ N0 b0 n0 W& U" E
3" K; Q8 z0 W2 H- o. b0 q
消息隊(duì)列(Message Queue)
* h1 }4 ~; n7 J9 l" Q消息隊(duì)列是一種先進(jìn)先出的隊(duì)列,允許進(jìn)程以消息的形式發(fā)送和接收數(shù)據(jù)。
& s4 Y' w* W9 X8 M4 n7 J4 h/ e0 f" ]) O" l& c- K
消息隊(duì)列可以支持多種類型的消息,通過(guò)消息類型實(shí)現(xiàn)多種目的的通信。
% H& ?, x' [4 A2 w. q0 Y k0 T( ^3 u; K2 B0 V
示例:進(jìn)程A可以向隊(duì)列發(fā)送一個(gè)帶有特定類型的消息,而進(jìn)程B可以根據(jù)消息類型進(jìn)行處理。! @! U0 k+ u* T$ K; W6 z
6 G. _( ^! D) Q+ W$ Y+ S5 B. bstruct msgbuf { long mtype; char mtext[100];};9 y+ A' h2 |' l6 h1 Z4 S) X# R
int main() { key_t key = ftok("msgqueue", 65); int msgid = msgget(key, 0666 | IPC_CREAT); struct msgbuf message;4 P" s8 w2 |/ J6 E; L0 a6 n
message.mtype = 1; // 消息類型 snprintf(message.mtext, sizeof(message.mtext), "Hello Message Queue"); msgsnd(msgid, &message, sizeof(message.mtext), 0);
+ A1 J0 e0 [/ R2 [ return 0;}8 d9 |( _6 w' V1 z9 N( E) ^
4
& O$ \ |" V5 C. W6 T1 |共享內(nèi)存(Shared Memory)
* ^! N- Q* w( e7 P共享內(nèi)存是最快的 IPC 機(jī)制之一,因?yàn)檫M(jìn)程之間直接訪問(wèn)同一塊內(nèi)存區(qū)域,而不需要拷貝數(shù)據(jù)。
8 b/ A! j' P( ?* n/ R) E
# l y- Y" e* }$ c9 ^8 D: X通常使用 shmget()、shmat() 和 shmdt() 函數(shù)進(jìn)行共享內(nèi)存的創(chuàng)建和訪問(wèn)。8 V& A/ E0 W! D r) G3 L
2 o+ a8 S: Z6 W* D# G7 w* S* y) N
示例:- A5 @) ` T5 b
4 F5 c5 G& q- H' ~& A& O1 y! M
int main() { key_t key = ftok("shmfile",65); int shmid = shmget(key, 1024, 0666|IPC_CREAT); char *str = (char*) shmat(shmid, (void*)0, 0);
2 c( A1 Z) W; _! X strcpy(str, "Hello Shared Memory");. B& a7 X: [0 s
printf("Data written in memory: %s% C3 w4 H+ z% I! x
", str); shmdt(str);
6 C% o7 Q! N* T9 K- K7 Z* U return 0;}; V9 H# y7 {+ @
51 d ~: J& M4 @, n5 }2 N& l
信號(hào)量(Semaphore)
7 |# ?' `% Q4 C' v. e( s信號(hào)量是一種用于進(jìn)程同步的機(jī)制,通常用于控制多個(gè)進(jìn)程對(duì)共享資源的訪問(wèn)。
- W% \/ W6 A0 [: n( Z# a$ ` a2 A! _6 |
嵌入式系統(tǒng)中,信號(hào)量通常用來(lái)避免多個(gè)進(jìn)程同時(shí)訪問(wèn)同一資源,防止數(shù)據(jù)競(jìng)爭(zhēng)。: K2 W0 _; o. O
9 O! @/ K2 R, I$ j$ B+ E+ f" z示例:信號(hào)量可以通過(guò) semget() 和 semop() 函數(shù)來(lái)操作,用于鎖定或解鎖資源。 k, J2 ]# I7 a" w% g/ r
$ b% K/ ?9 M* ~* q7 s- kint 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操作
6 R# D, I, C4 |# B- z2 d- }2 p* e semop(semid, &sem_lock, 1); // 上鎖 printf("Critical section
) I" L y4 Z& [! r& t3 f+ u' l7 m. {"); semop(semid, &sem_unlock, 1); // 解鎖! C4 m4 x% v" g2 j2 m b1 q
return 0;}
: q- P/ C4 z4 Y6, M, m) K! V6 \9 L% e! i
套接字(Socket)% a w, o4 V5 [' x
套接字不僅支持本地進(jìn)程間通信,還可以用于網(wǎng)絡(luò)通信。
$ T/ |. a6 ?. o
; Y p5 B! U% Q4 w$ s) z基于套接字的 IPC 支持雙向通信,比較靈活,適合嵌入式系統(tǒng)中進(jìn)程之間需要頻繁且復(fù)雜的數(shù)據(jù)交互的情況。
* g6 T" ?( w" F, F6 [0 l5 W
2 o7 h+ r' L' S7 M, l. U$ W示例:
+ Y! v1 t4 t8 [5 ]! K
( g+ c1 J' k8 eint main() { int sv[2]; socketpair(AF_UNIX, SOCK_STREAM, 0, sv);
/ [- u3 [0 L8 i" B* R! y2 Y1 F5 G0 E( a 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: %s+ |( \( U" N( U8 v
", buffer); close(sv[0]); } return 0;}
8 z# x( m- y! T; L( p: n. \71 R8 P+ h t% W2 V( {
信號(hào)(Signal)! s5 ^7 h3 t2 n4 W5 E
信號(hào)是用來(lái)通知進(jìn)程發(fā)生某種事件的機(jī)制。進(jìn)程可以捕獲、忽略或處理信號(hào),典型的信號(hào)包括 SIGINT(中斷信號(hào))和 SIGKILL(殺死進(jìn)程信號(hào))。8 `( _* a: w0 F! x7 j
, T5 s. N+ h8 f( e) q. p/ r
示例:處理 SIGINT 信號(hào)(Ctrl+C)。
, P+ P! q6 l0 K* u; ?9 k; ?1 M5 I/ x6 `# j' \! X
void sigint_handler(int sig) { printf("Caught signal %d' L$ X9 X9 ~/ ~1 |9 d# Q9 K' u0 t, H a
", sig);}1 ], G& a; G, M+ U8 N) r5 q+ v
int main() { signal(SIGINT, sigint_handler); while (1) { printf("Running...6 C& X8 Y6 g2 k1 N4 A. w/ K) h
"); sleep(1); } return 0;}
4 d8 @! U3 L) @% a& j$ K" \進(jìn)程間通信的機(jī)制多種多樣,選擇合適的方式取決于應(yīng)用場(chǎng)景的需求。2 I/ k8 v' `" n) Q& |4 ]1 l0 e. ]6 P
pxe3tci4tfg64088526143.jpg (71.14 KB, 下載次數(shù): 0)
下載附件
保存到相冊(cè)
pxe3tci4tfg64088526143.jpg
2024-12-10 21:53 上傳
5 Y/ M' Y" q0 W8 g' b
qjqlous0j2064088526243.gif (45.46 KB, 下載次數(shù): 0)
下載附件
保存到相冊(cè)
qjqlous0j2064088526243.gif
2024-12-10 21:53 上傳
! x- k$ K2 B+ y7 ~! |+ Q* a點(diǎn)擊閱讀原文,更精彩~ |
|