The design of the unix operating system by Maurice J
Вид материала | Реферат |
G6.8 упражненияh Управление процессом 7.1 Создание процесса |
- Лекция 10. Файловые системы Unix, 116.79kb.
- Уровни рассмотрения, 314.07kb.
- Курс по операционным системам (на примере ос windows) Основан на учебном курсе Windows, 29.21kb.
- Выполнил ученик 11 «А» класса, 443.51kb.
- Ос лекция 1 (2-й семестр – временно), 101.4kb.
- Operating System, 7686.97kb.
- Unix-подобные операционные системы, характеристики, особенности, разновидности, 40.63kb.
- 1. ms sql server. Общие сведения, 66.03kb.
- Shanti ananda maurice, 89.84kb.
- Методические материалы, 3002.45kb.
планирования их выполнения, а также при объяснении различных ме-
тодов распределения памяти.
G6.8 УПРАЖНЕНИЯH
1. Составьте алгоритм преобразования виртуальных адресов в фи-
зические, на входе которого задаются виртуальный адрес и ад-
рес точки входа в частную таблицу областей.
2. В машинах AT&T 3B2 и NSC серии 32000 используется двухуров-
невая схема трансляции виртуальных адресов в физические (с
сегментацией). То есть в системе поддерживается указатель на
таблицу страниц, каждая запись которой может адресовать фик-
сированную часть адресного пространства процесса по смещению
в таблице. Сравните алгоритм трансляции виртуальных адресов
на этих машинах с алгоритмом, изложенным в тексте при обсуж-
дении модели управления памятью. Подумайте над проблемами
производительности и потребности в памяти для размещения
вспомогательных таблиц.
3. В архитектуре системы VAX-11 поддерживаются два набора ре-
гистров защиты памяти, используемых машиной в процессе
трансляции пользовательских адресов. Механизм трансляции ис-
пользуется тот же, что и в предыдущем пункте, за одним иск-
лючением: указателей на таблицу страниц здесь два. Если про-
цесс располагает тремя областями - команд, данных и стека -
то каким образом, используя два набора регистров, следует
производить отображение областей на таблицы страниц ? Увели-
чение стека в архитектуре системы VAX-11 идет в направлении
младших виртуальных адресов. Какой тогда вид имела бы об-
ласть стека ? В главе 11 будет рассмотрена область разделяе-
мой памяти: как она может быть реализована в архитектуре
системы VAX-11 ?
4. Составьте алгоритм выделения и освобождения страниц памяти и
таблиц страниц. Какие структуры данных следует использовать,
чтобы достичь наивысшей производительности или наибольшей
простоты реализации алгоритма ?
5. Устройство управления памятью MC68451 для семейства микро-
процессоров Motorola 68000 допускает выделение сегментов па-
мяти размером от 256 байт до 16 мегабайт. Каждое (физичес-
кое) устройство управления памятью поддерживает 32
дескриптора сегментов. Опишите эффективный метод выделения
памяти для этого случая. Каким образом осуществлялась бы ре-
ализация областей ?
6. Рассмотрим отображение виртуальных адресов, представленное
на Рисунке 6.5. Предположим, что ядро выгружает процесс (в
системе с подкачкой процессов) или откачивает в область сте-
ка большое количество страниц (в системе с замещением стра-
ниц). Если через какое-то время процесс обратится к вирту-
альному адресу 68432, будет ли он должен обратиться к
соответствующей ячейке физической памяти, из которой он счи-
тывал данные до того, как была выполнена операция выгрузки
(откачки) ? Если нижние уровни системы управления памятью
реализуются с использованием таблицы страниц, следует ли эти
таблицы располагать в тех же, что и сами страницы, местах
физической памяти ?
*7. Можно реализовать систему, в которой стек ядра располагается
над вершиной стека задачи. Подумайте о достоинствах и недос-
татках подобной системы.
8. Каким образом, присоединяя область к процессу, ядро может
проверить то, что эта область не накладывается на виртуаль-
ные адреса областей, уже присоединенных к процессу ?
9. Обратимся к алгоритму переключения контекста. Допустим, что
в системе готов к выполнению только один процесс. Другими
словами, ядро выбирает для выполнения процесс с только что
сохраненным контекстом. Объясните, что произойдет при этом.
10. Предположим, что процесс приостановился, но в системе нет
процессов, готовых к выполнению. Что произойдет, когда при-
остановившийся процесс переключит контекст ?
11. Предположим, что процесс, выполняемый в режиме задачи, из-
расходовал выделенный ему квант времени и в результате пре-
рывания по таймеру ядро выбирает для выполнения новый
процесс. Объясните, почему переключение контекста произойдет
на системном контекстном уровне 2.
12. В системе с замещением страниц процесс, выполняемый в режиме
задачи, может столкнуться с отсутствием нужной страницы, ко-
торая не была загружена в память. В ходе обработки прерыва-
ния ядро считывает страницу из области подкачки и приоста-
навливается. Объясните, почему переключение контекста (в
момент приостанова) произойдет на системном контекстном
уровне 2.
13. Процесс использует системную функцию read с форматом вызова
read(fd,buf,1024);
в системе с замещением страниц памяти. Предположим, что ядро
исполняет алгоритм read для считывания данных в системный
буфер, однако при попытке копирования данных в адресное
пространство задачи сталкивается с отсутствием нужной стра-
ницы, содержащей структуру buf, вследствие того, что она бы-
ла ранее выгружена из памяти. Ядро обрабатывает возникшее
прерывание, считывая отсутствующую страницу в память. Что
происходит на каждом из системных контекстных уровней ? Что
произойдет, если программа обработки прерывания приостано-
вится в ожидании завершения считывания страницы ?
14. Что произошло бы, если бы во время копирования данных из ад-
ресного пространства задачи в память ядра (Рисунок 6.17) об-
наружилось, что указанный пользователем адрес неверен ?
*15. При выполнении алгоритмов sleep и wakeup ядро повышает
приоритет работы процессора так, чтобы не допустить прерыва-
ний, препятствующих ей. Какие отрицательные последствия мог-
ли бы возникнуть, если бы ядро не предпринимало этих дейс-
твий ? (Намек: ядро зачастую возобновляет приостановленные
процессы прямо из программ обработки прерываний).
*16. Предположим, что процесс пытается приостановиться до наступ-
ления события A, но, запуская алгоритм sleep, еще не забло-
кировал прерывания; допустим, что в этот момент происходит
прерывание и программа его обработки пытается возобновить
все процессы, приостановленные до наступления события A. Что
случится с первым процессом ? Не представляет ли эта ситуа-
ция опасность ? Если да, то может ли ядро избежать ее воз-
никновения ?
17. Что произойдет, если ядро запустит алгоритм wakeup для всех
процессов, приостановленных по адресу A, в то время, когда
по этому адресу не окажется ни одного приостановленного про-
цесса ?
18. По одному адресу может приостановиться множество процессов,
но ядру может потребоваться возобновление только некоторых
из них - тех, которым будет послан соответствующий сигнал. С
помощью механизма посылки сигналов можно идентифицировать
отдельные процессы. Подумайте, какие изменения следует про-
извести в алгоритме wakeup для того, чтобы можно было возоб-
новлять выполнение только одного процесса, а не всех процес-
сов, приостановленных по заданному адресу.
19. Обращения к алгоритмам sleep и wakeup в системе Multics
имеют следующий синтаксис:
sleep (событие);
wakeup (событие, приоритет);
Таким образом, в алгоритме wakeup возобновляемому процессу
присваивается приоритет. Сравните форму вызова этих алгорит-
мов с формой вызова соответствующих алгоритмов в системе
UNIX.
УПРАВЛЕНИЕ ПРОЦЕССОМ
В предыдущей главе был рассмотрен контекст процесса и описаны
алгоритмы для работы с ним; в данной главе речь пойдет об исполь-
зовании и реализации системных функций, управляющих контекстом
процесса. Системная функция fork создает новый процесс, функция
exit завершает выполнение процесса, а wait дает возможность роди-
тельскому процессу синхронизировать свое продолжение с завершени-
ем порожденного процесса. Об асинхронных событиях процессы инфор-
мируются при помощи сигналов. Поскольку ядро синхронизирует
выполнение функций exit и wait при помощи сигналов, описание ме-
ханизма сигналов предваряет собой рассмотрение функций exit и
wait. Системная функция exec дает процессу возможность запускать
"новую" программу, накладывая ее адресное пространство на испол-
няемый образ файла. Системная функция brk позволяет динамически
выделять дополнительную память; теми же самыми средствами ядро
динамически наращивает стек задачи, выделяя в случае необходимос-
ти дополнительное пространство. В заключительной части главы да-
ется краткое описание основных групп операций командного процес-
сора shell и начального процесса init.
На Рисунке 7.1 показана взаимосвязь между системными функция-
ми, рассматриваемыми в данной главе, с одной стороны, и алгорит-
мами, описанными в предыдущей главе, с другой. Почти во всех
функциях используются алгоритмы sleep и wakeup, отсутствующие на
рисунке. Функция exec, кроме того, взаимодействует с алгоритмами
работы с файловой системой, речь о которых шла в главах 4 и 5.
------------------------------T---------------------T------------┐
│ Системные функции, имеющие │ Системные функции, │ Функции │
│ ющие дело с управлением па- │ связанные с синхро- │ смешанного │
│ мятью │ низацией │ типа │
+-------T-------T-------T-----+--T----T------T----T-+-----T------+
│ fork │ exec │ brk │ exit │wait│signal│kill│setrgrp│setuid│
+-------+-------+-------+--------+----+------+----+-------+------+
│dupreg │detach-│growreg│ detach-│ │
│attach-│ reg │ │ reg │ │
│ reg │alloc- │ │ │ │
│ │ reg │ │ │ │
│ │attach-│ │ │ │
│ │ reg │ │ │ │
│ │growreg│ │ │ │
│ │loadreg│ │ │ │
│ │mapreg │ │ │ │
L-------+-------+-------+--------+--------------------------------
Рисунок 7.1. Системные функции управления процессом и их
связь с другими алгоритмами
7.1 СОЗДАНИЕ ПРОЦЕССА
Единственным способом создания пользователем нового процесса
в операционной системе UNIX является выполнение системной функции
fork. Процесс, вызывающий функцию fork, называется родительским
(процесс-родитель), вновь создаваемый процесс называется порож-
денным (процесс-потомок). Синтаксис вызова функции fork:
pid = fork();
В результате выполнения функции fork пользовательский контекст и
того, и другого процессов совпадает во всем, кроме возвращаемого
значения переменной pid. Для родительского процесса в pid возвра-
щается идентификатор порожденного процесса, для порожденного -
pid имеет нулевое значение. Нулевой процесс, возникающий внутри
ядра при загрузке системы, является единственным процессом, не
создаваемым с помощью функции fork.
В ходе выполнения функции ядро производит следующую последо-
вательность действий:
1. Отводит место в таблице процессов под новый процесс.
2. Присваивает порождаемому процессу уникальный код идентифика-
ции.
3. Делает логическую копию контекста родительского процесса.
Поскольку те или иные составляющие процесса, такие как об-
ласть команд, могут разделяться другими процессами, ядро мо-
жет иногда вместо копирования области в новый физический
участок памяти просто увеличить значение счетчика ссылок на
область.
4. Увеличивает значения счетчика числа файлов, связанных с про-
цессом, как в таблице файлов, так и в таблице индексов.
5. Возвращает родительскому процессу код идентификации порожден-
ного процесса, а порожденному процессу - нулевое значение.
Реализацию системной функции fork, пожалуй, нельзя назвать
тривиальной, так как порожденный процесс начинает свое выполне-
ние, возникая как бы из воздуха. Алгоритм реализации функции для
систем с замещением страниц по запросу и для систем с подкачкой
процессов имеет лишь незначительные различия; все изложенное ниже
в отношении этого алгоритма касается в первую очередь традицион-
ных систем с подкачкой процессов, но с непременным акцентировани-
ем внимания на тех моментах, которые в системах с замещением
страниц по запросу реализуются иначе. Кроме того, конечно, пред-
полагается, что в системе имеется свободная оперативная память,
достаточная для размещения порожденного процесса. В главе 9 будет
отдельно рассмотрен случай, когда для порожденного процесса не
хватает памяти, и там же будут даны разъяснения относительно реа-
лизации алгоритма fork в системах с замещением страниц.
-------------------------------------------------------------┐
│ алгоритм fork │
│ входная информация: отсутствует │
│ выходная информация: для родительского процесса - идентифи-│
│ катор (PID) порожденного процесса │
│ для порожденного процесса - 0 │
│ { │
│ проверить доступность ресурсов ядра; │
│ получить свободное место в таблице процессов и уникаль- │
│ ный код идентификации (PID); │
│ проверить, не запустил ли пользователь слишком много │
│ процессов; │
│ сделать пометку о том, что порождаемый процесс находится│
│ в состоянии "создания"; │
│ скопировать информацию в таблице процессов из записи, │
│ соответствующей родительскому процессу, в запись, соот-│
│ ветствующую порожденному процессу; │
│ увеличить значения счетчиков ссылок на текущий каталог и│
│ на корневой каталог (если он был изменен); │
│ увеличить значение счетчика открытий файла в таблице │
│ файлов; │
│ сделать копию контекста родительского процесса (адресное│
│ пространство, команды, данные, стек) в памяти; │
│ поместить в стек фиктивный уровень системного контекста │
│ над уровнем системного контекста, соответствующим по- │
│ рожденному процессу; │
│ фиктивный контекстный уровень содержит информацию, │
│ необходимую порожденному процессу для того, чтобы │
│ знать все о себе и будучи выбранным для исполнения │
│ запускаться с этого места; │
│ если (в данный момент выполняется родительский процесс) │
│ { │
│ перевести порожденный процесс в состояние "готовности│
│ к выполнению"; │
│ возвратить (идентификатор порожденного процесса); │
│ /* из системы пользователю */ │
│ } │
│ в противном случае /* выполняется порожденный │
│ процесс */ │
│ { │
│ записать начальные значения в поля синхронизации ад- │
│ ресного пространства процесса; │
│ возвратить (0); /* пользователю */ │
│ } │
│ } │
L-------------------------------------------------------------
Рисунок 7.2. Алгоритм fork
На Рисунке 7.2 приведен алгоритм создания процесса. Сначала
ядро должно удостовериться в том, что для успешного выполнения
алгоритма fork есть все необходимые ресурсы. В системе с подкач-
кой процессов для размещения порождаемого процесса требуется мес-
то либо в памяти, либо на диске; в системе с замещением страниц
следует выделить память для вспомогательных таблиц (в частности,
таблиц страниц). Если свободных ресурсов нет, алгоритм fork за-
вершается неудачно. Ядро ищет место в таблице процессов для конс-
труирования контекста порождаемого процесса и проверяет, не пре-
высил ли пользователь, выполняющий fork, ограничение на макси-
мально-допустимое количество параллельно запущенных процессов.
Ядро также подбирает для нового процесса уникальный идентифика-
тор, значение которого превышает на единицу максимальный из су-
ществующих идентификаторов. Если предлагаемый идентификатор уже
присвоен другому процессу, ядро берет идентификатор, следующий по
порядку. Как только будет достигнуто максимально-допустимое зна-
чение, отсчет идентификаторов опять начнется с 0. Поскольку боль-
шинство процессов имеет короткое время жизни, при переходе к на-
чалу отсчета значительная часть идентификаторов оказывается сво-
бодной.
На количество одновременно выполняющихся процессов
накладывается ограничение (конфигурируемое), отсюда ни один из
пользователей не может занимать в таблице процессов слишком много
места, мешая тем самым другим пользователям создавать новые про-
цессы. Кроме того, простым пользователям не разрешается создавать
процесс, занимающий последнее свободное место в таблице процес-
сов, в противном случае система зашла бы в тупик. Другими слова-
ми, поскольку в таблице процессов нет свободного места, то ядро
не может гарантировать, что все существующие процессы завершатся
естественным образом, поэтому новые процессы создаваться не бу-
дут. С другой стороны, суперпользователю нужно дать возможность
исполнять столько процессов, сколько ему потребуется, конечно,
учитывая размер таблицы процессов, при этом процесс, исполняемый
суперпользователем, может занять в таблице и последнее свободное
место. Предполагается, что суперпользователь может прибегать к
решительным мерам и запускать процесс, побуждающий остальные про-
цессы к завершению, если это вызывается необходимостью (см. раз-
дел 7.2.3, где говорится о системной функции kill).
Затем ядро присваивает начальные значения различным полям за-
писи таблицы процессов, соответствующей порожденному процессу,
копируя в них значения полей из записи родительского процесса.
Например, порожденный процесс "наследует" у родительского процес-
са коды идентификации пользователя (реальный и тот, под которым
исполняется процесс), группу процессов, управляемую родительским
процессом, а также значение, заданное родительским процессом в
функции nice и используемое при вычислении приоритета планирова-
ния. В следующих разделах мы поговорим о назначении этих полей.
Ядро передает значение поля идентификатора родительского процесса
в запись порожденного, включая последний в древовидную структуру
процессов, и присваивает начальные значения различным параметрам
планирования, таким как приоритет планирования, использование ре-
сурсов центрального процессора и другие значения полей синхрони-
зации. Начальным состоянием процесса является состояние "созда-
ния" (см. Рисунок 6.1).
После того ядро устанавливает значения счетчиков ссылок на
файлы, с которыми автоматически связывается порождаемый процесс.
Во-первых, порожденный процесс размещается в текущем каталоге ро-
дительского процесса. Число процессов, обращающихся в данный мо-
мент к каталогу, увеличивается на 1 и, соответственно, увеличива-
ется значение счетчика ссылок на его индекс. Во-вторых, если
родительский процесс или один из его предков уже выполнял смену
корневого каталога с помощью функции chroot, порожденный процесс
наследует и новый корень с соответствующим увеличением значения
счетчика ссылок на индекс корня. Наконец, ядро просматривает таб-
лицу пользовательских дескрипторов для родительского процесса в
поисках открытых файлов, известных процессу, и увеличивает значе-
ние счетчика ссылок, ассоциированного с каждым из открытых фай-
лов, в глобальной таблице файлов. Порожденный процесс не просто
наследует права доступа к открытым файлам, но и разделяет доступ
к файлам с родительским процессом, так как оба процесса обращают-
ся в таблице файлов к одним и тем же записям. Действие fork в от-
ношении открытых файлов подобно действию алгоритма dup: новая за-
пись в таблице пользовательских дескрипторов файла указывает на
запись в глобальной таблице файлов, соответствующую открытому
файлу. Для dup, однако, записи в таблице пользовательских деск-
рипторов файла относятся к одному процессу; для fork - к разным
процессам.