管理进程
fork()创建一个新进程、_exit()终止一个进程、exec() 装入一个新程序
当一个系统调用执行以后,进程就在所装入的全新地址空间恢复运行。
调用fork() 的进程是父进程,新进程就是他的子进程,两个进程可以互相通信,在每个进程的数据结构中,包含两个指针,一个指向父进程,另一个指向子进程。
实现fork() ,可以把父进程的数据与代码复制到子进程,但这会很浪费时间。
他需要完成以下任务:
- 为子进程的页表分配页面
- 为子进程的页分配页面
- 初始化子进程的页表
- 把父进程的页复制到子进程对应的页中
Linux引进了(Copy-On-Write)写时复制的技术。
写时复制(copy-on-write)是一种可以推迟甚至避免复制数据的技术。内核此时并不是复制整个进程空间,而是让父进程和子进程共享同一个副本。只有在需要写入的时候,数据才会被复制,从而使父进程、子进程拥有各自的副本。也就是说,资源的复制只有在需要写入的时候才进行,在此之前以只读方式共享。这种技术使得对地址空间中的页的复制被推迟到实际发生写入的时候。有时共享页根本不会被写入,例如,fork()后立即调用exec(),就无需复制父进程的页了。fork()实际开销就是复制父进程的页表以及给子进程创建唯一的PCB。这种优化可以避免复制大量根本就不会使用的数据。
_exit()系统调用中止一个进程,内核对这个系统调用的处理是通过释放进程所拥有的资源,并向父进程发送SIGCHILD信号,来实现的。
僵死进程
wait4()系统调用允许进程等待,直到其中的一个子进程结束,它返回已终止的进程PID
内核在执行这个系统调用时,检查子进程是否已经终止。引入僵死进程的特殊状态是为了表示终止的进程,父进程在执行完wait4()系统调用之前,进程就一直停留在那种状态。系统调用处理程序从进程描述符字段获取有关资源使用的数据,一旦得到数据,就可以释放进程描述符。若在执行时子进程尚未结束,内核就会把该进程设置为等待 状态,直到子进程结束。
waitpid(),允许等待一个特殊的子进程。