The design of the unix operating system by Maurice J

Вид материалаРеферат
Диспетчеризация процессов
Подобный материал:
1   ...   27   28   29   30   31   32   33   34   ...   55

него пространство процесса, области команд, данных и стека.

Впоследствии пользователь может тщательно изучить дамп обра-

за процесса с помощью стандартных средств отладки. Опишите

алгоритм, которому на Ваш взгляд должно следовать ядро в

процессе создания файла "core". Что нужно предпринять в том

случае, если в текущем каталоге файл с таким именем уже су-

ществует ? Как должно вести себя ядро, когда в одном и том

же каталоге дампируют свои образы сразу несколько процессов?

8. Еще раз обратимся к программе (Рисунок 7.12), описывающей,

как один процесс забрасывает другой процесс сигналами, кото-

рые принимаются их адресатом. Подумайте, что произошло бы в

том случае, если бы алгоритм обработки сигналов был перера-

ботан в любом из следующих направлений:


-------------------------------------------------------------┐

│ #include

│ int fdrd,fdwt; │

│ char c; │

│ │

│ main(argc,argv) │

│ int argc; │

│ char *argv[]; │

│ { │

│ if (argc != 3) │

│ exit(1); │

│ fork(); │

│ │

│ if ((fdrd = open(argv[1],O_RDONLY)) == -1) │

│ exit(1); │

│ if (((fdwt = creat(argv[2],0666)) == -1) && │

│ ((fdwt = open(argv[2],O_WRONLY)) == -1)) │

│ exit(1); │

│ rdwrt(); │

│ } │

│ rdwrt() │

│ { │

│ for (;;) │

│ { │

│ if (read(fdrd,&c,1) != 1) │

│ return; │

│ write(fdwt,&c,1); │

│ } │

│ } │

L-------------------------------------------------------------


Рисунок 7.34. Пример программы, в которой процесс-родитель и

процесс-потомок не разделяют доступ к файлу


* ядро не заменяет функцию обработки сигналов до тех пор,

пока пользователь явно не потребует этого;

* ядро заставляет процесс игнорировать сигналы до тех пор,

пока пользователь не обратится к функции signal вновь.

9. Переработайте алгоритм обработки сигналов так, чтобы ядро

автоматически перенастраивало процесс на игнорирование всех

последующих поступлений сигналов по возвращении из функции,

обрабатывающей их. Каким образом ядро может узнать о завер-

шении функции обработки сигналов, выполняющейся в режиме за-

дачи ? Такого рода перенастройка приблизила бы нас к трак-

товке сигналов в системе BSD.

*10. Если процесс получает сигнал, находясь в состоянии

приостанова во время выполнения системной функции с допуска-

ющим прерывания приоритетом, он выходит из функции по алго-

ритму longjump. Ядро производит необходимые установки для

запуска функции обработки сигнала; когда процесс выйдет из

функции обработки сигнала, в версии V это будет выглядеть

так, словно он вернулся из системной функции с признаком

ошибки (как бы прервав свое выполнение). В системе BSD сис-

темная функция в этом случае автоматически перезапускается.

Каким образом можно реализовать этот момент в нашей системе?


-------------------------------------------------------------┐

│ #include

│ main() │

│ { │

│ extern catcher(); │

│ │

│ signal(SIGCLD,catcher); │

│ if (fork() == 0) │

│ exit(); │

│ /* пауза до момента получения сигнала */ │

│ pause(); │

│ } │

│ │

│ catcher() │

│ { │

│ printf("процесс-родитель получил сигнал\n"); │

│ signal(SIGCLD,catcher); │

│ } │

L-------------------------------------------------------------


Рисунок 7.35. Программа, в которой процесс принимает сигналы

типа "гибель потомка"


11. В традиционной реализации команды mkdir для создания новой

вершины в дереве каталогов используется системная функция

mknod, после чего дважды вызывается системная функция link,

привязывающая точки входа в каталог с именами "." и ".." к

новой вершине и к ее родительскому каталогу. Без этих трех

операций каталог не будет иметь надлежащий формат. Что прои-

зойдет, если во время исполнения команды mkdir процесс полу-

чит сигнал ? Что если при этом будет получен сигнал SIGKILL,

который процесс не распознает ? Эту же проблему рассмотрите

применительно к реализации системной функции mkdir.

12. Процесс проверяет наличие сигналов в моменты перехода в сос-

тояние приостанова и выхода из него (если в состоянии приос-

танова процесс находился с приоритетом, допускающим прерыва-

ния), а также в момент перехода в режим задачи из режима

ядра по завершении исполнения системной функции или после

