一、fork与文件IO
fork()创建子进程的时候,子进程会继承父进程的代码和数据(还包含下图中的内容)
代码和数据:代码是共享的,不可更改;数据等需要变动时发生写时拷贝
进程控制块:凡是进程都会有,子进程的PCB以父进程为模板
地址空间:子进程也会有一份,和父进程有一样
页表:子进程也会有一份,数据发生变化时,由于发生了写时拷贝,映射到物理内存的地址会变化
struct files:子进程也可能会打开文件,为了管理文件就需要 fd_array[ ],内容和父进程一样
注意:文件结构体struct FILE 是不会被拷贝的,一个文件对应一个struct FILE,如果struct FILE被拷贝,那么就变成每创建一个进程,文件就会被拷贝一份
一个进程为什么能正常打印、正常读取输入的内容??
继承自父进程,也就是bash,因为bash和显示器文件stdout、键盘输入文件stdin建立起了联系,子进程会继承这种联系,所以子进程能够打印内容到显示器
二、fork与文件缓冲区
每一个文件都有自己的C缓冲区,fork在执行以后,会对缓冲区的内容发生写时拷贝
下面我们就来验证这个说法
上述的代码流程如下
(1) printf原本要将内容输出到stdout,但是发生了重定向,最终输出到了log.txt的缓冲区,而且从行缓冲变成了全缓冲,导致缓冲区的内容不会立马刷新到内核缓冲区
(2) 然后运行fork函数,fork函数会对缓冲区的内容发生写时拷贝,退出以后,子进程也会刷新自己缓冲区的内容
可以认为前三句是父进程退出进程以后,刷新缓冲区引起的
后三句是子进程退出进程以后,刷新缓冲区引起的