Skip to content

Latest commit

 

History

History
74 lines (41 loc) · 3.39 KB

chapter7.md

File metadata and controls

74 lines (41 loc) · 3.39 KB

进程间通信与IO重定向

让不同进程之间可以通信,组合一起运行。

一个进程的输出作为另一个进程的输入。

基于父子进程之间的通信机制 管道。

键盘和屏幕是标准输入输出。管道是特殊的输入输出。

把这三种输入输出都统一在文件这个抽象中。

扩展进程中的文件的概念,不仅是磁盘上的数据,还有外设、管道等物理和虚拟资源

进程如何知道要通信了? -> 通知机制,信号量

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

处理信号保证三个条件:

  1. 接收到了这个信号
  2. 没有被全局屏蔽
  3. 没有被当前正在处理的信号屏蔽