《深入理解计算机系统》第八章 (三)回收子进程

原创 2013年12月03日 11:33:05

进程总是处在下面三种状态的一种:

(1)运行(2)停止(3)终止。 

进程终止的原因:

(1)收到一个默认行为是终止进程的信号    (2)从主程序中返回    (3)调用exit函数

一个终止了但是没有被回收的进程成为僵死进程。进程一般是通过父进程进行回收,如果父进程没有回收它的僵死的子进程就终止了,那么内核就安排init进程来回收它们。init进程的PID为1,并且实在系统初始化的时候由内核创建的。僵死进程虽然没有运行,但是依然消耗系统的存储器资源,父进程回收已终止的子进程是,内核将子进程的退出状态传递给父进程,然后抛弃已经终止的进程。

父进程通过调用waitpid函数来等待它的子进程终止或者停止。每个waitpid函数对应一个等待集合。

 #include <sys/types.h>
 #include <sys/wait.h>

pid_t waitpid(pid_t pid, int *status, int options);


如果pid>0,等待集合就是一个单独的子进程,它的进程ID等于pid,

如果pid=-1,等待集合就是由父进程所有的子进程组成。


option默认为0,决定waitpid的操作,默认情况下,waitpid挂起调用进程的执行,直到它的等待集合中的一个子进程终止。waitpid返回已经终止的子进程的PID,并将这个已终止的子进程从系统中去除。


如果staus非空,则waitpid会在参数status中放上关于导致返回的子进程的状态信息。可以通过如下的几个宏定义,判断status的状态信息。

(1)WIFEXITED(status):如果子进程通过调用exit或者返回正常终止,则返回真

(2)WEXITSTATUS(status):返回一个正常终止的子进程的退出状态

(3)WIFSIGNALED(status):如果子进程接收到一个默认行为是终止进程的信号而终止的,则返回真

(4)WTERMSIG(status):如果子进程是因为信号的原因终止,则返回信号的编号

(5)WIFSTOPPED(status):如果引起返回的子进程当前是被停止的,则返回真

(6)WSTOPSIG(status):返回引起子进程终止的信号的数量


错误条件:

如果调用进程没有子进程,则waitpid返回-1,并且设置errno为ECHILD

如果waitpid函数被一个信号中断,则返回-1,并设置errno为EINTR


例城:

#include<stdio.h>
#include<sys/types.h>
#include<unistd.h>
#include<sys/wait.h>
#include<stdlib.h>
#include<errno.h>    /**errno定义在errno.h中  */
#include<string.h>   /**strerror定义在string.h中  */
#define N 2
int main()
{
    int status, i;
    pid_t pid[N],retpid;

    for(i=0;i<N;i++)
    {
        if((pid[i]=fork())==0)
        {
            exit(100+i);
        }
    }

    i = 0;
    while((retpid=waitpid(pid[i++],&status,0))>0)
    {
        if(WIFEXITED(status))
        {
            printf("child %d terminated normally with exit status=%d\n",retpid,WEXITSTATUS(status));
        }
        else
        {
            printf("child %d terminated abnormally\n",retpid);
        }
    }

    if(errno != ECHILD)
    {
        fprintf(stderr,"fork error :%s\n",strerror(errno));
    }
        exit(0);
    
}


运行结果:

child 4423 terminated normally with exit status=100
child 4424 terminated normally with exit status=101


操作系统 - 程序不会按照特定的顺序回收子进程

eg1: // waitpid1.c // 2015-08-26 Lucifer Zhang // Using the waitpid function to reap zombie chil...

《深入理解计算机系统》第八章 (四)信号

信号是软件层面上的异常 (一)Linux信号 可以通过man 7 signal 查看Linux提供的标准信号。其中描述的信号的编号在不同的处理器体系结构的差异有所不同。 (二)信号传送的步骤 传送一个...

深入理解计算机系统(第二版) 家庭作业 第八章

8.9 进程对 是否并发 AB No AC Yes AD Yes ...

《深入理解计算机系统》第八章 (二)程序的加载与运行

/* $begin shellmain */ #include "csapp.h" #define MAXARGS   128 /* function prototypes */ void eval...

阅读深入理解计算机系统(二)--------------- 进程控制

1.     进程控制 每个进程都有一个唯一的正数进程ID,getpid()函数可以获得调用者的进程ID。 a.     fork()函数: 创建一个新的运行子进程,新创建的子进程几乎但不完全与父进程...

《深入理解计算机系统》笔记(五)并发、多进程和多线程【Final】

该书中第11章是写web服务器的搭建,无奈对web还比较陌生。还没有搞明白。     这些所谓的并发,其实都是操作系统做的事情,比如,多进程是操作系统fork函数实现的、I/O多路复用需要内核挂起进程...
  • hherima
  • hherima
  • 2013年05月29日 14:05
  • 2748

《深入理解计算机系统》笔记(四)虚拟存储器,malloc,垃圾回收【插图】

概述         ●我们电脑上运行的程序都是使用虚拟存储,跟物理内存根本不搭边。         ●既然虚拟内存是在磁盘上的,为什么它又运行这么好,并没有感觉卡顿?这要感谢程序的局部性!     ...
  • hherima
  • hherima
  • 2013年05月24日 17:49
  • 3890

深入理解计算机系统(三)之程序的机器级表示

在一些应用中,程序员必须用汇编代码来访问机器的低级特性。一种方法是:整个函数都用汇编代码来写,然后在链接阶段与C语言函数结合起来。 第二种方法是,在C语言程序中直接利用GCC对嵌入汇编代码支持。 I...

阅读深入理解计算机系统(三)--------------- 虚拟存储器

一、碎片现象:造成堆利用率低的主要原因是一种碎片现象。         内部碎片:已分配块比有效载荷大时发生的。         外部碎片:是当空闲存储器合计起来满足分配请求,但是没有一个单独的空...

《深入理解计算机系统》笔记(三)链接知识【附图】

概述         ●该章节主要讲解的是ELF文件的结构。             ●静态库的概念         ●动态库(又叫共享库)的概念,一般用于操作系统,普通应用程序作用不大。    ...
  • hherima
  • hherima
  • 2013年05月23日 16:19
  • 3423
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:《深入理解计算机系统》第八章 (三)回收子进程
举报原因:
原因补充:

(最多只允许输入30个字)