<<
>>

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

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

В большинстве случаев после вызова fork дочернему процессу необходимо выполнить программный код, отличный от кода родительского процесса.

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

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

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

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

cp filel file2

Эта команда используется для копирования файла filel в файл f ile2. После создания оболочкой дочернего процесса последний находит и исполняет файл ср и передает ему имена исходного и целевого файлов.

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

main(arge, argv, envp)

В этом определении в параметр arge входит количество записей в командной строке, включая имя программы. Например, для показанной строки параметр arge равен 3.

Второй параметр argv является указателем на массив указателей. Элемент i массива указывает на г-ю запись в командной строке.

В нашем примере параметр argv [ 0 ] должен указывать на строку ср, a argv [ 1 ] и argv [ 2 ] — на строки filel и file2 соответственно.

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

Если команда ехес кажется сложной, не огорчайтесь, потому что это — один из наиболее сложных системных вызовов в POSIX. Все остальные намного проще. В качестве еще одного примера рассмотрим вызов exit, процессы должны

использовать его при завершении работы. У него есть всего один параметр, статус выхода, изменяющийся от 0 до 255. Он возвращается родительскому процессу через переменную statloc в системном вызове waitpid. Младший байт этой переменной содержит значение статуса выхода, который равен 0 при нормальном завершении работы и ненулевому значению при завершении по ошибке. Старший байт содержит статус завершения дочернего процесса (от 0 до 255). Например:

n = waitpid(-l, ^status, options);

Если родительский процесс выполнит эту команду, то его работа будет приостановлена до завершения дочернего процесса. Если дочерний процесс завершится, скажем, через вызов exit с параметром 4, то когда родительский процесс продолжит работу, п будет содержать PID дочернего процесса, a statloc — значение 0x0400 (в языке С принято писать символы Ох перед шестнадцатеричными числами, это соглашение постоянно используется в книге).

В MINIX 3 под процессы отводится часть памяти, которая, в свою очередь, делится на три сегмента: текста (код программы), данных (переменные) и стека. Сегмент данных растет снизу вверх, а стек увеличивается сверху вниз, как показано на рис. 1.9. Между ними существует часть неиспользованного адресного пространства. Стек автоматически занимает такую часть этого участка памяти, какую необходимо, но расширение сегмента данных выполняется явным образом.

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

Адрес (шестнадцатеричный)

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

Для удобства программиста предлагается библиотечная процедура БЬгк, также меняющая размер сегмента данных. Ее единственный параметр указывает, на сколько должен быть увеличен размер сегмента (чтобы уменьшить сегмент, нужно передавать отрицательные значения). Процедура работает так: вызовом Ьгк определяется текущий размер сегмента, затем вычисляется новый размер, после чего делается еще один системный вызов, запрашивающий требуемое количество байтов. Оба вызова (Ьгк и БЬгк) не относятся к стандарту Р051Х. Для динамического выделения памяти программисты могут использовать библиотечную процедуру mal loe. Поскольку впрямую эту процедуру применяют очень редко, ее стандартизацию посчитали нецелесообразной.

Следующий системный вызов для работы с процессами, getpid, является заодно и простейшим из них. Этот вызов просто возвращает идентификатор вызвавшего его процесса. Обратите внимание на то, что при вызове fork значение идентификатора дочернего процесса получает только родительский процесс. Если дочернему процессу потребуется узнать собственный идентификатор процесса, ему придется использовать вызов getpid. Вызов getgrp возвращает идентификатор группы процессов, в которую входит процесс, сделавший вызов. Вызов setsid открывает новый сеанс и устанавливает идентификатор группы процессов равным идентификатору процесса, сделавшего вызов. Сеансы относятся к необязательной функции POSIX, называемой управлением заданиями и в MINIX 3 не реализованной, поэтому данная функция в дальнейшем не упоминается.

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

1.4.2.

<< | >>
Источник: Э. ТАНЕНБАУМ, А. ВУДХАЛЛ. ОПЕРАЦИОННЫЕ СИСТЕМЫ Разработка и реализация 3-е издание. 2007

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

  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: Берт «Процесс — вот мое достояние. Именно процесс создает успех»