|
3rqolratvad64088525943.gif
6 q: k4 _) ]5 Y9 O- d点击上方蓝色字体,关注我们* ^ H! }# g% P7 ~
, M2 \- o2 T8 U1.1、UNIX IPC
% H& r+ S* o3 j; e! S8 y4 K, UUNIX 传统的 IPC 机制包括管道、FIFO 和信号,这些机制最早由 UNIX 系统引入,适用于简单的单机进程间通信。( f+ ~( N- Z y ?; o5 |2 t
管道(Pipe):' d& ]# _: [! y, Y0 s
一种单向、半双工的通信机制,通常用于父子进程间的数据传递。5 [: n$ C& \0 O7 _; X
父进程可以写入数据,子进程可以读取。FIFO(命名管道):; b% D1 ^9 p6 V* z7 K
类似于管道,但通过文件系统实现,任何进程都可以通过路径访问该管道,实现双向通信。信号(Signal):
" i/ H5 a7 y& G/ }信号是一种用于进程间异步通知的机制,可以用于进程之间的简单通信或事件通知,例如 SIGINT(Ctrl+C 发送的中断信号)。
% c& x m6 I9 y, t4 w9 o* O
6 t2 m8 d1 s& J/ e( l1.2、System V IPC* p3 |; w) h* j, V) v$ C
System V IPC 是 UNIX 的增强版本,主要包括信号量、消息队列和共享内存,适合需要更复杂的进程同步与数据共享的场景。 h5 G0 l- X% d* @
信号量(Semaphore):3 A6 A4 e& J. J7 P( m" Y
用于进程间的同步,通常用于控制对共享资源的访问。
; O" l+ T/ k5 `* H9 h0 o# ~信号量用于防止多个进程同时访问同一资源,避免资源争用问题。消息队列(Message Queue): ~7 ~1 t" r' F+ H
允许进程以消息的形式发送和接收数据。
& U; O O+ g( C; N3 G3 \4 ~消息队列是一种先进先出(FIFO)的结构,支持不同类型的消息,使得进程可以基于消息类型进行处理。共享内存(Shared Memory):0 D2 k8 l4 l' e+ d, ~6 n
进程之间共享同一块内存区域,允许它们直接读写数据。0 E1 q( f7 _6 Z" g0 M3 b* `* R( ~
这是最有效的 IPC 方式,因为数据不需要在进程之间复制。
& O8 V- v" x! `0 ^& H: b
9 w J0 D9 g Y3 v% P. b1.3、POSIX IPC
2 L. g S4 k5 l( P- p1 z8 I( B# ?POSIX IPC 是 System V IPC 的改进版本,旨在解决 System V IPC 在灵活性和可移植性上的一些不足。+ R; s1 W" C* ?5 b
7 u: p! A4 G4 P h( n1 T ePOSIX 标准为 UNIX 系统间的兼容性提供了统一的接口,使得程序可以更方便地在不同的 UNIX 系统间移植。! I9 R5 J' U4 a, t0 F
POSIX 信号量:1 r2 F( P& \4 H: _& T. L
与 System V 信号量类似,用于进程同步,但提供了更灵活的接口和更强的实时性支持。POSIX 消息队列:
: `7 P2 N; S7 e# r) f改进了 System V 消息队列,允许指定消息的优先级,并提供更简单的接口。POSIX 共享内存:" z. |, }; a$ F, q# F6 G4 N
与 System V 共享内存类似,但具有更好的兼容性和可移植性,接口设计更加现代化。
" f9 `2 k; t" P3 s* u, t3 i' p: J) r& Z! H& Z3 _
1.4、套接字(Socket)通信
+ [, [# I) A- }+ j0 L套接字是一种既可以用于本地进程间通信,也可以用于网络通信的机制,支持双向数据传输。/ ~8 ?+ a4 E( o" _- O! n& t$ u
' s5 P# w: c6 O- J1 C% S
基于套接字的 IPC 可以实现非常灵活的通信模式,例如客户端-服务器架构,适合在多台计算机之间传递数据。3 r {% G! z5 C1 `
/ S# q/ Y4 J- @各类 IPC 机制的对比和应用场景:( `6 C5 A4 C! G' `
1 i2 L& B- W; u7 \8 Y
bsbbcgpudkr64088526043.png
1 e, s9 z1 v# |& y8 i5 r
7 K0 w( b+ f- H8 k1 Q2' p5 X4 v* H. h/ e; ~, ~9 q2 t
管道(Pipe)
5 V! p# b6 W+ R& e0 Y管道是一种半双工(单向)的通信方式,通常用于父子进程之间的通信。一个进程可以向管道写入数据,另一个进程从管道读取数据。) @' M8 L9 V; {5 P0 D% m: Z# M
$ Z- L/ F7 }$ \" eLinux 提供了无名管道和命名管道两种类型。
# H% L- P/ s! V2 n; X: B" D1 S无名管道(Anonymous Pipe):
_ `+ p' R" d( y4 U8 ^只能在具有亲缘关系的进程间使用,比如父进程和子进程。命名管道(Named Pipe 或 FIFO):; J9 d& @' ~% q6 n$ `* O0 i3 _
通过文件系统中的路径来创建,任意进程都可以访问。
8 M" x" ]# U) L+ A9 z" P" s0 H9 E6 @5 r9 x
( v& u5 j6 `* S
示例:) J4 H0 _4 v: _. n
, {3 z1 z8 a1 rint main() { int fd[2]; pipe(fd); // 创建无名管道
2 }7 X; U4 V7 `: B% R2 n if (fork() == 0) { // 子进程 close(fd[0]); // 关闭读取端 write(fd[1], "Hello, parent!", 15); close(fd[1]); } else { // 父进程 char buffer[20]; close(fd[1]); // 关闭写入端 read(fd[0], buffer, sizeof(buffer)); printf("Received: %s% c" E, L( o" e( |3 U, y" G
", buffer); close(fd[0]); } return 0;}, s+ Y, G7 L( m: Z
36 |3 P8 x6 ?3 P/ ]- G: S- w
消息队列(Message Queue)2 q4 I: _ f" V4 i
消息队列是一种先进先出的队列,允许进程以消息的形式发送和接收数据。
/ _( L, o, `: N I
0 j/ Z* R0 ]* _5 ?8 R& P消息队列可以支持多种类型的消息,通过消息类型实现多种目的的通信。0 ]' T/ K% y2 [/ \
: R6 S; t# G/ U0 a/ |! ?2 G. |
示例:进程A可以向队列发送一个带有特定类型的消息,而进程B可以根据消息类型进行处理。/ w4 G: x" I b% m4 }0 U/ P: r
: o/ O; I( I9 Y6 d5 J
struct msgbuf { long mtype; char mtext[100];};
( r R: M; k( ~/ c1 b _int main() { key_t key = ftok("msgqueue", 65); int msgid = msgget(key, 0666 | IPC_CREAT); struct msgbuf message;
! U% J7 H2 M/ }( h" W9 v7 u message.mtype = 1; // 消息类型 snprintf(message.mtext, sizeof(message.mtext), "Hello Message Queue"); msgsnd(msgid, &message, sizeof(message.mtext), 0);
4 O. S, w2 B7 K return 0;}
& c( N2 S& _! ^# K7 |, d4
8 Q7 Z+ e9 S/ J共享内存(Shared Memory)5 n# u9 P0 v; h5 O( W2 {$ X, [3 V
共享内存是最快的 IPC 机制之一,因为进程之间直接访问同一块内存区域,而不需要拷贝数据。
% F6 p1 I3 x) H" z4 s; S8 M+ U$ U c$ G& I( D
通常使用 shmget()、shmat() 和 shmdt() 函数进行共享内存的创建和访问。
5 t$ @5 q4 n3 |' y
- R/ [" n( ^2 C( n' v$ s示例:$ u) k# I" L8 r* A" l( g' m
9 K7 G6 M9 f' S& y- G
int main() { key_t key = ftok("shmfile",65); int shmid = shmget(key, 1024, 0666|IPC_CREAT); char *str = (char*) shmat(shmid, (void*)0, 0);
6 N; o+ l. D. N) J: Z2 l/ B strcpy(str, "Hello Shared Memory");% _. k! K% d/ D0 E/ f4 x
printf("Data written in memory: %s
5 b( b$ R7 ^ W", str); shmdt(str);
: Z* T& n* {! K3 V7 P return 0;}( @5 u% U! o( K. t, m# d
57 C* O# J" v) J) E
信号量(Semaphore)7 L! O4 r/ |% _8 k3 N
信号量是一种用于进程同步的机制,通常用于控制多个进程对共享资源的访问。; L$ k- V) r9 g+ }5 p0 b
: I+ a) ]% y/ x/ I/ ]7 m嵌入式系统中,信号量通常用来避免多个进程同时访问同一资源,防止数据竞争。
" y# {2 }; Y7 {# U# O0 {
' K1 S( _7 ~) _9 o/ y示例:信号量可以通过 semget() 和 semop() 函数来操作,用于锁定或解锁资源。
t. J2 Y* ^; ^+ d
/ q7 j. S, m8 j m3 Lint 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 J- v' w* c8 N, d0 Z( r
semop(semid, &sem_lock, 1); // 上锁 printf("Critical section) w7 ?1 v$ H3 d9 J! P# Y! u4 [' x
"); semop(semid, &sem_unlock, 1); // 解锁0 N7 q7 }5 e2 }: W& V# d* |
return 0;}1 d5 t; T6 u9 g$ C6 _+ ~
69 h' w) q- e. J8 t+ T
套接字(Socket)
]9 M4 m' Z! n( u! d9 m$ Q z3 r套接字不仅支持本地进程间通信,还可以用于网络通信。4 B5 J5 { }+ ~/ z
9 l p: |+ X- A" T, Q" v
基于套接字的 IPC 支持双向通信,比较灵活,适合嵌入式系统中进程之间需要频繁且复杂的数据交互的情况。
; C2 K, s6 A- {2 ?) R" |8 E1 d6 a: u8 m& z) w
示例:/ ^4 k, k+ Z; N9 W
1 |& n" J4 e. x* Fint main() { int sv[2]; socketpair(AF_UNIX, SOCK_STREAM, 0, sv);; \/ Y6 |' O+ |( `4 T; w
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
' C# I% D- q- a" Z( [! s", buffer); close(sv[0]); } return 0;}
" C- N& ~& X4 h" E$ k71 z$ W9 v: \ ^ K3 @9 w% V7 m8 r( }& u
信号(Signal)
! z8 [' A3 T( B8 j7 T0 S; {' k信号是用来通知进程发生某种事件的机制。进程可以捕获、忽略或处理信号,典型的信号包括 SIGINT(中断信号)和 SIGKILL(杀死进程信号)。/ f9 K$ }# h% X6 R* N& _; q6 G0 T
, g# h& X+ a, g& ^8 Y$ }0 H( Q
示例:处理 SIGINT 信号(Ctrl+C)。5 v! a Y. Q2 ]8 S
) Y0 s% S2 V/ x( K" kvoid sigint_handler(int sig) { printf("Caught signal %d% p' o2 @% z, O$ v* H8 J1 i
", sig);}$ g/ D. e' E/ {/ D! s! X& I- p
int main() { signal(SIGINT, sigint_handler); while (1) { printf("Running...
/ k, ~* q. N* r e"); sleep(1); } return 0;}
. C- c" f y1 X( _进程间通信的机制多种多样,选择合适的方式取决于应用场景的需求。, f* \) E: _8 p: p; d
pxe3tci4tfg64088526143.jpg
n. S" s% ~1 n R# M( L
qjqlous0j2064088526243.gif
! m! z% A. f' G点击阅读原文,更精彩~ |
|