обработки прерывания. Почему процесс не проверяет наличие

сигналов в момент обращения к системной функции ?

*13. Предположим, что после исполнения системной функции процесс

готовится к возвращению в режим задачи и не обнаруживает ни

одного необработанного сигнала. Сразу после этого ядро обра-

батывает прерывание и посылает процессу сигнал. (Например,

пользователем была нажата клавиша "break".) Что делает про-

цесс после того, как ядро завершает обработку прерывания ?

*14. Если процессу одновременно посылается несколько сигналов,

ядро обрабатывает их в том порядке, в каком они перечислены

в описании. Существуют три способа реагирования на получение

сигнала - прием сигналов, завершение выполнения со сбросом

на внешний носитель (дампированием) образа процесса в памяти

и завершение выполнения без дампирования. Можно ли указать

наилучший порядок обработки одновременно поступающих сигна-

лов ? Например, если процесс получает сигнал о выходе (вызы-

вающий дампирование образа процесса в памяти) и сигнал о

прерывании (выход без дампирования), то какой из этих сигна-

лов имело бы смысл обработать первым ?

15. Запомните новую системную функцию

newpgrp(pid,ngrp);

которая включает процесс с идентификатором pid в группу про-

цессов с номером ngrp (устанавливает для процесса новую

группу). Подумайте, для каких целей она может использоваться

и какие опасности таит в себе ее вызов.

16. Прокомментируйте следующее утверждение: по алгоритму wait

процесс может приостановиться до наступления какого-либо со-

бытия и это не отразилось бы на работе всей системы.

17. Рассмотрим новую системную функцию

nowait(pid);

где pid - идентификатор процесса, являющегося потомком того

процесса, который вызывает функцию. Вызывая функцию, процесс

тем самым сообщает ядру о том, что он не собирается дожи-

даться завершения выполнения своего потомка, поэтому ядро

может по окончании существования потомка сразу же очистить

занимаемое им место в таблице процессов. Каким образом это

реализуется на практике ? Оцените достоинства новой функции

и сравните ее использование с использованием сигналов типа

"гибель потомка".

18. Загрузчик модулей на Си автоматически подключает к основному

модулю начальную процедуру (startup), которая вызывает функ-

цию main, принадлежащую программе пользователя. Если в поль-

зовательской программе отсутствует вызов функции exit, про-

цедура startup сама вызывает эту функцию при выходе из функ-

ции main. Что произошло бы в том случае, если бы и в проце-

дуре startup отсутствовал вызов функции exit (из-за ошибки

загрузчика) ?

19. Какую информацию получит процесс, выполняющий функцию wait,

если его потомок запустит функцию exit без параметра ? Име-

ется в виду, что процесс-потомок вызовет функцию в формате

exit() вместо exit(n). Если программист постоянно использует

вызов функции exit без параметра, то насколько предсказуемо

значение, ожидаемое функцией wait ? Докажите свой ответ.

20. Объясните, что произойдет, если процесс, исполняющий прог-

рамму на Рисунке 7.36 запустит с помощью функции exec самого

себя. Как в таком случае ядро сможет избежать возникновения

тупиковых ситуаций, связанных с блокировкой индексов ?

-----------------------------------┐

│ main(argc,argv) │

│ int argc; │

│ char *argv[]; │

│ { │

│ execl(argv[0],argv[0],0); │

│ } │

L-----------------------------------

Рисунок 7.36


21. По условию первым аргументом функции exec является имя (пос-

ледняя компонента имени пути поиска) исполняемого процессом

файла. Что произойдет в результате выполнения программы,

приведенной на Рисунке 7.37 ? Каков будет эффект, если в ка-

честве файла "a.out" выступит загрузочный модуль, полученный

в результате трансляции программы, приведенной на Рисунке

7.36 ?

22. Предположим, что в языке Си поддерживается новый тип данных

"read-only" (только для чтения), причем процесс, пытающийся

записать информацию в поле с этим типом, получает отказ сис-

темы защиты. Опишите реализацию этого момента. (Намек: срав-

ните это понятие с понятием "разделяемая область команд".) В

какие из алгоритмов ядра потребуется внести изменения ? Ка-

кие еще объекты могут быть реализованы аналогичным с об-

ластью образом ?

23. Какие изменения имеют место в алгоритмах open, chmod, unlink

и unmount при работе с файлами, для которых установлен режим

"sticky-bit" ? Какие действия, например, следует предпринять

в отношении такого файла ядру, когда с файлом разрывается

связь ?

24. Суперпользователь является единственным пользователем, имею-

