2013-02-28 34 views
2

所以这是我现在有的问题,我创建了2个不同的程序(1将管理另一个,而另一个将被执行多次)。程序将通过信号来回传递。我的问题是,是否有可能(以及如何)获得发送信号的程序的进程ID。 我的程序使用signal()来捕获信号并kill()发送它们。C - 获取信号处理的进程ID

回答

2

请勿使用signal(),它已过时。如果有,请使用sigaction(),它提供了一个接口来获取发件人的进程ID。

+1

它不会捕获sigkill和sigstop。例如,如果您从第二个进程按ctrl + c,它将不会被sigaction()捕获。 – 2013-02-28 08:30:16

+0

嗯,那很好,我怎么用sigaction()来捕捉它? – Chris 2013-02-28 08:33:01

+0

@Chris:对于一个'sigaction()'示例以及关于信号处理的索引刷新,请看[本文](http://lazarenko.me/2013/01/15/how-not-to-write -a-signal-handler /),这是我前一段时间写的。 – 2013-02-28 14:48:04

3

尽管signal()是标准C库,但该函数不是可移植的,其行为取决于系统。更好地使用POSIX.1的sigaction()。

下面是如何使用的sigaction用处理程序空隙ħ(INT SIG)的例子:

int mysignal (int sig, void (*h)(int), int options) 
{ 
    int r; 
    struct sigaction s; 
    s.sa_handler = h; 
    sigemptyset (&s.sa_mask); 
    s.sa_flags = options; 
    r = sigaction (sig, &s, NULL); 
    if (r < 0) perror (__func__); 
    return r; 
} 

选项在人的sigaction说明。一个不错的选择是options=SA_RESTART

要知道发送信号的进程的PID,请设置options=SA_SIGINFO,并使用sa_sigaction回调代替sa_handler;它将收到一个siginfo_t结构,它有一个si_pid字段。您可以使用sigqueue将数据与信号相关联。

一般来说,使用信号以安全的方式通信是一个坏主意(当发送n个信号时,只有第一个信号有机会被传送;没有挂钩来关联其他数据;可用的用户信号只有两个)。更好地使用管道,命名管道或套接字。

1

要获得发送信号的进程的进程ID,您需要在选项SA_SIGINFO中包含该进程。如果你这样做,sigaction的接口稍有不同。这里是一个正确的处理程序的例子,以及如何设置它。 (包括我SA_RESTART的,只是因为它通常是一个好主意的选项,但不是必需的)

// example of a handler which checks the signalling pid 
void handler(int sig, siginfo_t* info, void* vp) { 
    if (info->si_pid != getpid()) { 
    // not from me (or my call to alarm) 
    return; 
    } 
    // from me. let me know alarm when off 
    alarmWentOff = 1; 
} 

这里是我的设置处理器通用代码:

typedef void InfoHandler(int, siginfo_t *, void *); 

InfoHandler* 
SignalWithInfo(int signum, InfoHandler* handler) 
{ 
    struct sigaction action, old_action; 

    memset(&action, 0, sizeof(struct sigaction)); 
    action.sa_sigaction = handler; 
    sigemptyset(&action.sa_mask); /* block sigs of type being handled */ 
    action.sa_flags = SA_RESTART|SA_SIGINFO; /* restart syscalls if possible */ 

    if (sigaction(signum, &action, &old_action) < 0) 
perror("Signal error"); 
    return (old_action.sa_sigaction); 
} 

最后,对于这种特殊情况:

SignalWithInfo(SIGALRM, handler); 
-1

它现在改变了。信号信息显示不是1 pid,而是简单的数字号码。这符合killall过程。可能是枚举/ proc /目录,找到/ proc/DIGIT,打开/ proc/DIGIT/comm,读取并关闭它。可能是,acueried名称将被“关机”或“重启”