让不同进程之间可以通信,组合一起运行。
一个进程的输出作为另一个进程的输入。
基于父子进程之间的通信机制 管道。
键盘和屏幕是标准输入输出。管道是特殊的输入输出。
把这三种输入输出都统一在文件这个抽象中。
扩展进程中的文件的概念,不仅是磁盘上的数据,还有外设、管道等物理和虚拟资源
进程如何知道要通信了? -> 通知机制,信号量
IO重定向是啥? -> 允许用户把输出发送到控制台之外的地方
大概过程:某个app执行之前,dad对son的某个fd进行替换。比如输出,dad创建son之前打开一个文件A,fork子进程,子进程把stdout的fd关闭,再复制A的fd到stdout的位置,再关闭A的fd。这样stdout实际上就指向A了。
一切皆是文件
把IO资源按文件来管理:
- 键盘:输入,可以从键盘这个文件中读出一系列字节序列
- 屏幕设别:输出,可以写入
- 串口设备:可读可写。比如qemu模拟的串口设备,可以通过特定的命令行进行输入输出。
对于标准输入输出实现file trait。
当进程创建,默认打开0stdin,1stdout,2stderror。所以此时fd table 0-2已经被占用了。
至此,对文件的读写的系统调用sys_read,sys_write可以直接对stdio进行操作。
用来把不同进程的输入输出对接起来。有读写两端。对应不同的文件描述符。队头0读,队尾1写。
是一个有一定缓冲区大小的字节队列。
读写两端都被关闭后,需要调用close回收资源。
在程序中,单个管道,必须保证一读一写。双向通信,必须创建两个管道。
sys_pipe:为当前进程,开一个管道(是两个Pipe,一个Pipe是一个端),实际上先把pipe文件放到描述符表,再把读和写的fd按顺序填入输入参数中。管道Pipe本身是个缓冲区加上可读可写的控制,这个缓冲区是个数组,有头尾的索引变量,所以可以循环使用。
tips:还有一个write end,保存写端的一个弱引用计数,可以用来确认写端是不是都关闭了。过程:写端的pipefile里面有一个指向自己的weak引用,而进程的描述符表中放的是arc引用,当进程使用close把arc引用都释放了以后,weak无法升级成强引用,所以可以用weak升级失败来判断此时还有没有进程要用这个pipe,如果没有,等数据都被读取完了就可以释放资源了。
整个过程:分配一个缓冲区,分别包装成写端/读端的pipe file,放到fd table中。然后还要把对应的fd(索引)返回,相当于还执行了一个open操作,返回了fd。
进程间通信,收到特定事件时应该及时响应工作。信号是一种软中断。发出信号的时候会指定pid,即需要谁来响应(与谁通信)
发送方:进程/内核
接收方:进程
- 忽略
- 捕获 sigaction系统调用
- 终止
收到信号,需要在用户态进行处理,但此时已经属于另一个控制流而不是app原来的任务,解决完信号需要恢复之前trapcx再回到用户态。
处理SignalAction的包装
- handler:处理入口地址
- mask:处理过程中屏蔽哪些signal
处理信号保证三个条件:
- 接收到了这个信号
- 没有被全局屏蔽
- 没有被当前正在处理的信号屏蔽