Ответ 1
[Q-3] Используется ли переменная
terminate
в моем примереvolatile
? Я видел много примеров, когда эта переменная является изменчивой, а другие, где это не так.
Флаг terminate
должен быть volatile sig_atomic_t
:
Поскольку функции обработчика можно вызывать асинхронно. То есть, обработчик может быть вызван в любой момент программы, непредсказуемо. Если два сигнала поступают в течение очень короткого промежутка времени, один обработчик может работать в другом. И считается, что лучше объявить volatile sig_atomic_t
, этот тип всегда доступен атомарно, избегая неопределенности в отношении прерывания доступа к переменной. volatile
сообщает компилятору не оптимизировать и помещать его в регистр. (читайте: Атомный доступ к данным и обработка сигналов для подробного искупления).
Еще одна ссылка: 24.4.7 Атомный доступ к данным и обработка сигналов.
Кроме того, стандарт C11 в 7.14.1.1-5 указывает, что доступ к объектам из volatile sig_atomic_t
можно получить из обработчика сигнала (доступ к другим имеет поведение undefined).
[Q-4] Я читал, что
signal()
теперь устарел и используетсяsigaction()
. Находятся есть действительно хорошие примеры, чтобы показать, как конвертировать из Предыдущийsignal()
вызов? У меня возникают проблемы с новой структурой, которая Мне нужно создать/передать и как все это сочетается.
Приведенный ниже пример (и ссылка в комментариях) может быть полезен:
// 1. Prepare struct
struct sigaction sa;
sa.sa_handler = sighandler;
// 2. To restart functions if interrupted by handler (as handlers called asynchronously)
sa.sa_flags = SA_RESTART;
// 3. Set zero
sigemptyset(&sa.sa_mask);
/* 3b.
// uncomment if you wants to block
// some signals while one is executing.
sigaddset( &sa.sa_mask, SIGINT );
*/
// 4. Register signals
sigaction( SIGINT, &sa, NULL );
ссылки:
- Начиная программирование на Linux, 4-е издание: в этой книге именно ваш код объясняется с помощью
sigaction()
в разделе "Глава 11: Процессы и сигналы". - документация по sigaction, включая пример (быстрое обучение).
- Библиотека GNU C: Обработка сигналов
* Я начал с 1, Сейчас я читаю 3 GNU-library
[Q-5] Требуется ли второй вызов
signal()
? Есть ли что-то подобное, что мне нужно дляsigaction()
?
Почему вы устанавливаете его для действия по умолчанию до завершения программы для меня непонятно. Я думаю, что следующий параграф даст вам ответ:
Обработка сигналов
Вызов сигнала устанавливает обработку сигнала только для одного появления сигнала. Прежде чем вызывать функцию обработки сигналов, , библиотека сбрасывает сигнал, чтобы действие по умолчанию выполнялось, если снова появляется тот же сигнал. Сброс обработки сигналов помогает предотвратить бесконечный цикл, если, например, действие, выполняемое в обработчике сигнала, снова вызывает тот же сигнал. Если вы хотите, чтобы ваш обработчик использовался для сигнала каждый раз, когда он возникает, вы должны вызвать сигнал в обработчике, чтобы восстановить его. Вы должны быть осторожны в восстановлении обработки сигналов. Например, если вы постоянно восстанавливаете обработку
SIGINT
, вы можете потерять возможность прерывания и завершения вашей программы.
Функция signal()
определяет обработчик только следующего принятого сигнала, после чего восстанавливается обработчик по умолчанию. Поэтому обработчик сигнала необходимо вызвать signal()
, если программе необходимо продолжить обработку сигналов с помощью обработчика, отличного от стандартного.
Прочтите обсуждение для дальнейшего использования: Когда снова включить обработчики сигналов.
[Q-1a] Требуется ли обработка сигналов?
Да, Linux сделает для вас очистку. Например, если вы не закрываете файл или сокет, Linux выполнит очистку после завершения процесса. Но Linux может не понадобиться немедленно выполнить очистку, и может потребоваться некоторое время (возможно, чтобы высокая производительность системы или некоторые другие проблемы). Например, если вы не закрываете tcp-сокет, и программа завершает работу ядра, ядро немедленно не закрывает сокет, чтобы гарантировать, что все данные были переданы, TCP гарантирует доставку, если это возможно.
[Q-1b] Следовательно, могу ли я просто заменить обработчик сигнала только бесконечным циклом и позволить ОС изящно выйти из потоков, де-выделить память и т.д.
Нет, операционная система выполняет очистку только после завершения программы. В то время как процесс выполняется, ресурсы, которые выделяются для этого процесса, не запрашиваются ОС. (ОС не может знать, находится ли ваш процесс в бесконечном цикле или нет - это неразрешимая проблема). Если вы хотите, чтобы после завершения процесса ОС выполняла операции очистки для вас, вам не нужно обрабатывать сигналы (даже если ваш процесс аномально завершен сигналом).
[Q] Все, что я пытаюсь выполнить, чтобы мой основной цикл выполнялся до тех пор, пока не будет ctrl c, или питание не будет отключено, или что-то действительно плохое.
Нет, есть ограничение! Вы не можете поймать все сигналы. Некоторые сигналы не улавливаются, например. SIGKILL
и SIGSTOP
, и оба являются сигналами терминации. Цитирование:
- Макро: int
SIGKILL
Сигнал
SIGKILL
используется для немедленного завершения программы. Он не может быть обработан или проигнорирован и поэтому всегда фатален. Также возможно заблокировать этот сигнал не.
Таким образом, вы не можете сделать программу, которая не может быть прервана (непрерывная программа)!
<суб > Я не уверен, но может быть, вы можете сделать что-то подобное в системах Windows: путем написания TSR (некоторая привязка к режиму ядра). Я помню из своего тезиса, что некоторые вирусы не могут быть прекращены даже из диспетчера задач, но я также считаю, что они обманывают пользователя по разрешениям администратора.
Суб >
Я надеюсь, что этот ответ поможет вам.