Системные вызовы для управления процессами

Первая группа вызовов в табл. 1.1 предназначена для управления процессами. Начнем рассмотрение системного вызова fork (разветвление). Вызов fork является единственным существующим в POSIX способом создания нового процесса.
Он создает точную копию исходного процесса, включая все дескрипторы файлов, регистры и т. п. После выполнения вызова fork исходный процесс и его копия (родительский и дочерний процессы) выполняются независимо друг от друга. На момент разветвления все их соответствующие переменные имеют одинаковые значения, но поскольку родительские данные копируются в дочерний процесс, последующие изменения в одном из них не влияют на изменения в другом. (Текст программы, не подвергающийся изменениям, является общим для родительского и дочернего процессов.) Системный вызов fork возвращает нулевое значение для дочернего процесса и равное идентификатору дочернего процесса или PID — для родительского. Используя возвращенное значение PID, два процесса могут определить, какой из них родительский, а какой — дочерний.

В большинстве случаев после вызова fork дочернему процессу необходимо выполнить программный код, отличный от родительского. Рассмотрим пример работы системной оболочки. Она считывает команду с терминала, создает дочерний процесс, ожидает, пока дочерний процесс выполнит команду, а затем считывает другую команду, если дочерний процесс завершается. Для ожидания завершения дочернего процесса родительский процесс выполняет системный вызов waitpid, который просто ждет, пока дочерний процесс не закончит свою работу (причем здесь имеется в виду любой дочерний процесс, если их несколько). Системный вызов waitpid может ожидать завершения конкретного дочернего процесса или любого из запущенных дочерних процессов, если первый параметр имеет значение -1. Когда работа waitpid завершается, по адресу, указанному во втором параметре — statloc, заносится информация о статусе завершения дочернего процесса (нормальное или аварийное завершение и выходное значение). В третьем параметре определяются различные необязательные настройки.

Теперь рассмотрим, как вызов fork используется оболочкой. После набора команды оболочка создает дочерний процесс, который должен выполнить команду пользователя. Он делает это, используя системный вызов execve, который полностью заменяет образ памяти процесса файлом, указанным в первом параметре. (Фактически сам системный вызов называется exec, но некоторые библиотечные процедуры со слегка отличающимися именами вызывают его с различными параметрами. Здесь мы будем рассматривать все это как системные вызовы.) В листинге 1.1 показано использование fork, waitpid и execve предельно упрощенной оболочкой.

Листинг 1.1. Оболочка, усеченная до минимума #define TRUE 1

while (TRUE) { /* бесконечный цикл */

type_prompt( ); /* вывод приглашения на экран */

read_command(command, parameters); /* чтение ввода с терминала */

if (fork( ) != 0) { /* ответвление дочернего процесса */

/* код родительского процесса */

waitpid(-1, &status, 0); /* ожидание завершения дочернего процесса */

} else {

/* код дочернего процесса */

execve(command, parameters, 0); /* выполнение command */

}

}

Далее в этой книге предполагается, что для TRUE определено значение 1.

В наиболее общем случае команда execve имеет три параметра: имя выполняемого файла, указатель на массив аргументов и указатель на массив переменных окружения.

Эти параметры мы рассмотрим в дальнейшем. Различные библиотечные подпрограммы, включая execl, execv, execle и execve, предусматривают возможность пропуска параметров или указания их различными способами. Далее в этой книге мы воспользуемся именем exec для представления системного вызова, который инициируется всеми этими подпрограммами.

Рассмотрим следующую команду: cp file1 file2

Она используется для копирования одного файла в другой — filel в file2. После создания оболочкой дочернего процесса последний находит и выполняет файл cp и передает ему имена исходного и целевого файлов.

Основная программа cp (и большинство других основных программ на языке С) содержит объявление

main(argc, argv, envp)

где argc — количество элементов командной строки, включая имя программы. Для предыдущего примера argc равен 3.

Второй параметр — argv — представляет собой указатель на массив. Элемент i этого массива является указателем на i-й строковый элемент командной строки. В нашем примере argv[0] будет указывать на строку cp, argv[1] — на строку file1, а argv[2] — на строку file2.

