目录
[a. 进程间通信,成本可能会稍微高一点(因为进程是具有独立性的)](#a. 进程间通信,成本可能会稍微高一点(因为进程是具有独立性的))
b.进程间通信的前提,是先让不同的进程看到同一份资源(即"一段内存")
[3)demo -- 测试管道接口](#3)demo -- 测试管道接口)
[a. 获取的两个fd](#a. 获取的两个fd)
[b. 读一半、写一半](#b. 读一半、写一半)
[c. 管道的4种情况](#c. 管道的4种情况)
[I、如果管道内部是空的 && write fd没有关闭,读取条件不具备,读进程会被阻塞](#I、如果管道内部是空的 && write fd没有关闭,读取条件不具备,读进程会被阻塞)
[II、管道被写满 && read fd 不读且没有关闭,管道被写满,写进程会被阻塞](#II、管道被写满 && read fd 不读且没有关闭,管道被写满,写进程会被阻塞)
[III、管道一直在读 && 写端关闭了wfd,读端 read 返回值会读到0,表示读到了文件结尾](#III、管道一直在读 && 写端关闭了wfd,读端 read 返回值会读到0,表示读到了文件结尾)
[d. PIPE_BUF](#d. PIPE_BUF)
一、进程为什么要通信
进程也是需要进行某种协同的 ,且所有协同的前提条件 -- 就是通信
a. 数据传输:一个进程需要将它的数据发送给另一个进程
b. 资源共享:多个进程之间共享同样的资源。
c. 通知事件:一个进程需要向另一个或一组进程发送消息,通知它(它们)发生了某种事件(如进程终止 时要通知父进程)。
d. 进程控制:有些进程希望完全控制另一个进程的执行(如Debug进程),此时控制进程希望能够拦截另 一个进程的所有陷入和异常,并能够及时知道它的状态改变。
子进程继承父进程的数据不属于进程间通信,因为一次通信和一直能通信是不一样的!!
且子进程也仅仅是只读
二、进程如何通信
a. 进程间通信,成本可能会稍微高一点(因为进程是具有独立性的)
b.进程间通信的前提,是先让不同的进程看到同一份资源(即"一段内存")
一定是某一个进程先需要通信,让OS创建一个共享资源
OS必须提供很多的系统调用(因为操作系统不能被外部直接使用)
OS创建的共享资源的不同,系统调用接口的不同 --- 进程间通信会有不同的种类!
三、进程通信的常见方式
system V标准 -- 本地通信
a. 消息队列
b. 共享内存
c. 信号量
可不可以直接复用内核代码直接通信呢??
有的 --- 管道!
管道分为两种,即命名管道和匿名管道
1、匿名管道
1)理解匿名管道
一个进程分别以读方式和写方式打开时,它会生成两份struct file结构体,当我们fork一个子进程时,子进程会将父进程的PCB和文件描述符表都拷贝一份,因为 进程是具有独立性的
但是struct file它是和父进程共用的,因为struct file属于文件系统, 进程需要保持独立性, 和文件无关
理解现象:
为什么父子进程会向同一个显示器终端打印数据??
因为指向的是同一个文件缓冲区
进程默认会打开三个标准输出:0 1 2 --- 怎么做到的?因为 所有的进程默认都是bash的子进程 --- 即bash打开了,则所有的进程也就默认打开了,只需要做好约定即可关于 close();
为什么我们的子进程主动close(0/1/2),不影响父进程继续使用显示器文件呢??
因为struct file内部也会存在一个引用计数(内存级的),(当子进程close时,ref_count--) 只有当引用计数为0时(ref_count==0),我们才真正的释放文件资源
2)使用匿名管道
int pipe(int pipefd[2]);
(使用它不需要带文件路径和文件名,所以叫做匿名管道)
该参数为 输出型参数:
把我们对应的 以读方式和以写方式打开的两个文件描述符以数组的方式给带出来
1.如果我们想要双向通信呢??
创建两个管道
2.为什么要单向通信??
为了 让其实现起来简单 --> 只让它进行单向通信(也因此叫做管道)
3.父进程既然要关闭不需要的fd,那为什么曾经还要打开呢??
为了 让子进程继承下去
可以不关闭吗??
可以的,但是建议关了,以 防万一误写、误读
3)demo -- 测试管道接口
a. 获取的两个fd
b. 读一半、写一半
在管道中,不会出现这种情况
c. 管道的4种情况
I、如果管道内部是空的 && write fd没有关闭,读取条件不具备,读进程会被阻塞
--- wait 等待读取条件具备,再写入数据
II、管道被写满 && read fd 不读且没有关闭,管道被写满,写进程会被阻塞
--- 管道被写满,写条件不具备 --- wait 写条件具备(即读取)
III、管道一直在读 && 写端关闭了wfd,读端 read 返回值会读到0,表示读到了文件结尾
IV、rfd直接关闭,wfd一直在进行写入
写端进程会被OS直接使用13号信号关掉,相当于进程出现了异常