编译器或操作系统如何区分sig_atomic_t类型和普通的int类型变量,并确保操作是原子的?使用两者的程序具有相同的汇编代码。如何特别注意使操作成为原子?
答案 0 :(得分:19)
sig_atomic_t
不是原子数据类型。它只是您可以在信号处理程序的上下文中使用的数据类型,即全部。因此,最好将名称读作“相对于信号处理的原子”。
为了保证与信号处理程序之间的通信,只需要原子数据类型的一个属性,即读取和更新将始终看到一致的值。其他数据类型(例如可能long long
)可以用较低和较高部分的几个汇编指令编写,例如:保证sig_atomic_t
可以一次性读写。
因此,平台可以选择任何整数基类型为sig_atomic_t
,以保证volatile sig_atomic_t
可以安全地用于信号处理程序。许多平台为此选择了int
,因为他们知道对于他们int
只用一条指令编写。
最新的C标准C11具有原子类型,但它们完全不同。其中一些(那些“无锁”)也可能用于信号处理程序,但这又是一个完全不同的故事。
答案 1 :(得分:10)
请注意,sig_atomic_t
不是线程安全的,只是异步信号安全。
原子论涉及两种障碍:
volatile
关键字的作用。对主题观察atomic Weapons: The C++ Memory Model and Modern Hardware进行全面处理。
答案 2 :(得分:7)
sig_atomic_t
通常只是typedef
(对某些系统特定的整数类型,通常为int
或long
)。使用volatile sig_atomic_t
(不仅仅是sig_atomic_t
)非常重要。
当您添加volatile
关键字时,编译器必须避免大量优化。
答案 3 :(得分:0)
使用两者的程序具有相同的汇编程序代码。如何特别注意使操作成为原子?
虽然这是一个老问题,但我认为仍然值得专门解决这部分问题。在Linux上,sig_atomic_t
由glibc提供。 glibc中的sig_atomic_t
是int
的typedef,没有特殊处理(截至本文)。 glibc docs解决了这个问题:
在实践中,您可以假设int是原子的。你也可以假设 指针类型是原子的;这很方便。这两个 在GNU C库的所有机器上都有假设 支持我们所知道的所有POSIX系统。
换句话说,只有普通int
已经满足glibc支持的所有平台上sig_atomic_t
的要求,并且不需要特殊支持。尽管如此,C和POSIX标准要求sig_atomic_t
因为可能有一些奇特的机器,我们要在其上实现C {和} int
不满足sig_atomic_t
的要求。
答案 4 :(得分:0)
此数据类型似乎是原子的。 从这里:https://www.gnu.org/software/libc/manual/html_node/Atomic-Types.html
24.4.7.2原子类型为了避免不确定中断变量的访问,可以使用特定的数据类型进行访问 总是原子的:sig_atomic_t。读取和写入此数据类型是 保证只在一条指令中发生,所以没有办法 处理程序以在访问“中间”运行。
类型sig_atomic_t始终是整数数据类型,但它是哪一个 的大小以及其中包含的位数可能会因计算机而异。
数据类型:sig_atomic_t这是整数数据类型。这个的对象 类型始终是原子访问的。
在实践中,您可以假定int是原子的。你也可以假设 指针类型是原子的;那很方便。这两个 假设在GNU C库的所有机器上都是正确的 支持我们所知道的所有POSIX系统。