所以这是我现在遇到的问题,我创建了 2 个不同的程序(1 个将管理另一个,而另一个将被执行多次)。这些程序将通过信号来回通信。我的问题是,是否有可能(以及如何)获取发送信号的程序的进程 ID。我的程序使用 signal() 来捕获信号并使用 kill() 来发送它们。
4 回答
尽管 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个信号时,只有第一个有机会被传递;没有钩子来关联其他数据;可用的用户信号只有两个) . 最好使用管道、命名管道或套接字。
不要使用signal()
,它已经过时了。如果你有它,请改用它sigaction()
,它提供了一个接口来获取发送者的进程 ID。
要获取发送信号的进程的进程 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 个 pid,而是简单的数字。这符合killall过程。可能,有可能枚举 /proc/ 目录,当你找到 /proc/DIGIT 时,打开 /proc/DIGIT/comm,读取并关闭它。可能,acueried 名称将是“关闭”或“重新启动”