Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/27.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C Linux上以相反顺序接收的实时信号_C_Linux_Signals_Posix_Real Time - Fatal编程技术网

C Linux上以相反顺序接收的实时信号

C Linux上以相反顺序接收的实时信号,c,linux,signals,posix,real-time,C,Linux,Signals,Posix,Real Time,该程序向自身发送实时信号并进行处理。一旦它们被处理,它就会按照接收到的顺序输出接收到的信号 $ cat realtime.c #include <signal.h> #include <stdio.h> #include <unistd.h> #include <stdlib.h> int received_signals[10]; int received_signals_value[10]; int received_signals_coun

该程序向自身发送实时信号并进行处理。一旦它们被处理,它就会按照接收到的顺序输出接收到的信号

$ cat realtime.c
#include <signal.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>

int received_signals[10];
int received_signals_value[10];
int received_signals_count = 0;

void real_time_handler(int sig_number, siginfo_t * info,
                       void * arg __attribute__ ((unused)))
{
    received_signals[received_signals_count] = sig_number - SIGRTMIN;
    received_signals_value[received_signals_count] = info->si_value.sival_int;
    ++received_signals_count;
}

void send_real_time_signal(int sig_number, int value)
{
    union sigval sig_value;

    printf("Sending signal SIRTMIN+%d, value %d\n", sig_number, value);
    sig_value.sival_int = value;
    if (sigqueue(getpid(), sig_number + SIGRTMIN, sig_value) < 0) {
        perror("sigqueue");
        exit(EXIT_FAILURE);
    }
}

int main()
{
    struct sigaction action;
    sigset_t set;
    int i;

    // Handler setup
    action.sa_sigaction = real_time_handler;
    sigemptyset(&action.sa_mask);
    action.sa_flags = SA_SIGINFO;
    if ((sigaction(SIGRTMIN + 1, & action, NULL) < 0)
     || (sigaction(SIGRTMIN + 2, & action, NULL) < 0)
     || (sigaction(SIGRTMIN + 3, & action, NULL) < 0)) {
        perror("sigaction");
        exit(EXIT_FAILURE);
    }

    // Block all signals
    sigfillset(&set);
    sigprocmask(SIG_BLOCK, &set, NULL);

    send_real_time_signal(1, 0);
    send_real_time_signal(2, 1);
    send_real_time_signal(3, 2);
    send_real_time_signal(1, 3);
    send_real_time_signal(2, 4);
    send_real_time_signal(3, 5);
    send_real_time_signal(3, 6);
    send_real_time_signal(2, 7);
    send_real_time_signal(1, 8);
    send_real_time_signal(3, 9);

    // Unblock all signals
    sigfillset(&set);
    sigprocmask(SIG_UNBLOCK, &set, NULL);

    // To make sure we're handling all signals before resuming
    sleep(1);

    // Display results
    for (i = 0; i < received_signals_count; ++i) {
        printf("Received signal SIGRTMIN+%d, value %d\n",
               received_signals[i], received_signals_value[i]);
    }

    return EXIT_SUCCESS;
}
这与信号(7)()中的内容相矛盾:

实时信号以有保证的顺序发送。同一类型的多个实时信号按发送顺序发送。如果向进程发送不同的实时信号,则从编号最低的信号开始发送。(即,编号较低的信号具有最高优先级。)相反,如果一个过程中有多个标准信号处于挂起状态,则未指定它们的交付顺序

据我所知,我应该得到:

$ ./realtime
Sending signal SIRTMIN+1, value 0
Sending signal SIRTMIN+2, value 1
Sending signal SIRTMIN+3, value 2
Sending signal SIRTMIN+1, value 3
Sending signal SIRTMIN+2, value 4
Sending signal SIRTMIN+3, value 5
Sending signal SIRTMIN+3, value 6
Sending signal SIRTMIN+2, value 7
Sending signal SIRTMIN+1, value 8
Sending signal SIRTMIN+3, value 9
Received signal SIGRTMIN+1, value 0
Received signal SIGRTMIN+1, value 3
Received signal SIGRTMIN+1, value 8
Received signal SIGRTMIN+2, value 1
Received signal SIGRTMIN+2, value 4
Received signal SIGRTMIN+2, value 7
Received signal SIGRTMIN+3, value 2
Received signal SIGRTMIN+3, value 5
Received signal SIGRTMIN+3, value 6
Received signal SIGRTMIN+3, value 9
我已经快速查看了Linux内核源代码,但还没有找到实时信号的处理位置


我是做错了什么/遗漏了什么,还是手册页不准确?

您的问题是允许其他信号中断正在运行的信号处理程序:

sigemptyset(&action.sa_mask);
sa_mask
字段指定不允许中断此处理程序执行的信号集

这意味着您得到了
SIGRTMIN+1
,在您可以做任何事情之前您得到了另一个优先级较低的信号,然后您开始处理它。然后,该信号又被另一个信号打断,以此类推

要解决此问题,请禁止任何其他信号中断处理程序:

sigfillset(&action.sa_mask);

我认为您的问题在于这一行
sigeptyset(&action.sa_mask)

信号以正确的顺序RT1->RT3发送,但较高优先级的信号在稍后发送时会中断较低优先级的信号

在每个优先级内,信号按发送的顺序发送,默认情况下,在发送过程中会阻止正在发送的信号,并按发送的顺序正确处理这些信号,这会导致您的顺序混乱


正如cnicutar所说,切换到使用
sigfillset
,一切都会好起来。

正如上面提到的人,问题在于
sigeptyset(&action.sa_mask)行。
因此,另一个解决方案是仅阻止发送信号:

::sigaddset(&action.sa_mask, SIGRTMIN + 1);
::sigaddset(&action.sa_mask, SIGRTMIN + 2);
::sigaddset(&action.sa_mask, SIGRTMIN + 3);

注意:当调用处理程序时,阻塞信号本身被认为是一种良好的做法。

你确定你没有意外地依赖于未定义的行为吗?当您在信号处理程序中添加互斥锁/锁时会发生什么情况?默认情况下,正在传递的信号在传递过程中被阻止,它们按照发送的顺序得到正确处理:谢谢,这是第一个答案缺少的部分。
::sigaddset(&action.sa_mask, SIGRTMIN + 1);
::sigaddset(&action.sa_mask, SIGRTMIN + 2);
::sigaddset(&action.sa_mask, SIGRTMIN + 3);