进程间通信的目的:
数据传输:一个进程需要将它的数据发送给另一个进程
资源共享:对个进程之间共享同样的资源
通知事件:一个进程需要向另一个或一组进程发送消息,通知它们发生了什么事件
进程控制:有些进程希望完全控制另一个进程的执行(如:Debug进程)
进程间通信的发展:
管道:
System V进程间通信:
POSIX进程间通信:
进程间通信的分类:
管道:
我们把从一个进程连接到另一个进程的一个数据流称为一个“管道”,管道是Unix中最古老的进程间通信的方式。
- 匿名管道:
函数原型:
int pipe(int fd[2]);
参数说明:
fd:文件描述符数组,fd[0]表示读端,fd[1]表示写端
返回值:成功返回0,失败返回错误代码。
图解:
举一个例子:从键盘读取数据,写入管道,读取管道,写到屏幕。
管道读写规则:
当没有数据可读时:
- read调用阻塞,即进程暂停执行,一直等到有数据来到为止,read调用返回-1,errno值为EAGAIN
当管道满的时候:
- write调用阻塞,直到有进程读走数据,调用返回-1,errno值为EAGAIN。
如果所有管道写端对应的文件描述符被关闭,则read返回0
如果所有管道读端对应的文件描述符被关闭,则write操作会产生信号SIGIPE,进而可能导致write进程退出。
当要写入的数据量不大于PIPE_BUF时,Linux将保证写入的原子性
当要写入的数据量大于PIPE_BUF时,Linux将不再保证写入的原子性
管道特点:
只能用于具有共同祖先的进程(具有亲缘关系的进程)之间进行通信。比如,一个管道由一个进程创建,然后该进程调用fork,此后父、子进程之间就可以应用该管道。
管道提供流式服务
进程退出,管道释放,所以管道的生命周期随进程。
内核会对管道操作进行同步与互斥