Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1950144
  • 博文数量: 77
  • 博客积分: 2175
  • 博客等级: 大尉
  • 技术积分: 2491
  • 用 户 组: 普通用户
  • 注册时间: 2010-04-20 20:49
个人简介

欢迎光临我的博客

文章分类

全部博文(77)

文章存档

2023年(1)

2018年(4)

2017年(1)

2016年(2)

2015年(2)

2013年(5)

2012年(29)

2010年(33)

分类: 系统运维

2010-05-24 21:25:59

章标题(黑体小二号字,居中)

我们知道,UNIX用fork创建子进程。如果在子进程退出后,父进程没有调用wait等待接收它,那么该子进程将会成为“僵尸进程”,直到父进程退出为止。为避免这种情况的出现,父进程代码一般这样写:


void main()

{

     int pid = fork();

     int status;


     if(pid == 0)

     {

       execl(program, args, 0);

       return;

     }

     wait(&status); //接收子进程退出


     逻辑处理

}



但这样有一个问题,在子进程退出前,wait调用不会返回,这样父进程就被阻塞而不能继续执行“逻辑处理”。当然我们可以颠倒wait调用和逻辑处理的顺序如下:

逻辑处理

wait(&status); //接收子进程退出

但这样的问题是如果逻辑处理时间过长而子进程早已退出,那么父进程接收子进程就会被大大推迟。极端情况下,如果父进程的逻辑处理永远不会结束(比如在无限循环中处理用户输入的按键),则子进程将永远成为“僵尸进程”。

除了使用Linux新提供的waitpid进行非阻塞等待外。对于这种情况,还有两种处理方法避免父进程阻塞等待。

方法1:子进程退出前,向父进程发送特定的信号,父进程在信号处理函数中调用wait



#define SIG_USER 14

void SigUserProc()

{

     int status;

     wait(&status); //接收子进程退出


}


void main()

{

     int pid, ppid;

     int status;

     signal(SIG_USER, SigUserProc);

     pid = fork();

     ppid = getpid();

     if(pid == 0)

     {

         execl(program, args, 0);

         kill(ppid, SIG_USER);

         return;

     }

     逻辑处理;

}


方法2:创建一个“孙”进程来执行program



void main()

{

     int pid;

     int status;

     pid = fork();

     if(pid == 0)

     {

         if(fork() == 0)

        {

            execl(program, args, 0);

            exit(0);

        }

        exit(0);

     }

     wait(&status);

     逻辑处理;

}


子进程在创建后,马上再次创建子进程(也就是父进程的“孙”进程)来执行program

而自己立即退出。这样父进程的wait调用就可以很快返回,从而继续逻辑处理。而“孙”进程由于子进程的退出而被托管给1init进程。init进程会循环调用wait来接收子进程。


《返璞归真--UNIX技术内幕》在全国各大书店及网城均有销售:
                         
                       

阅读(15807) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~