父进程和子进程.pdf
在Unix/Linux操作系统中,进程是程序执行的实例。"父进程和子进程"的概念是进程管理的核心之一。当一个进程执行`fork()`系统调用时,它会创建一个与自身内容完全相同的进程,这个新产生的进程称为子进程。在PCB(进程控制块)中,子进程的父进程指针指向父进程。`fork()`操作相当于创建了进程的一个副本,两者拥有独立的地址空间,但是初始时数据是共享的,即子进程在创建时就包含了父进程的所有数据。 然而,这样的简单复制并不实用,通常我们需要通过`exec()`系列系统调用来替换子进程的执行上下文,使其执行新的程序。例如,一个进程正在执行A程序,调用`exec(B)`后,它将停止执行A,转而开始执行B程序,这时父子进程的执行内容就不同了,但父子关系依然保持不变。 在进程生命周期中,父子进程的执行顺序通常是并发的。在`fork()`后,父进程先执行,然后根据调度机制,子进程在下一个时间片中获得CPU执行权。每个进程都有一个父进程,当子进程结束时,会向父进程发送`SIGCHLD`信号。默认情况下,父进程会忽略这个信号,但可以通过捕获这个信号(如使用`wait()`函数)来得知子进程的状态变化,从而处理子进程的退出。 `wait()`函数是父进程用来等待子进程结束的关键工具,它允许父进程接收并处理`SIGCHLD`信号,得知子进程何时结束。在Shell编程中,这一特性尤其重要,因为它使得Shell能够知道命令(子进程)何时完成,从而提示用户输入下一个命令。 在进程管理中,进程组ID的设置也是关键的一环。一个进程只能为它自己或其子进程设置进程组ID,而且一旦子进程调用`exec()`,父进程就不能再改变子进程的进程组ID。守护进程是常驻后台的进程,它们通常由系统在启动时自动激活,如HTTP服务器Apache,其守护进程`httpd`在设置为运行级别的系统中会自动启动。 进程分为交互进程、批处理进程和守护进程三类。守护进程不依赖于终端,持续运行以处理请求。例如,Web服务器在接收到用户请求时,可能会创建多个进程来服务,这就是所谓的并发处理。每个进程都有自己的属性,包括唯一的进程ID(PID)、父进程ID(PPID)、启动用户ID和所属组ID、进程状态(如运行、休眠、僵尸状态)、优先级以及资源占用情况。 在管理Linux进程时,了解父进程和子进程之间的关系至关重要。例如,当需要终止消耗资源过多的进程时,可以使用`kill`命令发送特定信号来结束它们。不过需要注意,杀死子进程并不一定会终止父进程,除非父进程设置为监听子进程的结束并相应地进行操作。因此,理解并掌握这些概念有助于更有效地管理和控制系统的进程,优化系统资源的使用。