这是一个简单的玩具程序,使用volatile sig_atomic_t
.
#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
#include <unistd.h>
#define UNUSED(x) (void) (x)
volatile sig_atomic_t quit;
void sigusr1_handler(int sig)
{
UNUSED(sig);
write(1, "handler\n", 8);
quit = 1;
}
int main()
{
struct sigaction sa;
sa.sa_handler = sigusr1_handler;
sa.sa_flags = 0;
sigemptyset(&sa.sa_mask);
if (sigaction(SIGUSR1, &sa, NULL) == -1) {
perror("sigaction");
return 1;
}
quit = 0;
while (!quit)
;
printf("Exiting ...\n");
return 0;
}
我想我知道为什么volatile sig_atomic_t
是必要的quit
这个特定程序中的变量。
- Without
volatile
,编译器可能会优化while (!quit) ;
到无限循环。它没有发现循环修改quit
,因此假设quit
永远保留0
.
- 更新至
quit
或读过quit
应该发生在一条机器指令中。如果需要多条机器指令来更新或读取quit
,那么如果在更新正在进行时调用信号处理程序,则信号处理程序中的读取可能会看到不一致的值quit
.
到目前为止我的说法正确吗?如果没有,请纠正我的答案。
现在我想学习一个通用规则sig_atomic_t
在信号处理的上下文中是必要的。乔纳森·莱弗勒(Jonathan Leffler)在评论中解释说,提供概括并不容易。
您能否提供一个已知场景的列表,其中变量需要定义为sig_atomic_t
从C标准的角度来看?它不必是详尽的清单。经验不足的开发人员在编写带有信号处理代码的 C 软件时可以参考该列表。
您能否提供一个已知场景的列表,其中变量需要定义为sig_atomic_t
从C标准的角度来看?
有 2 个相关部分c99 spec:
(§7.14 p2)
[The sig_atomic_t
type] 是对象的(可能是 volatile 限定的)整数类型,即使存在异步中断,也可以将其作为原子实体进行访问
(§7.14.1.1 p5)
如果该信号不是由于调用abort
or raise
函数中,如果信号处理程序引用任何具有静态存储持续时间的对象,而不是将值分配给声明为的对象,则行为未定义volatile sig_atomic_t
, ...
“静态存储时间”定义为:
(§6.2.4 p3)
其标识符通过外部或内部链接或存储类说明符声明的对象static
has 静态存储时间。它的生命周期是程序的整个执行过程,并且其存储的值仅在程序启动之前初始化一次。
简而言之,您需要使用volatile sig_atomic_t
变量是否可以异步访问(即,在信号处理程序内部和外部都可以访问该变量)。此外,访问非对象是未定义的行为volatile sig_atomic_t
具有静态存储持续时间的变量。未定义的行为意味着不仅变量的值可能不一致,程序还可能完全执行其他操作(例如段错误)。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)