C语言 为什么kill()it [复制]后子进程变成僵尸

yqlxgs2m  于 2023-08-03  发布在  其他
关注(0)|答案(2)|浏览(125)

此问题在此处已有答案

Zombie processes(5个答案)
28天前关闭。
我有一个多进程程序。简单说明一下这个问题,子进程只会被阻塞,主进程判断子进程是否还存在,如果存在则父进程杀死子进程。
我的代码如下:

#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <time.h>
#include <errno.h> 
#include <sys/socket.h> 
#include <string.h>

#define TIME_OUT 3 

int get_current_time()
{
    struct timespec t;
    clock_gettime(CLOCK_REALTIME, &t);
    return t.tv_sec;
}

void child_process_exec() 
{
    int fd = open("./myfifo", O_WRONLY); // myfifo is a named pipe, here will be blocked.
    sleep(10);
}

void parent_process_exec(pid_t workProcessId)
{
    int status;
    int childRes; 
    int lastHeartBeatTime = get_current_time();
    while(1) {
        sleep(1);
        if (get_current_time() - lastHeartBeatTime> TIME_OUT) {
            childRes = waitpid(workProcessId, &status, WNOHANG);
            if(childRes == 0) {  
                printf("kill process\n"); 
                printf("kill get %d\n", kill(workProcessId, SIGTERM));
            }
            
            workProcessId = fork();
            if(workProcessId > 0) {
                lastHeartBeatTime = get_current_time();
            } else {
                printf("start up child process again\n");
                child_process_exec();
                return;
            }
        }
    }
}

int main()
{
    pid_t workProcessId = fork();
    if (workProcessId > 0) {
        parent_process_exec(workProcessId);
    } else {
        child_process_exec();
    }
    
    return 0;
}

字符串
但是我用ps得到的子进程是<defunct>在终端。为什么kill()后子进程变成僵尸了呢?如何干净地杀死子进程?

h6my8fg2

h6my8fg21#

1.在t+3s时,调用waitpid(..., WNOHANG),它立即返回,而没有获得子对象,这一点在childRes == 0中很明显。杀死第一个子节点,然后用第二个子节点的pid覆盖workProcessId。冲洗并重复。这意味着waitpid()在子进程终止后永远不会被调用,而在t=T中,您最终会得到T/3僵尸子进程。最简单的修复方法是将WNOHANG更改为0,以便父块等待子块。您可以通过使用wait()来阻止等待任何孩子来获得类似的效果。
或者,维护一个pid_t数组来保存每个还没有被收割的孩子。然后用waithpid(..., WNOHANG)循环该数组。
1.您可能希望修复parent_process_exec()中的逻辑,使其不会无条件地派生一个新的子进程。
1.在Linux上,我必须为kill()包含signal.h
1.将int workProcessId更改为pid_t workProcessId

  1. open()的第二个参数是一个int,而不是一个字符串,所以你想使用O_WRONLY而不是"O_WRONLY"。始终检查返回值。
jk9hmnmh

jk9hmnmh2#

根据@Useless的this,我在kill子进程后添加wait(),现在父进程收割子进程。像这样

if(childRes == 0) {  
    printf("kill process\n"); 
    printf("kill get %d\n", kill(workProcessId, SIGTERM));
    wait(NULL); // return the child process pid
}

字符串
我知道一个僵尸进程只是一个pid,它是无害的,但我认为应该有一种方法来杀死子进程。但是在父进程杀死它的子进程后,还有一个僵尸进程,这真的让我很困惑。

相关问题