В главе 9 книги [Stevens & Rago, 2005] представлен материал, похожий на тот, что был рассмотрен нами здесь, включая поэтапное описание установления сессии во время входа в систему. Справочное руководство к библиотеке glibc содержит пространное описание функций, связанных с системой управления заданиями и ее реализацией в рамках командной оболочки. В стандарте SUSv3 можно найти подробное обсуждение сессий, групп процессов и управления заданиями.
34.1. Представьте, что родительский процесс выполняет следующие шаги:
/* Вызываем fork(), чтобы ряд дочерних процессов, каждый
из которых остается в одной группе с родителем */
/* Чуть позже… */
signal(SIGUSR1, SIG_IGN); /* Родитель становится нечувствительным к SIGUSR1 */
killpg(getpgrp(), SIGUSR1); /* Отправляем сигнал потомкам, созданным ранее */
К какой проблеме может привести данный подход (вспомните конвейеры в командной оболочке)? Как ее можно избежать?
34.2. Напишите программу, которая подтверждает, что родительский процесс может изменить идентификатор PGID одного из своих потомков до того, как тот выполнит вызов exec(), но не после.
34.3. Напишите программу, которая подтверждает, что вызов setsid(), сделанный из лидера группы процессов, завершается неудачей.
34.4. Модифицируйте программу из листинга 3.4 (disc_SIGHUP.c), чтобы проверить, что ядро не отправляет сигнал SIGHUP участнику активной группы, если тот не приводит к завершению контролирующего процесса.
34.5. Представьте, что код, который разблокирует сигнал SIGTSTP в листинге 34.6, был перемещен в начало обработчика. К какому состоянию гонки это может привести?
34.6. Напишите программу, которая подтверждает, что операция read() возвращает ошибку EIO, если попытаться ее выполнить внутри процесса из осиротевшей группы в контролирующем терминале.
34.7. Напишите программу, которая подтверждает, что сигналы SIGTTIN, SIGTTOU или SIGTSTP, если отправить их члену осиротевшей группы процессов, отменяются (то есть не имеют никаких последствий), при условии, что они могли бы привести к остановке процесса (то есть если они имеют действие SIG_DFL); однако, если они имеют соответствующий обработчик, их доставка проходит успешно.
35. Приоритеты процессов и их планирование
Эта глава посвящена различным системным вызовам и атрибутам, которые определяют, какой процесс в какой момент времени получит доступ к процессору (-ам). Мы начнем с описания значения nice — свойства процесса, которое влияет на количество процессорного времени, выделяемого ему планировщиком ядра. После этого мы перейдем к программному интерфейсу POSIX для планирования в режиме реального времени. Этот программный интерфейс позволяет устанавливать политику и приоритет планирования процессов, предоставляя более строгий контроль над выделением ресурсов процессора. В конце мы уделим внимание системным вызовам для задания маски родственного процессора, определяющей набор процессоров, на которых должен выполняться процесс.
В Linux, как и в большинстве других реализаций UNIX, для распределения ресурсов процессора по умолчанию применяется
•
•
Алгоритм циклического разделения времени не дает процессам прямого контроля над тем, когда и как долго они смогут задействовать центральный процессор. По умолчанию каждый процесс поочередно получает доступ к процессору, пока не истечет его квант времени или пока он сам не освободит ресурсы (например, путем переключения в спящий режим или чтения с диска). Если все процессы пытаются использовать ЦПУ с максимальной интенсивностью (то есть когда ни один из них не переходит в режим сна или блокируется в результате операций ввода/вывода), они получат примерно одинаковый объем ресурсов процессора.