for FORK

pid_t pid = fork();

1. fork 函数返回两次, >0 表示父进程,返回值为子进程ID; =0 表示子进程。

 
  
if ( ( pid = fork() ) < 0 ){
// error
}
else if ( pid == 0 ){
// child
}
else {
// parent
}

 2. 父进程必须要回收子进程,这时必须用wait/waitpid。不然当子进程结束后,
   它会变成僵死进程。用 "ps -ef" 命令查看,可看到起状态为<defunct>。
   所所以,在fork()之后,我们一般是执行:
   waitpid( pid, NULL, 0 );
   参数1: pid表示到等待的子进程ID
   参数2: NULL表示对子进程的结束状态不在意。
   参数3: 控制选项
  

 
  
if ( ( pid = fork() ) < 0 ){
// error
}
else if ( pid == 0 ){
// child
...
}
else {
waitpid( pid, NULL,
0 ); // 用于等待子进程结束.
}

 3.  问题提出
 在调用waitpid后,父进程被阻塞,将不能执行其他的任务,这在监听程序中是
 不允许的。所以,必须要能回收掉子进程,并且能不被阻塞,要解决这个问题,
 我们可以fork两次,让子进程被init进程托管。

ContractedBlock.gif ExpandedBlockStart.gif 代码
 
   
if ( ( pid = fork() ) < 0 ){
// error
}
else if ( pid == 0 ){
// first child exit !
if ( fork() > 0 ){
exit(
0 );
}
else {
// second child...
}
}
else {
waitpid( pid, NULL,
0 );
// 因为第一个子进程马上退出,所以waitpid在等到其结束时马上返回,第二
// 个子进程将被init进程托管!
}

 4.  问题提升
 我们让子进程被init进程托管,也就等于对它放弃了控制权,没办法知道它什么时
 候结束的,以及结束的状态是什么。所以,为了父进程不被阻塞,并且能够及时的
 回收掉子进程。这时,用信号是一个不错的选择。

ContractedBlock.gif ExpandedBlockStart.gif 代码
 
   

int chld_count = 0 ;

void sigchd_exit( int signo)
{
if ( waitpid( - 1 , NULL, WNOHANG) > 0 ) chld_count -- ;

printf(
" child count: %d\n " , chld_count );
}

void set_sigchd()
{
signal(SIGCHLD, sigchd_exit);
// 子程序退出的信号
signal(SIGINT, sigchd_exit); // Ctrl+C
signal(SIGTERM, sigchd_exit);
}

// .....
set_sigchd()
if ( ( pid = fork() ) < 0 ){
// error
}
else if ( pid == 0 ){
// child
...
}
else {
chld_count
++ ;
}

 这时,在程序开始时设置信号处理函数,当子进程结束时,信号处理函数回收子进程
 减少子进程计数。fork之后,父进程增加子进程计数。这样子,程序就实时的知道了
 子进程的个数。也就可以对之后的fork做出一定的限制。

 

转载于:https://www.cnblogs.com/linxr/archive/2011/01/20/1940678.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值