fork 函数


       fork是由Linux内核提供的用于创建子进程的函数。理解其关键在于是一次调用两次返回,但两次返回是在不同的地址空间。

0 返回值

       对于父进程,其返回的是子进程的ID,而子进程返回的是0,(注意并不是父进程的ID)。原因在于,每个进程控制块数据结构中记录了两个ID,自身ID和父进程ID,显然,对于子进程而言,没有必要知道父进程ID,因为在fork后就记录在进程控制块中。但相反,对于父进程而言,是无法知晓的,因此有必要知道子进程ID。

1 孤儿进程

       简单说就是当父进程退出后,子进程仍然运行。那么该子进程就称为孤儿进程,体现在“孤儿子进程getppid()返回1”,即当父进程退出后,子进程托付给1号进程即init进程管理,其父进程变为1进程。

2 僵尸进程

       与孤儿进程对应,即子进程退出,而父进程没有退出。那么子进程就处于僵尸状态,defunt。根本原因在于,子进程退出后需要等待父进程查询,且回收申请的资源,如不回收则一直处于僵尸状态,一直占有着资源,不释放,造成资源的浪费(最明显的就是有限的PID号)。


解决办法:利用信号。子进程退出时,会向父进程发SIGCHILD信号,只要父进程处理该信号,即可完成资源回收的工作。

  1 

void SignalCHLDProcess(int signo)

  2 

{  

  3 

    pid_t pid;

  4 

    int stat;

  5 

    while((pid=waitpid(-1,&stat,WNOHANG))>0){

  6 

        printf("child dead\n");

  7 

    }

  8 

    return ;

  9 

}

 10 

 

 11 

int main(int argc, char* argv[])

 12 

{  

 13 

    pid_t pid;

 14 

    signal(SIGCHLD, SignalCHLDProcess);

 15 

    pid = fork();

 16 

    if(pid == 0){

 17 

        printf("child process\n");

 18 

    }

 19 

    else if(pid > 0){

 20 

        printf("parent process\n");

 21 

        sleep(100);

 22 

    }

 23 

    else{

 24 

        ERR_EXIT("fork");

 25 

    }

 26 

}

       需要说明的是回收资源的语句是用while((pid=waitpid(-1,&stat,WNOHANG))>0),理解这句话很关键。

3 waitpid

       首先,解释为什么使用while循环。假设父进程创建了5个子进程,且基本在同一时间退出,向父进程发送SIGCHLD信号,由于信号是非实时的,因此,系统只会保留一个。父进程进入处理函数,并且回收,此时如果没有while就直接退出了。

其次,-1是表示等待任意一个进程,无论是不是该进程组。而如果该参数大于0为pid,那么表示只等待ID号为pid的子进程,如果参数等于0,表示等待同一进程组的任意进程。如果小于0,那么表示等待一个指定进程组的任何子进程,这个进程组的ID等于PID的绝对值。

然后,WNOHANG的意义在于,不阻塞式回收。此时的返回规则是:如果有子进程,但是没有结束,那么返回0,相反如果有僵尸进程,那么就会返回子进程PID。如果没有WNOHANG选项,则会一直阻塞。试想,如果只退出一个子进程,那么接收完该信号后,回到while循环,此时若没有WNOHANG那么一直阻塞。

最后,使用waitpid而不是wait的原因在于,wait就是阻塞式等待任一进程退出,没错,与waitpid(-1,&stat,0);效果是一样的。因此,如果使用while则会一直阻塞父进程,而如果使用if +wait会导致信号丢失。(见“为什么使用while”)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值