Третий параметр функции main — envp — является указателем на массив переменных окружения, то есть на массив строк вида имя = значение, используемый для передачи программе такой информации, как тип терминала и имя домашнего каталога программ. Существуют библиотечные процедуры, которые программа может вызвать для получения переменных окружения. Они часто используются для настройки пользовательских предпочтений при выполнении определенных задач (например, для настройки принтера, используемого по умолчанию). В листинге 1.1 окружение дочернему процессу не передается, поэтому третий параметр execve имеет нулевое значение.

Если вызов exec кажется сложным, не стоит отчаиваться — это (с точки зрения семантики) наиболее сложный из всех имеющихся в POSIX системных вызовов. Все остальные выглядят намного проще. В качестве более простого примера можно рассмотреть exit, который используется процессами, когда они заканчивают выполнение. У него всего один параметр — статус выхода (0-255), который возвращается родительской программе через statloc в системном вызове waitpid.

В UNIX память каждого процесса делится на три сегмента: текстовый сегмент (то есть код программы), сегмент данных (переменные) и сегмент стека. Как показано на рис. 1.18, сегмент данных растет вверх, а стек растет вниз. Между ними существует часть неиспользованного адресного пространства. Стек заполняет пустое пространство автоматически по мере надобности. Расширение сегмента данных за счет пустого про-

Рис. 1.18. Память процессов состоит из трех сегментов: текста, данных и стека


странства выполняется явным образом. Для этого предназначен системный вызов brk, указывающий новый адрес окончания сегмента данных. Однако этот вызов стандартом POSIX не определен, так как программистам для динамического распределения памяти рекомендуется пользоваться библиотечной процедурой malloc. При этом низкоуровневая реализация malloc не рассматривалась в качестве объекта, подходящего для стандартизации, поскольку мало кто из программистов использует ее в непосредственном виде и весьма сомнительно, чтобы кто-нибудь даже заметил отсутствие в POSIX системного вызова brk.

1.6.2.

<< | >>
Источник: Э. ТАНЕНБАУМ Х. БОС. СОВРЕМЕННЫЕ ОПЕРАЦИОННЫЕ СИСТЕМ Ы 4-е ИЗДАНИЕ. 2015

Еще по теме Системные вызовы для управления процессами:

  1. I. 1. СИСТЕМНЫЙ ПОДХОД КАК ИНСТРУМЕНТ ДЛЯ ПОСТРОЕНИЯ СИСТЕМНЫХ ОПИСАНИЙ
  2. Психологическая системность в управлении.
  3. Психологическая системность в управлении.
  4. Поведенческая основа процесса управления.
  5. Сущность процесса управления в организациях.
  6. РАЗДЕЛ III. СОЦИОЛОГИЧЕСКОЕ ОБЕСПЕЧЕНИЕ ПРОЦЕССОВ УПРАВЛЕНИЯ СОЦИАЛЬНОЙ СФЕРОЙ
  7. Психологические особенности управления инновационным процессом в правоохранительных органах.
  8. Психологические особенности управления инновационным процессом в правоохранительных органах.
  9. I. СИСТЕМНЫЕ ОПИСАНИЯ - ГЛАВНЫЙ РЕЗУЛЬТАТ СИСТЕМНОГО ПОДХОДА В ПСИХОЛОГИИ
  10. § 45 Меры к охранению открывшегося наследства. – Опись. – Вызов наследников. – Утверждение в правах наследства. – Срок на явку наследников и вступление явившихся. – Особые правила для торгового сословия.
  11. Психология личности целостна, системна (принцип целостности, системности).
  12. ВЫЗОВ ВРАЧА
  13. СПТ откликается на вызов обстоятельств
  14. Быстрый вызов желаемого
  15. Бросьте себе вызов
  16. Самоубийство как вызов обществу
  17. Статья 1040. Обращение взыскания на имущество, переданное в управление, по требованию кредитора установщика управления
  18. Очерк 2: Берт «Процесс — вот мое достояние. Именно процесс создает успех»
  19. § 14 Условное соглашение. – Предложение и вызов. – Договор посредством публичного торга или состязания. – Одностороннее обещание.