Unix进程间通信方式
1.早期UNIX进程间通信方式:
- 无名管道(pipe)
- 有名管道(fifo)
- 信号(signal)
2.System V IPC:
- 共享内存(share memory)
- 消息队列(message queue)
- 信号灯集(semaphore set)
3.可用于本地间通信也可用于不同主机直接通过网络通信:
- 套接字(socket)
无名管道:
进程不像线程通信可以通过全局的变量来实现,进程的资源空间都是独立私有的,没有公共可访问的资源,所以要想实现进程接的数据交换就必须通过内核提供的通信机制来完成。
- 最简单的一种内核通信机制:无名管道

无名管道的特点
- 只能用于具有亲缘关系的进程之间通信,亲缘关系:父子进程、父孙进程等同属于一个进程组的进程。
- 单工的通信模式,具有固定的读端和写端。一个进程只能读管道或者写管道,不能读完管道后面又去写管道。
- 无名管道创建时会返回两个文件描述符,分别用于读写管道。所以可以看出无名管道底层通过文件io来进行数据交互。
- 无名管道只能通过自己创建或从父进程继承得到。
为什么无名管道只能用于有亲缘关系的进程间通信?
因为无名管道创建的时候创建的两个文件是仅仅存在于内存中的,这两个文件对文件系统不可见,也就没有文件路径。这两个文件只能通过文件描述符访问,父进程创建好后子进程可以通过继承的方式继承打开的普通文件和无名管道,而其它进程无法得到这个无名管道的文件描述符。
无名管道的创建
1 |
|
无名管道的单向性:
一个进程只能读或者写管道,如果要实现进程之间双向通信就需要使用两个无名管道实现。
使用的时候要约定好,哪个进程读管道(访问pfd[0])哪个进程写管道(访问pfd[1])。

无名管道 - 示例:
- 子进程1和子进程2分别往管道中写入字符串,父进程读管道内容并打印。
- 注意父进程必须线创建无名管道,创建好管道后再创建子进程这样子进程才能把无名管道继承过去。
代码:
1 |
|
无名管道返回的文件和普通文件的区别
- 无名管道文件里面的数据读完就会自动清除。
- 无名管道文件不支持文件读写定位fseek()、lseek()。
无名管道的读写特性
读无名管道
1.写端存在:至少有一个进程绑定了此管道的写操作
- 有数据
1.管道中数据大于进程要读的数据 : 读管道成功,read()函数返回进程要读的数据字节数。
2.管道中数据小于进程要读的数据 : 读管道成功,read()函数返回管道中的所有数据字节数。
- 没有数据
进程读阻塞,直到其它进程向管道写入数据,该进程被唤醒。
2.写端不存在:无进程绑定写管道操作
- 有数据
返回管道中数据,和写端存在处理一样。
- 没有数据
read()立刻返回0,和读普通文件一样,读到文件末尾没数据了就会返回0。
一个进程在通过一个管道发数据的时候,如果数据全部发完了就关闭管道写端,这样通过读管道接收数据的进程就可以通过read()返回值为0判断数据已经全部接收完毕。
写无名管道
1.读端存在:至少有一个进程绑定了此管道的读操作
- 有空间(存在于内存)
write返回实际写入的字节数
不保证原子操作:就是一次数据写入可能会被分成几段分段写入,每次有多少写多少,直到数据全部被写完。
- 无空间
管道空间小于要写入的数据大小:不保证原子操作方式写入。
有多少空间就写多少内容然后进入阻塞,如果有进程从管道读了一些数据,空出一部分空间,写管道进程唤醒继续上次写数据,如果这次还没有写完,写管道进程又进入阻塞,直到要写的数据全部被写完为止才返回write()函数。
示例1 - 写管道测试系统创建的管道默认大小:
代码:
1 |
|
运行结果:
1 | .... |
2.读端不存在:无进程绑定读管道操作
- 有空间
- 无空间
系统不允许写一个不存在读端的管道,写管道的进程会被系统异常停止(被信号结束),这种情况叫管道断裂,因为管道没有读端,向管道写数据是没有意义的。
示例2 - 写管道测试系统进程因管道断裂而退出:
代码:
1 |
|
运行结果:
父进程回收到子进程的程序退出码是13也就是SIGPIPE,进程被信号结束原因是管道断裂。












