zoukankan      html  css  js  c++  java
  • fork小续

    pid_t pid = fork();

    1.根据fork的返回值区分父子进程:

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

    可用代码表示为:

    1  if( ( pid = fork() ) < 0 ){
    2   //error
    3  }
    4  else if( pid == 0 ){ 
    5   //child
    6  }
    7  else{
    8   //parent
    9  }

    2.进程调用wait等待子进程的退出:

    系统调用wait做两件事:a.wait暂停调用它的进程直到子进程结束;b.wait取得子进程结束时传给exit的值。

    系统调用wait的两个特征:a.wait阻塞调用它的进程直到子进程结束;b.wait返回结束进程的PID。

    父进程必须要回收子进程,这时必须用wait/waitpid。不然当子进程结束后,它会变成僵死进程。用"ps -ef"命令查看,可看到其状态为<defunct>。所以,在fork()之后,我们一般执行:waitpid(pid,NUL,0);

      参数1: pid表示到等待的子进程ID
      参数2: NULL表示对子进程的结束状态不在意。
      参数3: 控制选项

     1  if( ( pid = fork() ) < 0 ){
     2   //error
     3  }
     4  else if( pid == 0 ){ 
     5   //child
     6   ...
     7  }
     8  else{
     9   waitpid( pid, NULL, 0 ); //用于等待子进程结束.
    10  }

    3.  问题提出——父进程被阻塞:

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

     1  if( ( pid = fork() ) < 0 ){
     2   //error
     3  }
     4  else if( pid == 0 ){ 
     5   //first child exit !
     6   if( fork() > 0 ){
     7    exit(0);
     8   }
     9   else{
    10    //second child...
    11   }
    12  }
    13  else{
    14   waitpid( pid, NULL, 0 ); 
    15   //因为第一个子进程马上退出,所以waitpid在等到其结束时马上返回,第二
    16   //个子进程将被init进程托管!
    17  }

     4.问题提升——子进程结束标志:

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

     1 int  chld_count = 0;
     2  
     3  void sigchd_exit(int signo) 
     4  { 
     5   if( waitpid(-1, NULL, WNOHANG) > 0 ) chld_count--;
     6   
     7   printf( "child count: %d
    ", chld_count );
     8  }
     9  
    10  void set_sigchd()
    11  {
    12   signal(SIGCHLD, sigchd_exit); //子程序退出的信号 
    13   signal(SIGINT,  sigchd_exit); //Ctrl+C
    14   signal(SIGTERM, sigchd_exit); 
    15  }
    16  
    17  //.....
    18  set_sigchd()
    19  if( ( pid = fork() ) < 0 ){
    20   //error
    21  }
    22  else if( pid == 0 ){
    23   //child
    24   ...
    25  }
    26  else{
    27   chld_count++;
    28  }

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

     

  • 相关阅读:
    如何 Scale Up/Down Deployment?- 每天5分钟玩转 Docker 容器技术(126)
    读懂 Deployment YAML
    k8s 创建资源的两种方式
    在qemu模拟的aarch32上使用kgtp
    交叉编译gdb和gdbserver
    基于设备树的controller学习(2)
    基于设备树的controller学习(1)
    基于设备树的TQ2440 DMA学习(4)—— client驱动
    基于设备树的TQ2440 DMA学习(3)—— DMA控制器驱动
    基于设备树的TQ2440 DMA学习(2)—— 简单的DMA传输
  • 原文地址:https://www.cnblogs.com/xymqx/p/3710286.html
Copyright © 2011-2022 走看看