卷二对Unix各种进程间通信(IPC)方法做了介绍。
IPC方法主要有(这里只列出POSIX IPC):
- 管道&FIFO(有名管道)
- 消息队列
- 锁与条件变量
- 信号量
- 共享内存
其中POSIX消息队列实际运用很少,就不在这里讲解了。
IPC的持续性
将IPC的持续性分为3种:
- 随进程,如管道、非共享内存区互斥锁和条件变量
- 随内核,如有名信号量、共享内存
- 随文件
管道&FIFO
管道适合进程进行少量数据的传递。
使用pipe
函数创建管道,然后使用fork
复制进程,子进程/父进程关闭读/写管道,最后使用write/read
进行数据读写。
FIFO是有名管道,可用于无亲缘关系的进程之间进行通信。
如果write
大小小雨PIPE_BUF,则write
操作具有原子性。
锁和条件变量
锁用来控制临界区访问,而条件变量用于等待条件。
条件变量在获取锁后,使用pthread_cond_wait
会释放锁并等待条件满足时被唤醒。
为了防止虚假唤醒,条件变量被唤醒时需要监测条件是否满足123while (!is_condition_satisfied) { pthread_cond_wait(&cond, &mutex);}
线程取消带来的死锁问题
pthread_cond_wait
是线程取消点(cancellation point)。在阻塞在pthread_cond_wait
时线程被取消将导致该线程重新获得锁,必须使用线程清理程序pthread_cleanup_push
,pthread_cleanuppop
将锁释放掉。
信号量
锁可以看作只有0/1的信号量,信号量可以存储一个整形的状态值,可以在多个进程间共享。
共享内存
共享内存是最快的IPC方式。主要函数:
- mmap,映射文件到进程地址空间。可以使用ANON属性避免文件创建。
- munmap, msync
- POSIX共享内存区函数,shm_open等