【问题标题】:C signals and processesC 信号和过程
【发布时间】:2010-04-23 12:31:02
【问题描述】:

所以基本上我希望“cmd_limit”以秒为单位取一个数字,这是我们等待子进程(安全地假设只有一个)完成的最长时间。如果子进程确实在睡眠期间完成,我希望 cmd_limit 返回 pass 并且不运行其余的 cmd_limit 代码。谁能帮我做这个,这是我到目前为止所得到的......

int cmd_limit( int limit, int pid ) {

    signal( SIGCHLD, child_died );
    sleep( limit );
    kill( pid, SIGKILL );
    printf("killin'\n");
    return PASS;
}

void child_died( int sig ) {

    int stat_loc; /* child return information */
    int status; /* child return status */

    waitpid( -1, &stat_loc, WNOHANG );

    if( WIFEXITED(stat_loc) ) { // program exited normally
        status = WEXITSTATUS( stat_loc ); /* get child exit status */
    }

    printf("child died: %s\n", signal);

}

【问题讨论】:

  • 你看过alarm()吗?
  • 我知道警报,但我不确定如何确保在睡眠期间可以使用警报从 cmd_limit 返回?
  • sleep 被不可忽略的信号打断(请阅读sleep 手册页了解具体情况),如果这是您想知道的。它还返回中断时的剩余时间,如果没有中断,则返回 0。但是,您不应该在某些系统上混合调用 sleep 和 ALRM 信号。

标签: c process signals


【解决方案1】:

如果发送了信号,kill 返回 0,如果没有发送信号,则返回 -1。如果进程已经退出,则无法发送任何信号,因此 kill 的返回值可以用来告诉您进程是被 kill 杀死还是已经死亡。

此外,您可以使用其中一个等待系统调用来查看子进程的状态更改(包括 exit )。

您还应该查看 SIGCHLD 的父进程中的信号处理,当子进程更改状态(包括 exit )时父进程会收到该信号,并且还会将父进程踢出睡眠状态(尽管在某些系统上睡眠功能可能会重新开始睡眠)。

使用 wait 和/或 SIGCHLD 如果孩子在您的时间限制内退出,您可以让父母更快完成。

您应该注意,您可能应该调用等待子进程退出,这样您就不会创建僵尸(已调用退出但必须保留以防父进程想要​​查看其退出状态的进程)。

您需要查看的另一件事是系统调用在被信号中断时可以设置的 errno 值 EINTR。

从您的命令行类型:

man errno
man 2 wait
man 2 sigaction

有关我所谈论的事情的更多信息。

【讨论】:

    【解决方案2】:

    你的意思是这样的吗?

    bool childDied;
    
    int cmd_limit( int limit, int pid ) {
        childDied = FALSE; 
        signal( SIGCHLD, child_died ); 
        sleep( limit ); 
        if (!childDied)
        {
          kill( pid, SIGKILL ); 
          printf("killin'\n"); 
        }
        return PASS; 
    } 
    
    void child_died( int sig ) {
        int stat_loc; /* child return information */ 
        int status; /* child return status */ 
    
        childDied = TRUE; 
    
        waitpid( -1, &stat_loc, WNOHANG ); 
    
        if( WIFEXITED(stat_loc) ) { // program exited normally 
            status = WEXITSTATUS( stat_loc ); /* get child exit status */ 
        } 
    
        printf("child died: %s\n", signal); 
    
    } 
    

    【讨论】:

    • 这是对的,除了如果 limit = 200 并且孩子在 10 秒内死亡,我们仍然需要等待 200 秒才能在程序中执行其他任何操作..
    • @Gary:如果这是一个问题,您可以使用一个循环计数器来替换一个大的睡眠调用,用几个较短的调用来计算所需的总数。每次通过循环检查子进程是否已经退出。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-04-28
    • 2017-05-06
    • 2013-12-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-25
    相关资源
    最近更新 更多