sig_atomic_t实际上如何工作?

Chu*_*Chu 22 c linux signals

编译器或操作系统如何区分sig_atomic_t类型和普通的int类型变量,并确保操作是原子的?使用两者的程序具有相同的汇编代码.如何特别注意使操作成为原子?

Jen*_*edt 23

sig_atomic_t不是原子数据类型.它只是您可以在信号处理程序的上下文中使用的数据类型,即全部.因此,最好将名称读作"相对于信号处理的原子".

为了保证与信号处理程序之间的通信,只需要原子数据类型的一个属性,即读取和更新将始终看到一致的值.其他数据类型(例如可能long long)可以用较低和较高部分的几个汇编指令编写,例如sig_atomic_t保证一次读取和写入.

因此,平台可以选择任何整数基类型sig_atomic_t,因为它可以保证volatile sig_atomic_t可以安全地用于信号处理程序.许多平台选择int了这个,因为他们知道对他们int来说是用一条指令写的.

最新的C标准C11具有原子类型,但这是完全不同的东西.其中一些(那些"无锁")也可能用于信号处理程序,但这又是一个完全不同的故事.

  • @Satchit,他们没有区别对待.使用普通`int`的平台可以保证`volatile int'足以用于信号处理程序.这通常不是用户应该或可能知道的,但编译器实现者必须查找并为此选择正确的基本类型.而且``sig_atomic_t`不是原子类型**. (4认同)
  • *`sig_atomic_t` 不是原子数据类型*。`sig_atomic_t` 的定义是:“定义的类型是 `sig_atomic_t`,它是一个对象的(可能是易失性限定的)整数类型,即使存在异步中断,也可以作为原子实体进行访问。” 该标准明确指出“`sig_atomic_t` ...是...一个可以作为原子实体访问的对象。” 在多线程上下文中仍然存在可见性问题(并且“易失性”无助于解决这些问题),但访问本身似乎需要是原子的。 (4认同)
  • @Satchit,C11 之前的 C 甚至没有线程模型,因此 C 标准的类型 `sig_atomic_t` 根本没有假设这是否适用于多线程。是的,通常它不适合线程间通信,不要为此目的使用它。`volatile` 也与线程安全性没有太大关系。正如我所说,引入线程的 C11 也引入了适当的原子数据类型。 (2认同)
  • @AndrewHenle,实际上,在这种情况下,原子一词并没有得到很好的定义。它可以意味着不同的东西,在这里它只是意味着“不可分割的”。这个定义与后来在 C11 标准中添加的 atomic 定义不同。 (2认同)

Max*_*kin 11

请注意,这sig_atomic_t不是线程安全的,只有异步信号安全.

原子学涉及两种类型的障碍:

  1. 编译器障碍.它确保编译器不会对读取/写入其他变量的原子变量重新排序读取/写入.这就是volatile关键字的作用.
  2. CPU障碍和可见性.它确保CPU不会重新排序读取和写入.在x86上,对齐1,2,4,8字节存储的所有加载和存储都是原子的.可见性可确保商店对其他线程可见.同样,在Intel CPU上,由于缓存一致性和内存一致性协议MESI,存储可立即显示给其他线程.但这可能会在未来发生变化.有关详细信息,请参阅英特尔®64和IA-32架构软件开发人员手册第3A卷中的§8.1锁定的原子操作.

对于主题手表原子武器的综合处理:C++记忆模型和现代硬件.

  • 不相干。即使`sig_atomic_t`的名称具有原子的,它也不是原子的数据类型。 (2认同)
  • @JensGustedt [C11 标准](http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf) 将 `sig_atomic_t` 始终定义为原子对象:“定义的类型是`sig_atomic_t`,它是一个对象的(可能是易失性限定的)整数类型,即使存在异步中断,也可以作为原子实体进行访问。” (2认同)
  • @MaximEgorushkin你误解了这个定义.`sig_atomic_t`始终是原子*."甚至存在异步中断"定义的一部分并不限制异步中断的原子性,它只是强调要求原子性包含它们.请注意,我并不是说`sig_atomic_t`是线程安全的 - 这确实需要使用障碍.但是,原子性确实意味着可以在没有互斥体之类的情况下访问*whole*值以保证完整性.*仍然需要解决线程安全所需的Visiblity*更改. (2认同)

Bas*_*tch 7

sig_atomic_t通常只是typedef(对某些系统特定的整数类型,通常intlong).使用volatile sig_atomic_t(不仅仅是sig_atomic_t单独使用)非常重要.

添加volatile关键字时,编译器必须避免大量优化.

最近的C11  标准中添加_Atomic<stdatomic.h>.你需要一个非常新的GCC(例如4.9)来支持它.