10.5 Создание процесса |
Предыдущая Содержание Следующая |
Создание процесса в Linux осуществляется с помощью системного вызова fork(). fork() создаёт для вызывающей стороны новый дочерний процесс. Как только fork возвращается, порождающий и порождённый становятся двумя независимыми субъектами, имеющими разные PID-ы. Теоретически, то, что необходимо сделать fork(), это создать точную копию всех структур данных родительского процесса, включая страницы памяти родительского процесса, доступные только ему. В Linux это дублирование страниц памяти родительского процесса является отложенным. Вместо этого порождающий и дочерний процессы совместно используют одни и те же страницы в памяти, пока один из них не попытается изменить общие страницы. Такой подход называется COW (Copy on Write, копирование при записи). Теперь давайте посмотрим, как fork() достигает этого. Мы обсудим реализацию fork в Linux 2.6. В Linux 2.4 API называются по другому, но функциональность осталась прежней.
1.Создаётся новая структура задачи процесса для дочернего процесса. 2.Получается PID для дочернего процесса. 3.Из родительского в дочерний процесс копируются файловые дескрипторы, обработчики сигналов, политики планировщика и так далее. 4.Порождённый процесс добавляется в очередь планировщика задач и выполняется возврат.
Как только fork возвращается, дочерний процесс становится работоспособным процессом и будет запланирован в соответствии с политикой планирования родительского процесса. Обратите внимание, что в fork копируются только структуры данных родительского процесса. Его сегменты текста, данных и стека не копируются. fork пометила такие страницы как COW для последующего выделения памяти по требованию. На шаге 3 функция copy_mm() по существу помечает страницы родителя как общие только читаемые между родителем и потомком. Атрибут "только чтение" гарантирует, что содержимое памяти не может быть изменено, пока оно является общим. Всякий раз, когда любой из двух процессов пытается записать в эту страницу, обработчик ошибки страницы определяет COW страницу с помощью специальной проверки дескрипторов страницы. Страница, соответствующая ошибке, дублируется и помечается как доступная для записи в процессе, который пытался записать. Исходная страница остаётся защищённой от записи, пока другой процесс не попытается выполнить запись, в течение которой эта страница помечается доступной для записи только после проверки, что она уже не используется каким-то другим процессом. Как показано выше, процесс дублирования в Linux, осуществляемый через COW, реализован с помощью обработчика ошибки страницы и, следовательно, uClinux не поддерживает fork(). Также для родителя и потомка невозможно иметь аналогичное виртуальное адресное пространство, как это ожидается от fork. Вместо использования для создания дочернего процесса fork(), разработчики uClinux предлагают использование vfork() вместе с exec(). Системный вызов vfork() создаёт дочерний процесс и блокирует выполнение родительского процесса, пока потомок не завершит работу или не выполнит новую программу. Это гарантирует, что родительскому и дочернему процессам не требуется иметь общий доступ к страницам памяти.
|
Предыдущая Содержание Следующая |