在 Linux 上使用信号的 IPC

Posted

技术标签:

【中文标题】在 Linux 上使用信号的 IPC【英文标题】:IPC using Signals on linux 【发布时间】:2012-06-21 07:59:50 【问题描述】:

IPC (inter process communication) 可以使用信号捕获和信号提升吗?

我做了两个程序。在第一个程序中我处理了信号,而在另一个程序中我只是提出了我想在另一个程序中处理的信号。我工作得很好,但我想使用信号在这两个程序之间进行通信,并且还想用这个 raise 信号发送一些数据字节。我该怎么做?

我也想用这个信号传递消息。我可以做吗?有可能吗?

另外,使用信号的 IPC 机制的优缺点是什么?

以下是我的两个程序的工作代码。这样做,我可以只发出信号和捕获信号,但我想将数据从一个程序传递到另一个程序。

在第二个程序中,我使用了第一个程序的进程 ID。我怎样才能使它动态化?

第一个程序:

/* Example of using sigaction() to setup a signal handler with 3 arguments
 * including siginfo_t.
 */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <string.h>

static void hdl (int sig, siginfo_t *siginfo, void *context)

    printf("sig no = %d \n", sig);
    if(sig == SIGINT)
        exit(0);
    printf ("Sending PID: %ld, UID: %ld\n",
            (long)siginfo->si_pid, (long)siginfo->si_uid);


int main (int argc, char *argv[])

    struct sigaction act;


    sigemptyset(&act.sa_mask);

    act.sa_sigaction = &hdl;
    act.sa_flags = SA_SIGINFO;

    if (sigaction(SIGUSR1, &act, NULL) < 0) 
        perror ("sigaction SIGUSR1");
        return 1;
    
    if (sigaction(SIGINT, &act, NULL) < 0) 
        perror ("sigaction SIGINT");
        return 1;
    

    while (1)
    
        sleep(1);
    

    return 0;

第二个节目

#include  <stdio.h>
#include  <signal.h>

void  main(void)


   while (1)
    
        sleep(1);
        kill(11558, SIGUSR1);
    


【问题讨论】:

我建议反对SIGINTSIGUSR1 等信号使用相同的信号处理程序。让您的信号处理程序尽可能分开。 @JoachimPileborg 我该怎么做你能给我链接或一些我在谷歌上找到很多但我没有得到任何东西的教程。 对两个不同的调用使用两个不同的sigaction 结构,每个调用都有自己的处理函数。 @JoachimPileborg 在下面的回答中,每个人都说我们可以发送任何带有信号的数据。那么它的可能性如何 printf() 不是异步信号安全的。所以你不应该从你的处理程序中调用它。见SIG30-C. Call only asynchronous-safe functions within signal handlers 和CWE-828: Signal Handler with Functionality that is not Asynchronous-Safe。 【参考方案1】:

Signals 旨在提供对流程的基本控制形式,而不是作为 IPC 机制。信号在用作其他任何东西时有几个问题:

很多系统调用会被信号打断,需要特殊处理。

因此,很多代码都不是信号安全的。

信号没有任何类型的数据内容,除了它们自己。这使得它们作为消息传递方法几乎毫无用处。

在信号处理程序中您能做的只有这么多。

最重要的是,相同类型的后续信号不会排队 - 它们合并到一个实例中。

更重要的是,无法保证信号的传递顺序与生成时的顺序相同。从手册页:

相比之下,如果一个进程有多个标准信号待处理, 它们是未指定的

您可能理论上能够使用几个来回传递的信号建立某种通道,其中一些充当某种确认,但没有理智的人会想要尝试这样的事情。您不妨改用烟雾信号...

【讨论】:

“没有理智的人会想尝试这样的事情”【参考方案2】:

不,不要尝试为此使用信号。您不能使用 siginfo 结构以外的信号附加额外数据。使用信号的主要问题是信号安全性太小。您必须避免几乎所有的 C 运行时例程,并确保接收程序对其所有内核调用进行 EINTR 检查。关于信号何时出现,你唯一能说的就是它不会在你期望的时候出现(有点像西班牙宗教裁判所)。

我建议您研究其他 IPC 机制,例如共享内存、消息队列、fifos(命名管道)和套接字。

【讨论】:

【参考方案3】:

是否可以使用信号捕获和信号引发进行 IPC(进程间通信)?

是和不是。仅考虑信号,您可以向另一个进程发送信号,但除了信号之外,您不能发送任何其他内容。

我也想用这个信号传递消息。我可以做吗?有可能吗?

不,不是您想要的方式。您可以使用套接字、文件、管道或命名管道来执行此操作。如果您想了解有关 UNIX IPC 的更多信息,请阅读Advanced Programming in the UNIX Environment。

【讨论】:

我认为 UNIX 环境中的高级编程有第二版。【参考方案4】:

除了我遇到的一种特定情况外,信号通常不能用作 IPC 机制。

我唯一一次使用信号是作为 IPC 机制的一部分,当您需要中断信号进程的正常操作流程来处理某些事情时,例如计时器中断。信号(已经使用信号和boost共享内存来实现进程间事件管理。共享内存包含需要处理的事件列表,信号用于获取进程处理这些事件。这些事件是带外的并且不可预测,因此使用信号是理想的。我进行了大量测试来验证实现(很难让它完全稳定)。

这在使用 glibc 的 Linux 环境中使用 sigqueue 和信号 SIGRTMIN+1 并在 sigaction 上使用 SA_RESTART 将避免直接处理 EINTR 的需要,请参阅glibc: Primitives Interrupted by Signals。 BSD 有一个类似的方案,所以我的系统不需要 EINTR 处理。其他答案提出的所有观点都被考虑和处理(和测试)。

但是,如果您只想在进程的正常操作中来回传递值,那么另一个 IPC(例如套接字、文件、管道或命名管道)会更好。如果您可以使用ZeroMQ,那就更好了,因为它以一种非常优雅的方式为您完成了很多艰苦的工作。

【讨论】:

【参考方案5】:

我目前正在阅读man 7 signal

实时信号的区别如下:

    如果使用 sigqueue(3) 发送信号,则可以随信号一起发送伴随值(整数或指针)。 ...

注意:实时信号从SIGRTMINSIGRTMAX

【讨论】:

+1 用于手册页阅读。还指出您可以发送数据以及大多数答案都丢失的信号。 SIGUSR1 和 SIGUSR2 可用于该自定义目的。

以上是关于在 Linux 上使用信号的 IPC的主要内容,如果未能解决你的问题,请参考以下文章

linux进程间通讯-System V IPC 信号量

Linux中IPC信号量的使用

linux 内核信号量

20155202 张旭 Linux下IPC机制

Linux IPC基础

Linux IPC 选择?