щим право на запись в файл паролей "/etc/passwd", благодаря

чему содержимое файла предохраняется от умышленной или слу-

чайной порчи. Программа passwd дает пользователям возмож-

ность изменять свой собственный пароль, защищая от изменений

чужие записи. Каким образом она работает ?


------------------------------------------------------┐

│ main() │

│ { │

│ if (fork() == 0) │

│ { │

│ execl("a.out",0); │

│ printf("неудачное завершение функции exec\n");│

│ } │

│ } │

L------------------------------------------------------

Рисунок 7.37


*25. Поясните, какая угроза безопасности хранения данных возника-

ет, если setuid-программа не защищена от записи.

26. Выполните следующую последовательность команд, в которой "a.

out" - имя исполняемого файла:

chmod 4777 a.out

chown root a.out

Команда chmod "включает" бит setuid (4 в 4777); пользователь

"root" традиционно является суперпользователем. Может ли в

результате выполнения этой последовательности произойти на-

рушение защиты информации ?

27. Что произойдет в процессе выполнения программы, представлен-

ной на Рисунке 7.38 ? Поясните свой ответ.


------------------------------------------------------┐

│ main() │

│ { │

│ char *endpt; │

│ char *sbrk(); │

│ int brk(); │

│ │

│ endpt = sbrk(0); │

│ printf("endpt = %ud после sbrk\n", (int) endpt); │


│ │

│ while (endpt--) │

│ { │

│ if (brk(endpt) == -1) │

│ { │

│ printf("brk с параметром %ud завершилась │

│ неудачно\n",endpt); │

│ exit(); │

│ } │

│ } │

│ } │

L------------------------------------------------------

Рисунок 7.38


28. Библиотечная подпрограмма malloc увеличивает область данных

процесса с помощью функции brk, а подпрограмма free освобож-

дает память, выделенную подпрограммой malloc. Синтаксис вы-

зова подпрограмм:


ptr = malloc(size);

free(ptr);

где size - целое число без знака, обозначающее количество

выделяемых байт памяти, а ptr - символьная ссылка на вновь

выделенное пространство. Прежде чем появиться в качестве па-

раметра в вызове подпрограммы free, указатель ptr должен

быть возвращен подпрограммой malloc. Выполните эти подпрог-

раммы.

29. Что произойдет в процессе выполнения программы, представлен-

ной на Рисунке 7.39 ? Сравните результаты выполнения этой

программы с результатами, предусмотренными в системном опи-

сании.


------------------------------------------------------┐

│ main() │

│ { │

│ int i; │

│ char *cp; │

│ extern char *sbrk(); │

│ │

│ cp = sbrk(10); │

│ for (i = 0; i < 10; i++) │

│ *cp++ = 'a' + i; │

│ sbrk(-10); │

│ cp = sbrk(10); │

│ for (i = 0; i < 10; i++) │

│ printf("char %d = '%c'\n",i,*cp++); │

│ } │

L------------------------------------------------------


Рисунок 7.39. Пример программы, использующей подпрограмму

sbrk


30. Каким образом командный процессор shell узнает о том, что

файл исполняемый, когда для выполнения команды создает новый

процесс ? Если файл исполняемый, то как узнать, создан ли он

в результате трансляции исходной программы или же представ-

ляет собой набор команд языка shell ? В каком порядке следу-

ет выполнять проверку указанных условий ?

31. В командном языке shell символы ">>" используются для

направления вывода данных в файл с указанной спецификацией,

например, команда:

run >> outfile

открывает файл с именем "outfile" (а в случае отсутствия

файла с таким именем создает его) и записывает в него дан-

ные. Напишите программу, в которой используется эта команда.


-------------------┐

│ main() │

│ { │

│ exit(0); │

│ } │

L-------------------


Рисунок 7.40


32. Процессор командного языка shell проверяет код, возвращаемый

функцией exit, воспринимая нулевое значение как "истину", а

любое другое значение как "ложь" (обратите внимание на не-

согласованность с языком Си). Предположим, что файл, испол-

няющий программу на Рисунке 7.40, имеет имя "truth". Поясни-

те, что произойдет, когда shell будет исполнять следующий

набор команд:

while truth

do

truth &

done

33. Вопрос по Рисунку 7.29: В связи с чем возникает необходи-

мость в создании процессов для конвейерной обработки двух-

компонентной команды в указанном порядке ?

34. Напишите более общую программу работы основного цикла про-

цессора shell в части обработки каналов. Имеется в виду, что

программа должна уметь обрабатывать случайное число каналов,

указанных в командной строке.

35. Переменная среды PATH описывает порядок, в котором shell'у

следует просматривать каталоги в поисках исполняемых файлов.

В библиотечных функциях execlp и execvp перечисленные в PATH

каталоги присоединяются к именам файлов, кроме тех, которые

начинаются с символа "/". Выполните эти функции.

*36. Для того, чтобы shell в поисках исполняемых файлов не обра-

щался к текущему каталогу, суперпользователь должен задать

переменную среды PATH. Какая угроза безопасности хранения

данных может возникнуть, если shell попытается исполнить

файлы из текущего каталога ?

37. Каким образом shell обрабатывает команду cd (создать ката-

лог) ? Какие действия предпринимает shell в процессе обра-

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

cd pathname & ?

38. Когда пользователь нажимает на клавиатуре терминала клавиши

"delete" или "break", всем процессам, входящим в группу ре-

гистрационного shell'а, терминальный драйвер посылает сигнал

о прерывании. Пользователь может иметь намерение остановить

все процессы, порожденные shell'ом, без выхода из системы.

Какие усовершенствования в связи с этим следует произвести в

теле основного цикла программы shell (Рисунок 7.28) ?

39. С помощью команды

nohup command_line

пользователь может отменить действие сигналов о "зависании"

и о завершении (quit) в отношении процессов, реализующих ко-

мандную строку (command_line). Как эта команда будет обраба-

тываться в основном цикле программы shell ?

40. Рассмотрим набор команд языка shell:

nroff -mm bigfile1 > big1out &

nroff -mm bigfile2 > big2out

и вновь обратимся к основному циклу программы shell (Рисунок

7.28). Что произойдет, если выполнение первой команды nroff

завершится раньше второй ? Какие изменения следует внести в

основной цикл программы shell на этот случай ?

41. Часто во время выполнения из shell'а непротестированных

программ появляется сообщение об ошибке следующего вида:

"Bus error - core dumped" (Ошибка в магистрали - содержимое

памяти сброшено на внешний носитель). Очевидно, что в прог-

рамме выполняются какие-то недопустимые действия; откуда

shell узнает о том, что ему нужно вывести сообщение об ошиб-

ке ?

42. Процессом 1 в системе может выступать только процесс init.

Тем не менее, запустив процесс init, администратор системы

может тем самым изменить состояние системы. Например, при

загрузке система может войти в однопользовательский режим,

означающий, что в системе активен только консольный терми-

нал. Для того, чтобы перевести процесс init в состояние 2

(многопользовательский режим), администратор системы вводит

с консоли команду

init 2 .

Консольный shell порождает свое ответвление и запускает

init. Что имело бы место в системе в том случае, если бы ак-

тивен был только один процесс init ?

43. Формат записей в файле "/etc/inittab" допускает задание

действия, связанного с каждым порождаемым процессом. Напри-

мер, с getty-процессом связано действие "respawn" (возрожде-

ние), означающее, что процесс init должен возрождать

getty-процесс, если последний прекращает существование. На

практике, когда пользователь выходит из системы процесс init

порождает новый getty-процесс, чтобы другой пользователь мог

получить доступ к временно бездействующей терминальной ли-

нии. Каким образом это делает процесс init ?

44. Некоторые из алгоритмов ядра прибегают к просмотру таблицы

процессов. Время поиска данных можно сократить, если исполь-

зовать указатели на: родителя процесса, любого из потомков,

другой процесс, имеющий того же родителя. Процесс обнаружи-

вает всех своих потомков, следуя сначала за указателем на

любого из потомков, а затем используя указатели на другие

процессы, имеющие того же родителя (циклы недопустимы). Ка-

кие из алгоритмов выиграют от этого ? Какие из алгоритмов

нужно оставить без изменений ?

ДИСПЕТЧЕРИЗАЦИЯ ПРОЦЕССОВ

И ЕЕ ВРЕМЕННЫЕ

ХАРАКТЕРИСТИКИ


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

сурсы центрального процессора (ЦП) на интервал времени, называе-

мый квантом, по истечении которого выгружает этот процесс и за-

пускает другой, периодически переупорядочивая очередь процессов.

Алгоритм планирования процессов в системе UNIX использует время

выполнения в качестве параметра. Каждый активный процесс имеет

приоритет планирования; ядро переключает контекст на процесс с

наивысшим приоритетом. При переходе выполняющегося процесса из

режима ядра в режим задачи ядро пересчитывает его приоритет, пе-

риодически и в режиме задачи переустанавливая приоритет каждого

процесса, готового к выполнению.


Информация о времени, связанном с выполнением, нужна также и

некоторым из пользовательских процессов: используемая ими, напри-