Как компилятор или ОС различают тип sig_atomic_t и нормальную переменную типа int и гарантирует, что операция будет атомарной? Программы, использующие оба, имеют одинаковый код ассемблера. Как сделать дополнительную операцию, чтобы сделать операцию атомой?
Как работает sig_atomic_t?
Ответ 1
sig_atomic_t
не является типом данных атома. Это только тип данных, который вы можете использовать в контексте обработчика сигналов, вот и все. Поэтому лучше читать имя как "атомный относительно обработки сигналов".
Чтобы гарантировать связь с обработчиком сигналов и от него, требуется только одно из свойств атомных типов данных, а именно тот факт, что чтение и обновление всегда будут видеть согласованное значение. Другие типы данных (например, возможно, long long
) могут быть записаны с несколькими инструкциями ассемблера для нижней и верхней частей, например. sig_atomic_t
гарантированно читается и записывается за один раз.
Таким образом, платформа может выбрать любой целочисленный базовый тип как sig_atomic_t
, для которого он может гарантировать, что volatile sig_atomic_t
можно безопасно использовать в обработчиках сигналов. Многие платформы выбрали для этого int
, потому что они знают, что для них int
записывается с одной инструкцией.
Последний C-стандарт C11 имеет атомные типы, но это совершенно другая вещь. Некоторые из них (те, которые являются "неблокируемыми" ) также могут использоваться в обработчиках сигналов, но это опять-таки совершенно другая история.
Ответ 2
Обратите внимание, что sig_atomic_t
не является потокобезопасным, только безопасным для асинхронного сигнала.
Атомы включают два типа барьеров:
- Предел компилятора. Он гарантирует, что компилятор не изменяет порядок чтения/записи с/на атомную переменную относительно чтения и записи на другие переменные. Это ключевое слово
volatile
. - ЦП и видимость ЦП. Он гарантирует, что процессор не будет изменять порядок чтения и записи. На x86 все нагрузки и хранилища в выровненном 1,2,4,8-байтовом хранилище являются атомарными. Видимость гарантирует, что магазины станут видимыми для других потоков. Опять же, на процессорах Intel магазины сразу видны для других потоков из-за согласования когерентности и протокола согласования памяти MESI. Но это может измениться в будущем. Подробнее см. В §8.1 "ЗАБЛОКИРОВАННЫЕ АТОМНЫЕ ОПЕРАЦИИ" в Руководстве разработчиков программного обеспечения Intel® 64 и IA-32, том 3A.
Для всестороннего рассмотрения тематических часов атомное оружие: модель памяти С++ и современное оборудование.
Ответ 3
sig_atomic_t
часто бывает просто typedef
(к некоторому системному интегральному типу, обычно int
или long
). И очень важно использовать volatile sig_atomic_t
(не только sig_atomic_t
).
Когда вы добавляете ключевое слово volatile
, компилятор должен избегать множества оптимизаций.
Недавно добавлен C11 _Atomic
и <stdatomic.h>
. Вам понадобится очень недавний GCC (например, 4.9), чтобы он поддерживался.
Ответ 4
Программы, использующие оба, имеют одинаковый код ассемблера. Как сделать дополнительную операцию, чтобы сделать операцию атомой?
Хотя это старый вопрос, я думаю, что он по-прежнему стоит рассматривать эту часть вопроса конкретно. В Linux sig_atomic_t
предоставляется glibc. sig_atomic_t
в glibc является typedef для int
и не имеет специального лечения (начиная с этого поста). glibc docs адресуется к этому:
На практике вы можете предположить, что int является атомарным. Вы также можете предположить что типы указателей являются атомарными; это очень удобно. Оба из них предположения верны для всех машин, которые Библиотека GNU C поддерживает и на всех POSIX-системах, о которых мы знаем.
Другими словами, бывает так, что обычный int
уже удовлетворяет требованиям sig_atomic_t
на всех платформах, поддерживаемых glibc, и никакой специальной поддержки не требуется. Тем не менее, стандарты C и POSIX гарантируют sig_atomic_t
, потому что может быть какая-то экзотическая машина, на которой мы хотим реализовать C и POSIX, для которых int
не соответствует требованиям sig_atomic_t
.
Ответ 5
Этот тип данных выглядит атомарным.
С здесь:
24.4.7.2 Атомарные типы Чтобы избежать неопределенности в прерывании доступа к переменной, вы можете использовать конкретный тип данных, для которого доступ всегда атомарный: sig_atomic_t. Чтение и запись этого типа данных гарантированно произойдет в одной инструкции, поэтому нет никакого способа для обработчик для запуска "в середине" доступа.
Тип sig_atomic_t всегда является целочисленным типом данных, но какой это и сколько битов в нем содержится, может отличаться в зависимости от компьютера.
Тип данных: sig_atomic_t Это целочисленный тип данных. Объекты этого тип всегда доступен атомарно.
На практике вы можете предположить, что int является атомарным. Вы также можете предположить, типы указателей являются атомарными; это очень удобно. Оба эти допущения верны на всех машинах, которые библиотека GNU C поддерживает и во всех известных нам системах POSIX.