您的当前位置:首页正文

僵尸进程/wait/waitpid

2024-11-23 来源:个人技术集锦
  • 杀死僵尸进程的父进程(僵尸进程的父进程必然存在),僵尸进程成为"孤儿进程",过继给1号进程init,init始终会负责清理僵尸进程。

  • 如果子进程退出,父进程还没有执行到wait,那边子进程就会由变为短暂的僵尸进程,直到父进程执行到wait,然后被父进程处理。

  • 当一个进程正常或异常终止的时候,内核就向其父进程发送SIGCHLD信号。父进程可以选择忽略该信号,或者提供一个该信号发生时即被调用执行的函数。对于这种信号的系统默认动作是忽略它

  • 调用wait进程可能会发生的情况

  • 如果进程由于接收到SIGCHLD信号而调用wait,则可期望wait会立即返回(因为,SIGCHILD代表有子进程退出,所以不用阻塞等待)。但是如果在任意时刻调用wait则进程可能会阻塞。
  • 在信号处理函数中使用wait存在的问题:有多个子进程几乎同时退出,只产生了一个信号,所以信号函数wait可能了只处理一个子进程。使用循环wait会导致阻塞,如下
void sig_chld(int signo)
{
    int pid;
    if(signo == SIGCHLD) {
        while((pid = wait(NULL)) > 0)//如果子进程还未退出父进程会阻塞在sighandler中
            printf("process %d is exited\n",pid);
    }
}

  • 用waitpid可以避免阻塞。从本质上讲,系统调用waitpid和wait的作用是完全相同的,但waitpid多出了两个可由用户控制的参数pid和options,从而为我们编程提供了另一种更灵活的方式。
  1. pid>0时,只等待进程ID等于pid的子进程,不管其它已经有多少子进程运行结束退出了,只要指定的子进程还没有结束,waitpid就会一直等下去。
  2. pid=-1时,等待任何一个子进程退出,没有任何限制,此时waitpid和wait的作用一模一样。
  3. pid=0时,等待同一个进程组中的任何子进程,如果子进程已经加入了别的进程组,waitpid不会对它做任何理睬。
    pid<-1时,等待一个指定进程组中的任何子进程,这个进程组的ID等于pid的绝对值。
  4. options:options提供了一些额外的选项来控制waitpid,目前在Linux中只支持WNOHANG和WUNTRACED两个选项,最常用的就是WNONHANG来避免阻塞
  5. waitpid的返回值比wait稍微复杂一些,一共有3种情况:
    1、当正常返回的时候,waitpid返回收集到的子进程的进程ID;
    2、如果设置了选项WNOHANG,而调用中waitpid发现没有已退出的子进程可收集,则返回0;
    3、如果调用中出错,则返回-1,这时errno会被设置成相应的值以指示错误所在。当pid所指示的子进程不存在,或此进程存在,但不是调用进程的子进程,waitpid就会出错返回,这时errno被设置为ECHILD;
  • 因此上述代码可以改为如下的方式
void sig_chld(int signo)
{
    int pid;
    if(signo == SIGCHLD) {
        while((pid = waitpid(-1,NULL,WNOHANG) > 0)//暂时没有要处理的子进程就退出循环。
            printf("process %d is exited\n",pid);
    }
}
  • 杀死僵尸进程
  1. 重启计算机
  2. 杀死父进程

参考链接:
https:///qq739887227/article/details/82874309
https:///deniece1/article/details/102756586
https://www.cnblogs.com/nufangrensheng/p/3510101.html

显示全文