Операционная система UNIX - страница 102
(round robin).[38] Этот механизм запускается ядром через каждый временной квант для наиболее приоритетной очереди. Однако если в системе появляется готовый к запуску процесс с более высоким приоритетом, чем текущий, он будет запущен, не дожидаясь прошествия временного кванта. С другой стороны, если все процессы, готовые к запуску, находятся в низкоприоритетных по отношению к текущему процессу очередях, последний будет продолжать выполняться и в течение следующего временного кванта.
Создание процесса
Как уже обсуждалось, в UNIX проведена четкая грань между программой и процессом. Каждый процесс в конкретный момент времени выполняет инструкции некоторой программы, которая может быть одной и той же для нескольких процессов.[39] Примером может служить командный интерпретатор, с которым одновременно работают несколько пользователей, таким образом инструкции программы shell выполняют несколько различных процессов. Такие процессы могут совместно использовать один сегмент кода в памяти, но в остальном они являются изолированными друг от друга и имеют собственные сегменты данных и стека.
В любой момент процесс может запустить другую программу и начать выполнять ее инструкции; такую операцию он может сделать несколько раз.
В операционной системе UNIX имеются отдельные системные вызовы для создания (порождения) процесса, и для запуска новой программы. Системный вызов fork(2) создает новый процесс, который является точной копией родителя. После возвращения из системного вызова оба процесса выполняют инструкции одной и той же программы и имеют одинаковые сегменты данных и стека.
Тем не менее между родительским и дочерним процессом имеется ряд различий:
□ Дочернему процессу присваивается уникальный идентификатор PID, отличный от родительского.
□ Соответственно и идентификатор родительского процесса PPID для родителя и потомка различны.
□ Дочерний процесс получает собственную копию u-area и, в частности, собственные файловые дескрипторы, хотя он разделяет те же записи файловой таблицы.
□ Для дочернего процесса очищаются все ожидающие доставки сигналы.
□ Временная статистика выполнения процесса в режиме ядра и задачи для дочернего процесса обнуляется.
□ Блокировки памяти и записей, установленные родительским процессом, потомком не наследуются.
Более подробно наследуемые характеристики представлены в табл. 3.4.
Таблица 3.4. Наследование установок при создании процесса и запуске программы
Атрибут | Наследование потомком (fork(2)) | Сохранение при запуске программы (exec(2)) |
---|---|---|
Сегмент кода (text) | Да, разделяемый | Нет |
Сегмент данных (data) | Да, копируется при записи (copy-on-write) | Нет |
Окружение | Да | Возможно |
Аргументы | Да | Возможно |
Идентификатор пользователя UID | Да | Да |
Идентификатор группы GID | Да | Да |
Эффективный идентификатор пользователя EUID | Да | Да (Нет, при вызове setuid(2)) |
Эффективный идентификатор группы EGID | Да | Да (Нет, при вызове setgid(2)) |
ID процесса (PID) | Нет | Да |
ID группы процессов | Да | Да |
ID родительского процесса (PPID) | Нет | Да |
Приоритет nice number | Да | Да |
Права доступа к создаваемому файлу | Да | Да |
Ограничение на размер файла | Да | Да |
Сигналы, обрабатываемые по умолчанию | Да | Да |
Игнорируемые сигналы | Да | Да |
Перехватываемые сигналы | Да | Нет |
Файловые дескрипторы | Да | Да, если для файлового дескриптора не установлен флаг >FD_CLOEXEC (например, с помощью fcntl(2)) |
Файловые указатели | Да, разделяемые | Да, если для файлового дескриптора не установлен флаг >FD_CLOEXEC (например, с помощью fcntl(2)) |
В общем случае вызов fork(2) выполняет следующие действия:
□ Резервирует место в области свопинга для сегмента данных и стека процесса.
□ Размещает новую запись >proc
в таблице процессов и присваивает процессу уникальный идентификатор PID.
□ Инициализирует структуру >proc
(поля структуры proc подробно рассматривались в разделе "Структуры данных процесса").
□ Размещает карты отображения, необходимые для трансляции адреса.
□ Размещает u-area процесса и копирует ее содержимое с родительского.
□ Создает соответствующие области процесса, часть из которых совпадает с родительскими.
□ Инициализирует аппаратный контекст процесса, копируя его с родительского.
□ Устанавливает в ноль возвращаемое дочернему процессу вызовом