进程间通信:
对于每个进程来说,都有一份属于它自己的内存资源,并且独占这份内存资源。而进程间通信的目的就是让不同的进程间能看到一份公共的资源。所有交换的数据必须通过内核来传递,在内核中开辟一块缓冲区,通过这块缓冲区来实现数据的传递,内核提供的这种机制称为进程间通信。
进程间通信的方法:1、管道 2、信号量 3、消息队列 4、共享内存 5、套接字(只有套接字可以跨主机)
匿名管道:pipe(父子间进程的通信方式)
- 头文件:#include <unsitd.h>
- 函数:int pipe(int fd[2]);
- 参数:fd:文件描述符数组,其中fd[0]指向读端,fd[1]指向写端。可以通过read(fd[0])或write(fd[1])操作。
- 返回值:成功返回0,失败返回-1。
- 意义:调用这个函数,会在内核中开辟出一块缓冲区来进行进程间的通信,这块缓冲区称之为管道,有一个读端和一个写端。
具体步骤:
1、父进程创建管道
2、fork创建子进程,子进程也会得到这两个文件描述符,指向同一管道
3、父进程关闭读端(fd[0]),子进程关闭写端(fd[1])。这样父进程就可以往管道写入,子进程可以从子进程读取。
当进程结束,管道也会自动消失。
代码实现:
有名管道:fifo
- 函数:int mkfifo(const char *filename,mode_t mode);//在程序里创建调用函数
- 命令:mkfifo fifo(管道名)//在命令行直接创建
- 参数:文件名和权限
- 特点:不管是否写入数据,大小均为0,直接在内存中写入。没有数据会阻塞。
大体思路与匿名管道一致。这里只展示代码。
总结:
-
管道是半双工方式(一个读,一个写),但管道分不清内容是谁写的,所以一般固定传递方向。
-
管道为空,read阻塞 管道满,write阻塞。
-
进程退出,管道释放,管道的生命周期随进程。
-
管道的实现依赖于文件系统。管道是内存上的特殊文件。
-
管道的大小一般系统将其限制在最大长度为4096字节的小型文件。
区分:
-
无名管道pipe()只能在父子进程中使用;有名管道可以在任意两个进程中使用
-
无名管道:
1、如果写端关闭,读端read返回0
2、如果读端关闭,写异常,发送信号(write -> SIGPIPE),系统默认关闭写端。
-
无名管道:优点:简单方便;缺点:1)局限于单向通信2)只能创建在它的进程以及其有亲缘关系的进程之间;3)缓冲
区有限;
有名管道:优点:可以实现任意关系的进程间的通信;缺点:1)长期存于系统中,使用不当容易出错;2)缓冲区有限