【问题标题】:How can I terminate a process and verify its not running anymore in C?如何终止进程并验证它不再在 C 中运行?
【发布时间】:2021-07-19 08:05:02
【问题描述】:

我想完全终止 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);
}

你怎么看?

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

它试图终止进程但没有这样做。我不知道为什么。

谢谢。

【问题讨论】:

  • 哪个操作系统,如果有的话?看门狗是一个术语,指的是嵌入式系统中的一种硬件复位电路。
  • @Lundin 嘿,看门狗不是这里的主要话题。我一般在how can I terminate a process 上发言,为什么我的代码不起作用。看门狗不太相关,我会从帖子中删除它以免混淆其他人,谢谢。

标签: c process signals terminate kill-process


【解决方案1】:

你在做不必要的事情。

检查进程是否存在:

kill(pid, 0);

如果返回值为0,则表示进程存在,如果为-1,则必须检查errno。如果是ESRCH

目标进程或进程组不存在。请注意,现有进程可能是僵尸进程,即已终止执行但尚未等待 (2) 的进程。


终止进程:

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

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

杀死后,您必须通过以下方式等待进程:

waitpid(pid, &status, 0);

如果status 不是NULLwait()waitpid() 将状态信息存储在它指向的int 中。可以使用手册页中描述的宏检查此整数。


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;
}

【讨论】:

  • 嘿,谢谢! waitpid(process_to_check, &amp;status, WNOHANG); 呢?那和你建议的waitpid(pid, &amp;status, 0有什么区别?
  • 关于ESRCH,杀死一个僵尸进程怎么样?可能吗?因为在我的情况下,我试图杀死一个进程,然后重新启动它。问题是即使我杀了它,它仍然停留在htop
  • WNOHANG 如果没有孩子退出,则立即返回。如果您想确定孩子已经终止,请不要使用它。
  • 等等,等等,等等……waitpid 杀死了那个僵尸。
  • 我实际上想在busy wait 中添加wait,正如您在我的while loop 中看到的那样。我猜这是个坏主意。您可以添加waitpid(pid, &amp;status, 0); 吗?我认为如果没有孩子退出,它也会立即返回。所以我认为这与WHOHANG 之间没有区别
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-07-26
  • 2021-11-15
  • 1970-01-01
  • 2023-03-11
  • 2020-08-19
  • 1970-01-01
相关资源
最近更新 更多