C99 sig_atomic_t
conforms only to a very weak definition of "atomicity", because C99 has no concept of concurrency, only interruptibility. (C2011 adds a concurrency model, and with it the _Atomic
types that make stronger guarantees; however, AFAIK sig_atomic_t
is unchanged, since its raison d'être is still communication with signal handlers, not across threads.)
This is everything C99 says about sig_atomic_t
:
(§7.14 <signal.h>
, paragraph 2) The type defined is sig_atomic_t
, which is the (possibly volatile-qualified) integer type of an object that can be accessed as an atomic entity, even in the presence of asynchronous interrupts. (§7.14 <signal.h>
, paragraph 2)
(§7.14p5) If [a] signal occurs other than as the result of calling the abort
or raise
function, the behavior is undefined if the signal handler refers to any object with static storage duration other than by assigning a value to an object declared as volatile sig_atomic_t
.
(§7.18.3 Limits of other integer types, paragraph 3) If sig_atomic_t
(see 7.14) is defined as a signed integer type, the value of SIG_ATOMIC_MIN
shall be no greater than ?127 and the value of SIG_ATOMIC_MAX
shall be no less than 127; otherwise, sig_atomic_t is defined as an unsigned integer type, and the value of SIG_ATOMIC_MIN
shall be 0 and the value of SIG_ATOMIC_MAX
shall be no less than 255.
The term "atomic entity" is not defined anywhere in the standard. Translating from standards-ese, the intent is that the CPU can completely update a variable of type sig_atomic_t
in memory ("static storage duration") with one machine instruction. Thus, in the concurrency-free, precisely interruptible C99 abstract machine, it is impossible for a signal handler to observe a variable of type sig_atomic_t
halfway through an update. The §7.18.3p3 language licenses this type to be as small as char
if necessary. Note please the complete absence of any language relating to cross-processor consistency.
There are real CPUs which require more than one instruction to write a value larger than char
to memory. There are also real CPUs which require more than one instruction to write values smaller than a machine word (often, but not necessarily, the same as int
) to memory. The language in the GNU C Library manual is now inaccurate. It represents a desire on the part of the original authors to eliminate what they saw as unnecessary license for C implementations to do weird shit that made life harder for application programmers. Unfortunately, that very license is what makes it possible to have C at all on some real machines. There is at least one embedded Linux port (to the AVR) for which neither int
nor pointers can be written to memory in one instruction. (People are working on making the manual more accurate, see e.g. http://sourceware.org/ml/libc-alpha/2012-02/msg00651.html -- sig_atomic_t
seems to have been missed in that one, though.)
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…