Когда обработчик сигнала прерывает заблокированный системный вызов, этот системный вызов завершается с ошибкой EINTR. Мы можем воспользоваться этой моделью поведения для, например, установки таймера на блокирующий системный вызов. При необходимости прерванные системные вызовы могут быть перезапущены вручную. Кроме того, установка обработчика сигнала с помощью функции sigaction() с флагом SA_RESTART приводит к автоматическому перезапуску многих (но не всех) системных вызовов.

Дополнительная информация

См. источники, перечисленные в разделе 20.15.

21.7. Упражнение

21.1. Реализуйте функцию abort().

<p>22. Сигналы: дополнительные возможности</p>

В этой главе мы завершим рассматривать сигналы. Здесь мы обсудим некоторые более сложные темы, включая такие, как:

• файлы дампа ядра;

• особые случаи доставки сигнала, его диспозиции и обработки;

• синхронная и асинхронная генерация сигналов;

• когда и в какой очередности доставляются сигналы;

• сигналы реального времени;

• использование функции sigsuspend() для настройки сигнальной маски процесса и ожидания прибытия сигнала;

• использование функции sigwaitinfo() (и sigtimedwait()) для синхронного ожидания доставки сигнала;

• использование функции signalfd() для получения сигнала через файловый дескриптор;

• старые сигнальные API операционной системы BSD.

22.1. Файлы дампа ядра

Некоторые сигналы заставляют процесс создать файл дампа ядра и завершиться (см. табл. 20.1). Дамп ядра — это файл, содержащий образ памяти процесса на момент его завершения. (Термин «ядро» (core) восходит к старой технологии памяти.) Такой образ может быть загружен в отладчик для изучения состояния программного кода и данных в момент получения сигнала.

Одним из способов заставить программу создать файл дампа ядра является ввод символа «выход» (обычно Ctrl+\), вызывающего генерацию сигнала SIGQUIT.

$ ulimit — c unlimited Объяснено в тексте

$ sleep 30

Нажатие Ctrl+\

Quit (core dumped)

$ ls — l core Показывает файл дампа ядра для sleep(1)

— rw- 1 mtk users 57344 Nov 30 13:39 core

В данном примере оболочка распечатывает сообщение Quit (core dumped) после обнаружения того, что дочерний процесс (запустивший программу sleep) был завершен сигналом SIGQUIT с созданием файла дампа ядра.

Файл дампа ядра был создан в рабочем каталоге процесса и назван core. В скором времени будет рассказано, как можно изменить эти настройки по умолчанию.

Во многих реализациях есть инструмент (например, gcore во FreeBSD и Solaris), позволяющий получить дамп ядра запущенного процесса. Аналогичная функциональность доступна и на Linux за счет подключения процесса с помощью gdb и последующего запуска команды gcore.

Обстоятельства, при которых файлы дампа ядра не создаются

Файл дампа ядра не создается в следующих случаях.

• У процесса нет права записи файла дампа ядра. Это может произойти, если у процесса отсутствуют права записи в каталоге, в котором создается файл дампа, или потому, что файл с таким именем уже существует в каталоге и либо недоступен для записи, либо не является обычным файлом (например, это может быть каталог или символьная ссылка).

• Обычный файл с таким именем уже существует и доступен для записи, но на него уже создано несколько (жестких) ссылок.

• Каталог, в котором планируется создание файла дампа, не существует.

• Ограничение ресурсов процесса для размера файла дампа памяти ядра установлено на 0. Это ограничение, RLIMIT_CORE, более подробно рассматривается в разделе 36.3. В вышеприведенном примере мы использовали команду ulimit (limit в оболочке С shell) для гарантии того, что для файлов core никакие ограничения не устанавливаются.

• Ограничение ресурсов процесса для размера файла, которое может быть создано процессом, установлено на 0. Это ограничение, RLIMIT_FSIZE, обсуждается более подробно в разделе 36.3.

• Бинарный исполняемый файл недоступен для чтения. Это не позволяет пользователям обратиться к дампу ядра для получения кода программы, недоступного никаким иным способом.

• Файловая система, в которой находится текущий рабочий каталог, монтирована в режиме «только для чтения», не располагает свободным местом или свободными индексными дескрипторами. Возможно, пользователь также достиг ограничения выделенной ему квоты пространства файловой системы.

• Выполняемая программа с установленным ID пользователя (или с установленным ID группы) не генерирует дамп ядра, если выполняется не владельцем файла (или из группы владельца). Это предотвращает ситуации, когда злоумышленники могут воспользоваться дампом памяти для получения и изучения конфиденциальной информации из программы, например паролей.

Перейти на страницу:

Похожие книги