一、fork的返回值和父子进程基本概念
pid_t fork(void) ;//是一个返回值为pid_t类型的系统调用函数
1、fork 出错 时返回值为 -1
2、fork函数调用一次,返回俩次。在原来的进程(父进程)返回新进程的pid(不可能为0),在新进程(子进程)中返回0;
3、新进程返回原来的数据,用程序计数器来操作,新进程从fork之后开始运行。
4、 fork之后,父子进程是俩个独立的进程,谁先运行由操作系统决定。
二、进程的创建
1、fork是以页为单位来进行复制创建的
2、fork之后,子进程会拷贝父进程的PCB结构,然后对PCB里面的数据做修改。父进程的页表(操作系统为每一个进程维护一个页表)直接拷贝(浅拷贝)给子进程,父子进程共享所有的数据空间。
三、写实拷贝
在linux中,fork()之后父进程会产生一个和父进程完全相同的子进程,但子进程在此后多会采用exec系统调用,出于效率考虑,linux中引入了“写时复制”技术,也就是只有进程空间的各段的内容要发生变化时,才将父进程的内容复制一份给子进程。
在fork之后,父子进程的物理空间相同,虚拟空间不同,也就是说父子进程共用一块物理空间,内核不需复制整个进程的地址空间,父子进程共享一块地址空间。当父子进程任意一个进程试图修改数据时,操作系统就会把将要修改的数据所在的页直接复制出来,以此提高效率。
fork()的实际开销就是复制父进程的页表以及给子进程创建一个进程描述符。在一般情况下,进程创建后都为马上运行一个可执行的文件,这种优化,可以避免拷贝大量根本就不会被使用的数据(地址空间里常常包含数十兆的数据)。由于Unix强调进程快速执行的能力,所以这个优化是很重要的。