1.进程间通信
如果一个系统是单进程的,那就无法使用并发能力。进程间通信是实现多进程协同的手段,目的是完成进程间的数据传输、消息通知、同步执行流等。
进程具有独立性! 虚拟空间 + 页表的方式保证了进程的独立性。进程间通信的本质,前提是要进程看到同一块"内存",这个"内存"不隶属那个进程,是进程间共享的!
每个进程的用户地址空间都是独立的,一般而言是不能互相访问的,但内核空间是每个进程都共享的,所以进程之间要通信必须通过内核。
2.管道
$ ps axj | grep mysql
Linux指令中「|
」竖线就是一个管道,它的功能是将前一个命令(ps auxf
)的输出,作为后一个命令(grep mysql
)的输入。可以看出管道传输数据是单向的,即半双工。
从一个进程连接到另一个进程的一个数据流称为一个"管道",它是Unix中最古老的进程间通信的形式。管道分为匿名管道 和 命名管道。
2.1.匿名管道
站在文件描述符角度-深度理解管道
站在内核角度-管道本质
子进程 fork 来复制父进程 fd 文件描述符,让父子进程通过文件看到同一块空间。将资源(数据)放到内存中(缓冲区中)没有必要将数据写到磁盘中,这样能提高效率。
管道读写规则
- 写端快读端慢:管道写满不能再写
- 写端慢读端快:管道没有数据时,读端必须等待
- 写端关闭读端read返回0,标识读到文件结尾
- 读端关闭写端继续写,操作系统会终止写端进程
管道特点
- 管道只能用于具有共同祖先的进程(具有亲缘关系的进程)之间进行通信;通常用于父子进程通信
- 管道通过控制读写端的速度,提供了访问控制
- 管道提供的是面向流式的通信服务,即管道是面向字节流的
- 管道是基于文件的,而文件的生命周期随进程,所以管道的生命周期随进程的
- 管道是单向通信的,是半双工的特殊情况
2.2.命名管道
对于匿名管道,它的通信是具有血缘关系进程间通信。通常通过 fork 来复制父进程 fd 文件描述符,来达到通信的目的。而对于命名管道,它可以在不相关的进程间也能相互通信。因为命令管道,提前创建了一个类型为管道的设备文件,在进程里只要使用这个设备文件,就可以相互通信。
不管是匿名管道还是命名管道,进程写入的数据都是缓存在内核中,另一个进程读取数据时候自然也是从内核中获取,同时通信数据都遵循先进先出原则。
在命令行中使用:
使用命令mkfifo
命名管道:
xiyan@VM-20-5-ubuntu:~/code/namePipe$ mkfifo fifo.ipc
代码中使用:
int mkfifo(const char *filename,mode_t mode);
定义一个路径,服务端创建命名管道,并以读的方式打开对应的路径文件,而客户端以写的方式和服务器打开相同路径下的文件(即:命名管道)