进程间通信:
进程不是孤立的,不同的进程需要进行信息的交互和状态的传递等,因此需要进程间通信。
每个进程各自有不同的进程地址空间,所有进程之间要交换数据必须通过内核,在内核中开辟一块缓冲区,进程1把数据从用户空间拷到内核缓冲区,进程2再从内核缓冲区读走数据,内核提供的这种机制就是进程间通信(IPC),管道是最基本的IPC机制
进程间通信目的:
数据传输:一个进程需要将它的数据发送给另一个进程
资源共享:多个进程之间共享同样的资源。
通知事件:一个进程需要向另一个或一组进程发送消息,通知它(它们)发生了某种事件(如进程终止时要通知父进程)。
进程控制:有些进程希望完全控制另一个进程的执行(如Debug进程),此时控制进程希望能够拦截另一个进程的所有陷入和异常,并能够及时知道它的状态改变
管道:
匿名管道:具有亲缘关系(父子进程),匿名管道无法被其他进程找到,也只能通过子进程复制父进程,两者访问同一份管道。
#include <unistd.h>int pipe(int fd[2])fd:文件描述符fd[0]:表示读端fd[1]:表示写端
常见读写行为:
- 如果管道的写端文件描述符都关闭(写端引用计数为0)如果还有读,则read返回0。
- 写端还有在写的,当管道中的内容被读完以后,read进行阻塞,等待内容。
- 如果读端全都关闭,如果还有写入,进程收到信号(SIGPIPE),导致进程异常终止。也可以对SIGPIPE信号实施捕捉,不终止进程。
读端还有再读的,写满以后,write进行阻塞,有空位再写入。
管道特点:
只能用于
具有共同祖先的进程(具有亲缘关系的进程)之间进行通信,一个管道由一个进程创建,然后该进程调用fork,此后父、子进程之间就可应用该管道。- 管道提供
流式服务 - 一般而言,
进程退出,管道释放,所以管道的生命周期随进程 - 一般而言,内核会对管道操作进行
同步与互斥 - 管道是
半双工的,数据只能向一个方向流动;需要双方通信时,需要建立起两个管道
命名管道(FIFO)
打破了匿名管道只能在有血缘关系的进程间的通信,命名管道之所以可以实现进程间通信在于通过同一个路径名而看到同一份资源
可以使用open()和close()函数打开和关闭命名管道。
#include <sys/tyoes.h>#include <sys/stat.h>int mkfifo(const char* pathname, mode_t mode);
