c - signal man linux
¿Cómo funciona realmente sig_atomic_t? (5)
¿Cómo distingue el compilador o el sistema operativo entre el tipo sig_atomic_t y una variable normal de tipo int, y garantiza que la operación sea atómica? Los programas que usan ambos tienen el mismo código de ensamblador. ¿Qué cuidado adicional se toma para que la operación sea atómica?
Los programas que usan ambos tienen el mismo código de ensamblador. ¿Qué cuidado adicional se toma para que la operación sea atómica?
Aunque esta es una pregunta antigua, creo que todavía vale la pena abordar esta parte de la pregunta específicamente. En Linux, sig_atomic_t
es proporcionado por glibc. sig_atomic_t
en glibc es un typedef para int
y no tiene un tratamiento especial (a partir de este post). Los documentos de glibc abordan esto:
En la práctica, puedes asumir que int es atómico. También puedes asumir que los tipos de punteros son atómicos; eso es muy conveniente Ambas suposiciones son ciertas en todas las máquinas que admite la biblioteca GNU C y en todos los sistemas POSIX que conocemos.
En otras palabras, da la casualidad de que regular int
ya satisface los requisitos de sig_atomic_t
en todas las plataformas compatibles con glibc y no se necesita soporte especial. No obstante, los estándares C y POSIX exigen sig_atomic_t
porque podría haber alguna máquina exótica en la que deseamos implementar C y POSIX para la cual int
no cumple los requisitos de sig_atomic_t
.
Este tipo de datos parece ser atómico. Desde aquí: https://www.gnu.org/software/libc/manual/html_node/Atomic-Types.html
24.4.7.2 Tipos atómicos Para evitar la incertidumbre sobre la interrupción del acceso a una variable, puede usar un tipo de datos en particular para el cual el acceso es siempre atómico: sig_atomic_t. Se garantiza que la lectura y escritura de este tipo de datos sucederán en una sola instrucción, por lo que no hay forma de que un controlador se ejecute "en el medio" de un acceso.
El tipo sig_atomic_t es siempre un tipo de datos enteros, pero cuál es, y cuántos bits contiene, puede variar de una máquina a otra.
Tipo de datos: sig_atomic_t Este es un tipo de datos entero. Los objetos de este tipo siempre se acceden de forma atómica.
En la práctica, puedes asumir que int es atómico. También puedes asumir que los tipos de punteros son atómicos; eso es muy conveniente Ambas suposiciones son ciertas en todas las máquinas que admite la biblioteca GNU C y en todos los sistemas POSIX que conocemos.
Tenga en cuenta que sig_atomic_t
no es seguro para subprocesos, solo async-signal safe.
La atómica involucra dos tipos de barreras:
- Barrera compilador. Se asegura de que el compilador no reordene las lecturas / escrituras desde / hacia una variable atómica relativa a las lecturas y escrituras en otras variables. Esto es lo que hace la palabra clave
volatile
. - CPU barrera y visibilidad. Se asegura de que la CPU no reordene las lecturas y escrituras. En x86, todas las cargas y almacenes para almacenamiento de 1,2,4,8 bytes alineado son atómicos. La visibilidad asegura que las tiendas se vuelvan visibles a otros hilos. Nuevamente, en las CPU de Intel, las tiendas son visibles inmediatamente a otros subprocesos debido a la coherencia de caché y al protocolo de coherencia de memoria MESI . Pero eso puede cambiar en el futuro. Consulte el §8.1 OPERACIONES ATÓMICAS BLOQUEADAS en el Manual del desarrollador de software para arquitecturas Intel® 64 e IA-32, Volumen 3A, para obtener más detalles.
Para un tratamiento integral de la materia, vea Armas atómicas: el modelo de memoria C ++ y el hardware moderno .
sig_atomic_t
menudo, sig_atomic_t
es solo un typedef
(para algún tipo integral de sistema, generalmente int
o long
). Y es muy importante utilizar volatile sig_atomic_t
(no solo sig_atomic_t
solo).
Cuando agrega la palabra clave volatile
, el compilador debe evitar muchas optimizaciones.
El reciente estándar C11 agregó _Atomic
y <stdatomic.h>
. Necesita un GCC muy reciente (por ejemplo, 4.9 ) para que sea compatible.
sig_atomic_t
no es un tipo de datos atómico. Es solo el tipo de datos que puede usar en el contexto de un manejador de señales, eso es todo. Así que mejor lea el nombre como "atómico relativo al manejo de la señal".
Para garantizar la comunicación con y desde un manejador de señales, solo se necesita una de las propiedades de los tipos de datos atómicos, a saber, el hecho de que la lectura y la actualización siempre tendrán un valor consistente. Otros tipos de datos (como quizás long long
) podrían escribirse con varias instrucciones de ensamblador para la parte inferior y superior, por ejemplo, se garantiza que la lectura y la escritura de sig_atomic_t
se sig_atomic_t
una sola vez.
Por lo tanto, una plataforma puede elegir cualquier tipo de base de entero como sig_atomic_t
por lo que puede garantizar que el volatile sig_atomic_t
puede usar de manera segura en los manejadores de señales. Muchas plataformas eligieron int
para esto, porque saben que para ellos int
está escrito con una sola instrucción.
El último estándar de C, C11, tiene tipos atómicos, pero son algo completamente diferente. Algunos de ellos (los que están "sin bloqueo") también se pueden usar en los controladores de señales, pero de nuevo es una historia completamente diferente.