所以这就是我现在遇到的问题,我创建了2个不同的程序(1个将管理另一个,而另一个将被执行多次)。程序将通过信号来回通信。我的问题是,是否有可能(以及如何)获取发送信号的程序的进程ID。 我的程序使用signal()来捕获信号,使用kill()来发送它们。
答案 0 :(得分:3)
尽管signal()在标准C库中,但此功能不可移植,其行为取决于系统。最好使用sigaction(),即POSIX.1。
以下是如何将sigaction与处理程序void h(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;
}
选项在man sigaction中描述。一个不错的选择是options=SA_RESTART
。
要知道发送信号的过程的PID,请设置options=SA_SIGINFO
,并使用sa_sigaction
回调代替sa_handler
;它将收到一个siginfo_t
结构,其中包含si_pid
字段。您可以使用sigqueue
将数据与信号相关联。
一般来说,使用信号以安全的方式进行通信是一个坏主意(当发送n个信号时,只有第一个信号有机会被传送;没有钩子来关联其他数据;可用的用户信号是只有两个)。更好地使用管道,命名管道或插座。
答案 1 :(得分:2)
不要使用signal()
,它已经过时了。如果您拥有它,请改用sigaction()
,它提供了一个接口来获取发件人的进程ID。
答案 2 :(得分:2)
要获取发送信号的进程的进程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);
答案 3 :(得分:-1)
现在已经改变了。信号信息不是1 pid,而是简单的数字。这符合killall过程。可能是,有可能枚举/ proc /目录,当你找到/ proc / DIGIT时,打开/ proc / DIGIT / comm,读取并关闭它。可能是,acueried名称将是“shutdown”或“reboot”