Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лекции_по_ОС / ТОС_6_3_проц_слайды1.doc
Скачиваний:
44
Добавлен:
03.03.2016
Размер:
1.56 Mб
Скачать

Создание процесса

Каждый процесс в конкретный момент времени выполняет инструкции некоторой программы, которая может быть одной и той же для нескольких процессов.

Пример: командный интерпретатор, с которым одновременно работают несколько пользователей, т.о. инструкции программы shell выполняют несколько различных процессов.

Такие процессы могут совместно использовать один сегмент кода в памяти, но имеют собственные сегменты данных и стека.

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

В ОС UNIX имеются отдельные системные вызовы для создания (порождения) процесса, и для запуска новой программы.

Системный вызов fork() создает новый процесс, который является точной копией родителя. После возвращения из системного вызова оба процесса выполняют инструкции одной и той же программы и имеют одинаковые сегменты данных и стека.

Различия между родительским и дочерним процессом:

- Дочернему процессу присваивается уникальный идентификатор PID, отличный от родительского.

Речь здесь идет о выполнении в режиме задачи.

- Соответственно и идентификатор родительского процесса PPID для родителя и потомка различны.

- Дочерний процесс получает собственную копию u-area и, собственные файловые дескрипторы, хотя он разделяет те же записи файловой таблицы.

В u-area хранятся данные, которые используются многими подсистемами ядра и не только для управления процессом. В частности, там содержится информация об открытых файловых дескрипторах, диспозиция сигналов, статистика выполнения процесса, а также сохраненные значения регист­ров, когда выполнение процесса приостановлено. Очевидно, что процесс не должен иметь возможности модифицировать эти данные произвольным образом, поэтому u-area защищена от доступа в режиме задачи.

- Для дочернего процесса очищаются все ожидающие доставки сигналы.

- Временная статистика выполнения процесса в режиме ядра и задачи для дочернего процесса обнуляется.

- Блокировки памяти и записей, установленные родительским процессом, потомком не наследуются.

Более подробно наследуемые характеристики представлены в табл. 3.4.

Таблица 3.4. Наследование установок при создании процесса и запуске программы

Атрибут

Наследование по­томком (fork())

Сохранение при запус­ке программы (ехес())

Сегмент кода (text)

Да, разделяемый

Нет

Сегмент данных (data)

Да, копируется при записи (copy-on-write)

Нет

Окружение

Да

Возможно

Аргументы

Да

Возможно

Идентификатор пользова­теля UID

Идентификатор группы GID

Да

Да

Эффективный идентифика­тор пользователя EUID

Да

Да

Эффективный идентифика­тор группы EGID

Да

Да (Нет, при вызове setgid(2))

ID процесса (РID)

Нет

Да

ID группы процессов

Да

Да

ID родительского процесса (PPID)

Нет

Да

Приоритет nice number

Да

Да

Права доступа к создаваемому файлу

Да

Да

Ограничение на размер файла

Да

Да

Сигналы, обрабатываемые по умолчанию

Да

Да

Игнорируемые сигналы

Да

Да

Таблица 3.4 (продолжение)

Атрибут

Наследование по­томком (fork(2))

Сохранение при запус­ке программы (ехес(2))

Перехватываемые сигналы

Да

Нет

Файловые дескрипторы

Да

Да, если для файлового де­скриптора не установлен флаг fd_cloexec (например, с помощью fcntl(2))

Файловые указатели

Да, разделяемые

Да, если для файлового де­скриптора не установлен флаг FD_CLOEXEC (например, с помощью fcntl(2))

В общем случае вызов fork() выполняет следующие действия:

-Резервирует место в области свопинга для сегмента данных и стека процесса.

-Размещает новую запись рrос в таблице процессов и присваивает процессу уникальный идентификатор PID.

- Инициализирует структуру рrос

p_stat

Состояние процесса (выполнение, приостановлен, сон и т. д.)

p_pri

Текущий приоритет процесса

p_flag

Флаги, определяющие дополнительную инфор-мацию о состоянии процесса

p_uid

UID процесса

p_suid

EUID процесса

p_sid

Идентификатор сеанса

p_pgrp

Идентификатор группы процессов (равен иден-тификатору лидера группы)

p_pid

