我如何终止一个进程并在 C 中验证它不再是 运行?

How can I terminate a process and verify its not running anymore in C?

我想完全终止 Linux C89 上的进程。

流程是:检查它是否已经死亡,如果没有,使用sigterm让它平静地死亡并等待10秒直到它死亡。如果它还活着 - SIGKILL 它。

int TerminateProcessIMP(pid_t process_to_kill)
{    
    assert(process_to_kill);
    
    /*---------------------------------------------------------*/
    /*  check if process is already does not exist */
    if (!IsProcessAliveIMP(process_to_kill))
    {
        return (SUCCESS);
    }
    /*---------------------------------------------------------*/
    /*  terminate process_to_kill   */
    if (kill(process_to_kill, SIGTERM))
    {
        fprintf(stderr, "%s\n", strerror(errno));
    }
    
    if (!IsProcessAliveIMP(process_to_kill))
    {
        return (SUCCESS);
    }
    
    /*---------------------------------------------------------*/
    /*  if its still alive, SIGKILL it */
    if (kill(process_to_kill, SIGKILL))
    {
        fprintf(stderr, "%s\n", strerror(errno));
    }
    
    if (!IsProcessAliveIMP(process_to_kill))
    {
        return (SUCCESS);
    }
    /*---------------------------------------------------------*/

    return (FAILURE);
}
/******************************************************************************/
int IsProcessAliveIMP(pid_t process_to_check)
{
    time_t start_time = 0;
    time_t end_time = 0;
    time_t time_to_wait = 10; /* in seconds */
    
    assert(process_to_check);
    
    start_time = time(0);
    end_time = start_time + time_to_wait;
    
    /*  give it time to be terminated because maybe it frees memory meanwhile */
    while (0 != kill(process_to_check, 0) && time(0) < end_time)
    {}
    
    /*  check if it still exists */
    if (0 == kill(process_to_check, 0))
    {
        return (0);
    }
    
    /* the process is still alive */
    return (1);
}

你怎么看?

现在,它不起作用,也不会终止进程。

它试图终止进程,但没有成功。我不明白为什么。

谢谢。

你在做不必要的事情。

检查进程是否存在:

kill(pid, 0);

如果return值为0,则进程存在,如果-1则必须检查errno。在 ESRCH 的情况下:

The target process or process group does not exist. Note that an existing process might be a zombie, a process that has terminated execution, but has not yet been wait(2)ed for.


要终止进程:

kill(pid, SIGTERM); // signal can be blocked, handled or ignored

kill(pid, SIGKILL); // signal cannot be blocked, handled or ignored

kill后,等待进程通过:

waitpid(pid, &status, 0);

If status is not NULL, wait() and waitpid() store status information in the int to which it points. This integer can be inspected with the macros, described in the man page.


man kill
man waitpid


示例:

int TerminateProcessIMP(pid_t pid)
{
    //check if process exists
    int res = kill(pid, 0);
    
    if ((res == -1) && (errno != ESRCH)) {
        //error: either EINVAL or EPERM
        //ESRCH: an existing process might be a zombie
        return -1;
    }
    
    if (res == 0) { //process exists
        
        //ask politely to terminate
        
        if (kill(pid, SIGTERM) == -1) {
            //error: unable to send a signal to the process
            return -1;
        }
        
        //let us see if the child complied to our request
        res = waitpid(pid, NULL, WNOHANG | WUNTRACED | WCONTINUED);
        
        if (res == -1) {
            //most likely not our child (errno == ECHILD)
            //but the process could follow our request and still terminate
            //if you want to be sure goto SIGKILL below
            //or return
        } else if (res == 0) {
           //our child, but at this point the child has not terminated yet 
           //(maybe it will never)
           //either continue to wait or goto SIGKILL below
        } else {
           //child complied to our request and terminated in time
           //res contains the id of the child (res == pid)
           return res;
        }

        //--- or ---

        /* do {
            res = waitpid(pid, NULL, WNOHANG | WUNTRACED | WCONTINUED);
            //because of WNOHANG
            sleep(1);
            //your timeout method goes here
        } while (!res);

        if (res == -1) { //same as above }
        if (res  >  0) { return res;     } */
        
    }
    
    //at this point, the process either does not exists (maybe zombie), 
    //is not our child or refused our request (SIGTERM)
    
    //send a SIGKILL signal to the process
    kill(pid, SIGKILL);
    
    //wait for the process to terminate
    res = waitpid(pid, NULL, 0);
    
    /*if (res == -1) {
        //not our child, or process does not exists
    }*/
    
    /*if (res > 0) {
        //child successfully terminated
    }*/
    
    return res;
}