В FreeBSD новые процессы создаются с помощью семейства системных вызовов fork. Системный вызов fork создает полную копию родительского процесса. Системный вызов rfork создает элемент нового процесса, который вместо копирования всего разделяет со своим родителем выбранный набор ресурсов. Системный вызов vfork отличается от fork в том, как рассматриваются ресурсы виртуальной памяти; vfork гарантирует также, что родитель не будет запущен до тех пор, пока порожденный процесс не выполнит системный вызов либо exec, либо exit.
0Процесс, созданный с помощью fork, обозначается как порожденный процесс первоначального родительского процесса. С точки зрения пользователя, порожденный процесс является точным дубликатом родительского процесса, за исключением двух значений: PID порожденного процесса и PID родителя. Вызов fork возвращает PID порожденного процесса в процесс родителя и ноль в порожденный процесс. Таким образом, программа может определить, является ли этот процесс родительским или порожденным, проверив возвращаемое fork значение.
Вызов fork включает три главных шага.
- Выделение и инициализация новой структуры процесса для порожденного процесса. Дублирование для порожденного процесса контекста родителя (включая структуру потока и ресурсы виртуальной памяти). Планирование выполнения порожденного процесса.
Поэтому здесь будут описаны лишь те действия, которые относятся к управлению процессами.
Ядро начинает с выделения памяти для нового процесса и элементов потоков (см. рис. 4.1). Эти элементы потоков и процесса инициализируются за три шага: одна часть копируется из соответствующей структуры родителя, другая часть обнуляется, а остальное инициализируется явным образом. Обнуляемые поля включают недавнее использование процессора, канал ожидания, время подкачки и сна, таймеры, трассировку и сведения об ожидающих сигналах. Скопированные части включают все привилегии и ограничения, унаследованные от родителя, включая следующее:
- группу процесса и сеанс; состояние сигналов (маски игнорируемых, перехватываемых и блокируемых сигналов); параметр планирования kgjiice; ссылку на мандат родителя ссылку на родительский набор открытых файлов; ссылку на ограничения родителя.
Явным образом устанавливаемая информация включает: элемент в списке всех процессов;
- элемент в списке порожденных процессов родителя и обратный указатель на родителя; элемент в списке групп процессов родителя; элемент в хеш-структуре, которая позволяет искать процессы по их PID; указатель на структуру статистики процесса, выделенную в его структуре пользователя; указатель на структуру действий сигналов процесса, выделенную в его структуре пользователя; новый PID для процесса.
Новый PID должен быть уникальным среди всех процессов. Ранние версии BSD проверяли уникальность PID, осуществляя линейный поиск в таблице процессов. Этот поиск стал на больших системах со множеством процессов неприемлемым. FreeBSD поддерживает диапазон невыделенных PID между lastpid и pidchecked. Она выделяет новый PID, увеличивая и используя значение lastpid. Когда вновь выбранный PID достигает значения pidchecked, система вычисляет новый диапазон неиспользуемых PID, осуществляя единственное сканирование всех существующих процессов (сканируются не только активные - проверяются также зомби и процессы, сброшенные на диск).
Последним шагом является копирование адресного пространства родителя. Для дублирования образа процесса ядро использует средства управления памятью, вызывая vm_forkproc(). Процедуре vmforkproc() передается указатель на инициализированную структуру порожденного процесса, она должна выделить все ресурсы, которые нужны порожденному процессу для выполнения. Вызов vmforkproc() возвращается через другой путь выполнения непосредственно в режим пользователя в порожденном процессе и через обычный путь выполнения в процесс родителя.
После полного построения порожденного процесса о его потоке сообщается планировщику через помещение его в очередь выполнения. Альтернативный путь возврата установит в порожденном процессе возвращаемое системным вызовом fork значение в 0. Путь возврата обычного выполнения в родителе установит возвращаемое значение системного вызова fork равным новому PID.
- 10/10/2010 22:11 - История сигналов
- 10/10/2010 01:09 - Процедуры вычисления приоритета потока
- 09/10/2010 12:36 - Сигналы
- 06/10/2010 04:14 - Вычисления приоритета потоков
- 05/10/2010 23:55 - Планирование потоков с разделением времени
- 01/10/2010 01:49 - Планировщик 4.4BSD
- 28/09/2010 13:03 - Функции планировщика ULE
- 27/09/2010 22:41 - Планировщик ULE
- 22/09/2010 20:46 - Планирование потоков
- 20/09/2010 00:36 - Другие виды синхронизации