Идентификатор процесса (РID)

p_ppid

Идентификатор родительского процесса (PPID)

p_sig

Сигналы, ожидающие доставки

p_size

Размер адресного пространства процесса в страницах

p_utime

Время выполнения в режиме задачи

p_stime

Время выполнения в режиме ядра

p_ldt

Указатель на LDT процесса

*p_region

Список областей памяти процесса

p_xstat

Код возврата, передаваемый родительскому процессу

p_utbl []

Массив записей таблицы страниц для u-area

-Размещает карты отображения, необходимые для трансляции адреса.

-Размещает u-area процесса и копирует ее содержимое с родительского.

-Создает соответствующие области процесса, часть из которых совпадает с родительскими.

-Инициализирует аппаратный контекст процесса, копируя его с родительского.

- Устанавливает в ноль возвращаемое дочернему процессу вызовом fork() значение.

- Устанавливает возвращаемое родительскому процессу вызовом fork() значение равным PID потомка.

-Помечает процесс готовым к запуску и помещает его в очередь на выполнение.

Системный вызов fork() в итоге создает для дочернего процесса отдельную копию адресного пространства родителя.

Во многих случаях, вскоре после этого, дочерний процесс делает системный вызов ехeс() для запуска новой программы, при этом существующее адресное пространство уничтожается и создается новое.

Т.о. создание фактической копии адресного пространства процесса, т. е. выделение ОП и создание соответствующих карт отображения, является неоправданным.

Для решения данной проблемы используются два подхода.

Первый из них, предложенный в UNIX System V, называется "копирование при записи" (copy-on-write или COW). Суть в том, что сегменты данных и стека родительского процесса помечаются доступными только для чтения, а дочерний процесс, хотя и получает собственные карты отображения, разделяет эти сегменты с родительским.

Другими словами, сразу после создания процесса и родитель и потомок адресуют одни и те же страницы физической памяти.

Если какой-либо из двух процессов попытается модифицировать данные или стек, возникнет страничная ошибка, поскольку страница открыта только для чтения, а не для записи. При этом будет запущен обработчик ошибки ядра, который создаст для процесса копию этой страницы, доступную для записи.

Т.о., фактическому копированию подлежат только модифицируемые страницы, а не все адресное пространство процесса.

Если дочерний процесс делает системный вызов ехес() или вообще завершает свое выполнение, права доступа к страницам родителя, имеющим флаг COW, возвращаются к их прежним значениям (т. е. до создания дочернего процесса), а флаг COW очищается.

Другой подход используется в BSD UNIX. В этой версии системы был пред­ложен новый системный вызов — vfork(). Использование этого вызова име­ет смысл, когда дочерний процесс сразу же выполняет вызов eхес() и за­пускает новую программу.

При вызове vfork(2) родительский процесс пре­доставляет свое адресное пространство дочернему и переходит в состояние сна, пока последний не вернет его обратно.

Далее дочерний процесс выполняется в адресном пространстве родителя, пока не делает вызов ехес() или exit(), после чего ядро возвращает адресное пространство родителю и пробуждает его.

С помощью vfork(2) можно добиться максимального быстродействия, т. к. в этом случае мы полностью избегаем копирования, даже для карт отображения. Вместо этого адресное пространство родительского процесса предоставляется потомку передачей нескольких аппаратных регистров, отвечающих за трансляцию адресов.

Однако vfork(2) таит в себе потенциальную опасность, поскольку позволяет одному процессу использовать и даже модифицировать адресное пространство другого.

Для управления памятью процесса ядру необходимо соответствующим образом задать области. При этом структуры pregion дочернего процесса, соответствующие разделяемым областям, указывают на те же структуры region, что и для родителя.

Для областей, совместное использование которых недопустимо, ядро размещает отдельные структуры region для дочернего процесса (изначально копируя их содержимое с родительского) и устанавливает соответствующие указатели. На рис. 3.15 представлена схема этих операций. Заметим, что совместная работа и дублирование областей являются отдельным механизмом, не связанным с рассмотренными выше подходами, для совместного использования адресного пространства, на­пример COW. Так, после создания отдельной копии неразделяемой области она по-прежнему будет адресовать те же страницы памяти, что и соответствующая область родителя.