【发布时间】:2020-12-12 14:20:38
【问题描述】:
在我正在编写的代码中,检查信号处理程序的返回值以确保信号是否被接收是非常有用的。所以,例如,如果我有这样的东西:
Message m;
sig_t s = signal(SIGALRM, sigalrm);
alarm(DURATION);
int status = msgrcv(msg_id, &m, sizeof(m.appointment), destination_mailbox, 0);
将会发生的事情是程序一到达 msgrcv 命令就会阻塞,因为它会等待消息。但是,如果它在 DURATION 秒后没有收到消息,则警报信号将唤醒它,状态将等于 -1。
现在,理想情况下,假设我想确保程序由于警报而不是其他原因唤醒。比如说msgrcv出错了,程序就被唤醒了,但是状态还是-1,m为空。
信号状态返回值的man入口
signal() 返回信号处理程序的前一个值,或 SIG_ERR 关于错误。在里面 发生错误时,设置 errno 以指示原因。
如果我在调用信号处理程序后尝试打印 sig_t 的值,我会怎么做?这将打印“信号(零)”。
printf("signal %p\n", s);
那么,如果我想这样做,我该如何处理这个返回值
if(s == a state where the handler was never called)
do A;
else
do B;
【问题讨论】:
-
typedef void (*sig_t) (int);如您所见,信号处理程序是一个不返回值的函数。 -
调用
signal不会调用处理程序。如果signal返回 NULL,那只是意味着之前没有处理程序。这并不意味着没有收到 SIGALRM。如果您想知道您的处理程序已被调用,请让处理程序更改全局 sig_atomic_t 的值(实际上,这就是您的处理程序应该做的所有事情)。在主进程中,检查该值何时被修改。 -
@WilliamPursell 该死的,我试图不惜一切代价避免全局变量。但是你建议我使用 sig_atomic_t 类型的全局变量?
-
如果
msgrcv及时返回,希望您重置alarm。 -
信号处理程序需要使用文件范围变量——全局或静态。这实际上是不可避免的。对于常规信号处理程序,信号处理程序可用的唯一信息是信号编号。 POSIX 提供
sigaction(),它提供选项SA_SIGINFO并将更多信息传递给处理程序,但仍然无法访问程序员控制的数据——如果您必须访问信号处理程序中的数据,它必须至少是文件范围数据.
标签: c signals interrupt-handling