Linux программирование в примерах
Шрифт:
На языке Unix, помимо названия системного вызова, слово «fork» является и глаголом, и существительным [88] . Мы можем сказать, что «один процесс ответвляет другой», и что «после разветвления работают два процесса». (Думайте «развилка (fork) на дороге», а не «вилка (fork), нож и ложка».)
9.1.1.1. После
Порожденный процесс «наследует» идентичные копии большого числа атрибутов от родителя. Многие из этих атрибутов специализированы и здесь неуместны. Поэтому следующий список намеренно неполон. Существенны следующие:
88
Fork (англ.) —
• Окружение, см. раздел 2.4 «Окружение».
• Все открытые файлы и открытые каталоги; см. раздел 4.4.1 «Понятие о дескрипторах файлов» и раздел 5.3.1 «Базовое чтение каталогов».
• Установки umask; см. раздел 4.6 «Создание файлов».
• Текущий рабочий каталог; см раздел 8.4.1 «Смена каталога:
• Корневой каталог; см. раздел 8.6 «Изменение корневого каталога:
• Текущий приоритет (иначе называемый «значение nice»; вскоре мы это обсудим; см раздел 9.1.3 «Установка приоритета процесса:
• Управляющие терминалы. Это устройство терминала (физическая консоль или окно эмулятора терминала), которому разрешено посылать процессу сигналы (такие, как CTRL-Z для прекращения выполняющихся работ). Это обсуждается далее в разделе 9.2.1 «Обзор управления работой».
• Маска сигналов процесса и расположение всех текущих сигналов (еще не обсуждалось; см. главу 10 «Сигналы»).
• Реальный, эффективный и сохраненный ID пользователя, группы и набора дополнительных групп (еще не обсуждалось; см. главу 11 «Права доступа и ID пользователя и группы»).
Помимо возвращаемого значения
• У каждого есть уникальный ID процесса и ID родительского процесса (PID и PPID) Они описаны в разделе 9.1.2 «Идентификация процесса:
• PID порожденного процесса не будет равняться ID любой существующей группы процессов (см. раздел 9.2 «Группы процессов»).
• Аккумулированное время использования процессора для порожденного процесса и его будущих потомков инициализируется нулем. (Это имеет смысл; в конце концов, это совершенно новый процесс.)
• Любые сигналы, которые были ожидающими в родительском процессе, в порожденном сбрасываются, также как ожидающие аварийные сигналы и таймеры. (Мы еще не рассматривали эти темы; см. главу 10 «Сигналы» и раздел 14.3.3 «Интервальные таймеры:
• Блокировки файлов в родительском процессе не дублируются в порожденном (также еще не обсуждалось; см. раздел 14.2 «Блокировка файлов»).
9.1.1.2. Разделение дескрипторов файлов
Атрибуты, которые порожденный процесс наследует от родителя, устанавливаются в те же значения, которые были в родительском процессе в момент выполнения
Открытые файлы являются важным исключением из этого правила. Дескрипторы открытых файлов
являются разделяемыми, и действия одного процесса с разделяемым дескриптором файла затрагивает состояние файла также и для другого процесса. Это лучше всего понять, изучив рис. 9.1.Рис. 9.1. Разделение дескрипторов файлов
Рисунок отображает внутренние структуры данных ядра. Ключевой структурой данных является таблица файлов. Каждый элемент ссылается на открытый файл. Помимо других учетных данных, таблица файлов содержит текущее положение (смещение чтения/записи) в файле. Оно устанавливается либо автоматически каждый раз при чтении или записи файла, либо непосредственно через
Дескриптор файла, возвращенный функциями
На рис. 9.1 показаны два процесса, разделяющие стандартный ввод и стандартный вывод; для каждого из процессов указаны одни и те же элементы в таблице файлов. Поэтому, когда процесс 45 (порожденный) осуществляет
Это легко можно видеть на уровне оболочки:
Первая исполняемая строка