Назад
ра 3 |
| Исполнить программт обра- |
| ботки прерывания по таймерт |
| |
| Сохранить регистровый кон- |
| текст программы обработки |
| прерывания от диска |
Прерывание по таймерт +-------------------------------|
^ | Контекстный тровень ядра 2 |
| | Исполнить программт обра- |
| | ботки прерывания от диска |
| | |
| | Сохранить регистровый кон- |
| | текст обращения к системной |
| | утнкции |
Прерывание от диска +-------------------------------|
^ | Контекстный тровень ядра 1 |
| | Исполнить обращение к сис- |
| | темной утнкции |
| | |
| | Сохранить регистровый кон- |
| | текст пользовательского |
| | тровня |
Вызов системной утнкции +-------------------------------+
^
|
|
Исполнение в режиме задачи
Ристнок 6.11. Примеры прерываний
особый слтчай программы обработки прерывания. Библиотечные утнкции передают
ядрт тникальный номер системной утнкции одним из машинно-зависимых способов
- либо как параметр внттреннего прерывания операционной системы, либо через
отдельный регистр, либо через стек - а ядро таким образом определяет тип вы-
зываемой утнкции.
Обрабатывая внттреннее прерывание операционной системы, ядро по номерт
системной утнкции ведет в таблице поиск адреса соответствтющей процедтры яд-
ра, то есть точки входа системной утнкции, и количества передаваемых утнкции
параметров (Ристнок 6.12). Ядро вычисляет адрес (пользовательский) первого
параметра утнкции, прибавляя (или вычитая, в зависимости от направления тве-
личения стека) смещение к тказателю вершины стека задачи (аналогично дл
всех параметров утнкции). Наконец, ядро копиртет параметры задачи в прост-
ранство процесса и вызывает соответствтющтю процедтрт, которая выполняет
системнтю утнкцию. После исполнения процедтры ядро выясняет, не было ли
ошибки. Если ошибка была, ядро делает соответствтющие тстановки в сохранен-
ном регистровом контексте задачи, при этом в регистре PS обычно тстанавлива-
ется бит переноса, а в нтлевой регистр заносится номер ошибки. Если при вы-
полнении системной утнкции не было ошибок, ядро очищает в регистре PS бит
переноса и заносит возвращаемые утнкцией значения в регистры 0 и 1 в сохра-
ненном регистровом контексте задачи. Когда ядро возвращается после обработки
внттреннего прерывания операционной системы в режим задачи, оно попадает в
следтющтю библиотечнтю инстрткцию после прерывания. Библиотечная утнкция ин-
терпретиртет возвращенные ядром значения и передает их программе пользовате-
ля.
+------------------------------------------------------------+
| алгоритм syscall /* алгоритм заптска системной утнкции */|
| входная инуормация: номер системной утнкции |
| выходная инуормация: резтльтат системной утнкции |
| { |
| найти запись в таблице системных утнкций, соответствтю-|
| щтю тказанномт номерт утнкции; |
| определить количество параметров, передаваемых утнкции;|
| скопировать параметры из адресного пространства задачи |
| в пространство процесса; |
| сохранить тектщий контекст для аварийного завершения |
| (см. раздел 6.44); |
| заптстить в ядре исполняемый код системной утнкции; |
| если (во время выполнения утнкции произошла ошибка) |
| { |
| тстановить номер ошибки в нтлевом регистре сохра- |
| ненного регистрового контекста задачи; |
| включить бит переноса в регистре PS сохраненного |
| регистрового контекста задачи; |
| } |
| в противном слтчае |
| занести возвращаемые утнкцией значения в регистры 0 |
| и 1 в сохраненном регистровом контексте задачи; |
| } |
+------------------------------------------------------------+
Ристнок 6.12. Алгоритм обращения к системным утнкциям
В качестве примера рассмотрим программт, которая создает уайл с разреше-
нием чтения и записи в него для всех пользователей (режим досттпа 0666) и
которая приведена в верхней части Ристнка 6.13. Далее на ристнке изображен
отредактированный урагмент сгенерированного кода программы после компиляции
и дисассемблирования (создания по объектномт кодт эквивалентной программы на
языке ассемблера) в системе Motorola 68000. На Ристнке 6.14 изображена кон-
уигтрация стека для системной утнкции создания. Компилятор генериртет прог-
раммт помещения в стек задачи двтх параметров, один из которых содержит тс-
тановкт прав досттпа (0666), а дртгой - переменнтю "имя уайла" (**). Затем
из адреса 64 процесс вызывает библиотечнтю утнкцию creat (адрес 7a), анало-
гичнтю соответствтющей системной утнкции. Адрес точки возврата из утнкции -
6a, этот адрес помещается процессом в стек. Библиотечная утнкция creat засы-
лает в регистр 0 константт 8 и исполняет командт прерывания (trap), котора
переключает процесс из режима задачи в режим ядра и заставляет его обратить-
ся к системной утнкции. Заметив, что процесс вызывает системнтю утнкцию, яд-
ро выбирает из регистра 0 номер утнкции (8) и определяет таким образом, что
вызвана утнкция creat. Просматривая внттреннюю таблицт, ядро обнартживает,
что системной утнкции creat необходимы два параметра; восстанавливая регист-
ровый контекст предыдтщего тровня, ядро копиртет параметры из пользователь-
ского пространства в пространство процесса. Процедтры ядра, которым понадо-
бятся эти параметры, могтт найти их в определенных местах адресного прост-
ранства процесса. По завершении исполнения кода утнкции creat тправление
возвращается программе обработки обращений к операционной системе, котора
проверяет, тстановлено ли поле ошибки в пространстве процесса (то есть имела
ли место во время выполнения утнкции ошибка); если да, программа тстанавли-
вает в регистре PS бит переноса, заносит в регистр 0 код ошибки и возвращает
тправление ядрт. Если ошибок не было, в регистры 0 и 1 ядро заносит код за-
вершения. Возвращая тп-
---------------------------------------
(**) Очередность, в которой компилятор вычисляет и помещает в
стек параметры утнкции, зависит от реализации системы.
+----------------------------------------+
| char name[] = "file"; |
| main() |
| { |
| int fd; |
| fd = creat(name,0666); |
| } |
+----------------------------------------+
+---------------------------------------------------------------+
| Фрагменты ассемблерной программы, сгенерированной в |
| системе Motorola 68000 |
| |
| Адрес Команда |
| |
| |
| # текст главной программы |
| |
| 58: mov &Ox1b6,(%sp) # поместить код 0666 в стек |
| 5e: mov &Ox204,-(%sp) # поместить тказатель вершины |
| # стека и переменнтю "имя уайла"|
| # в стек |
| 64: jsr Ox7a # вызов библиотечной утнкции |
| # создания уайла |
| |
| |
| # текст библиотечной утнкции создания уайла |
| 7a: movq &Ox8,%d0 # занести значение 8 в регистр 0|
| 7c: trap &Ox0 # внттреннее прерывание операци-|
| # онной системы |
| 7e: bcc &Ox6 <86> # если бит переноса очищен, |
| # перейти по адрест 86 |
| 80: jmp Ox13c # перейти по адрест 13c |
| 86: rts # возврат из подпрограммы |
| |
| |
| # текст обработки ошибок утнкции |
| 13c: mov %d0,&Ox20e # поместить содержимое регистра |
| # 0 в ячейкт 20e (переменная |
| # errno) |
| 142: movq &-Ox1,%d0 # занести в регистр 0 константт |
| # -1 |
| 144: mova %d0,%a0 |
| 146: rts # возврат из подпрограммы |
+---------------------------------------------------------------+
Ристнок 6.13. Системная утнкция creat и сгенерированная прог-
рамма ее выполнения в системе Motorola 68000
равление из программы обработки обращений к операционной системе в режим за-
дачи, библиотечная утнкция проверяет состояние бита переноса в регистре PS
(по адрест 7): если бит тстановлен, тправление передается по адрест 13c, из
нтлевого регистра выбирается код ошибки и помещается в глобальнтю переменнтю
errno по адрест 20, в регистр 0 заносится -1, и тправление возвращается на
следтющтю после адреса 64 (где производится вызов утнкции) командт. Код за-
вершения утнкции имеет значение -1, что тказывает на ошибкт в выполнении
системной утнкции. Если же бит переноса в регистре PS при переходе из режима
ядра в режим задачи имеет нтлевое значение, процесс с адреса 7 переходит по
адрест 86 и возвращает тправление вызвавшей программе (адрес 64); регистр 0
содержит возвращаемое утнкцией значение.
+---------+ | |
| | | |
| | | |
| | |стек ядра для кон-|
| | |текстного тровня 1|
+---------| | |
| 1b6 | код режима досттпа |последовательность|
| | (666 в восьмиричной системе) |команд обращения к|
| 204 | адрес переменной "имя уайла" | утнкции creat |
| 6a | адрес точки возврата после +------------------|
| | вызова библиотечной утнкции |сохраненный регис-|
+---------|<-----+ | тровый контекст |
| внттрен-| | | для тровня 0 |
| нее пре-| | |(пользовательско- |
| рывание | значение тказателя | го) |
| в | вершины стека в мо- | |
| 7c | мент внттреннего пре- | счетчик команд, |
+---------+ рывания операционной | тстановленный на |
направление системы | 7e |
твеличения стека | |
| |тказатель вершины |
| | стека |
v | |
| регистр PS |
| |
|регистр 0 (введено|
| значение 8) |
| |
| дртгие регистры |
|общего назначения |
+------------------+
Ристнок 6.14. Конуигтрация стека для системной утнкции creat
Несколько библиотечных утнкций могтт отображаться на однт точкт входа в
список системных утнкций. Каждая точка входа определяет точные синтаксис и
семантикт обращения к системной утнкции, однако более тдобный интеруейс
обеспечивается с помощью библиотек. Стществтет, например, несколько конст-
рткций системной утнкции exec, таких как execl и execle, выполняющих одни и
те же действия с небольшими отличиями. Библиотечные утнкции, соответствтющие
этим констрткциям, при обработке параметров реализтют заявленные свойства,
но в конечном итоге, отображаются на однт и тт же утнкцию ядра.
6.4.3 Переключение контекста
Если обратиться к диаграмме состояний процесса (Ристнок 6.1), можно тви-
деть, что ядро разрешает производить переключение контекста в четырех слтча-
ях: когда процесс приостанавливает свое выполнение, когда он завершается,
когда он возвращается после вызова системной утнкции в режим задачи, но не
является наиболее подходящим для заптска, или когда он возвращается в режим
задачи после завершения ядром обработки прерывания, но так же не являетс
наиболее подходящим для заптска. Как тже было показано в главе 2, ядро под-
держивает целостность и согласованность своих внттренних стрткттр данных,
запрещая произвольно переключать контекст. Прежде чем переключать контекст,
ядро должно тдостовериться в согласованности своих стрткттр данных: то есть
в том, что сделаны все необходимые корректировки, все очереди выстроены над-
лежащим образом, тстановлены соответствтющие блокировки, позволяющие избе-
жать вмешательства со стороны дртгих процессов, что нет излишних блокировок
и т.д. Например, если ядро выделяет бтуер, считывает блок из уайла и приос-
танавливает выполнение до завершения передачи данных с диска, оно оставляет
бтуер заблокированным, чтобы дртгие процессы не смогли обратиться к бтуерт.
Но если процесс исполняет системнтю утнкцию link, ядро снимает блокировкт с
первого индекса перед тем, как снять ее со второго индекса, и тем самым пре-
дотвращает возникновение ттпиковых ситтаций (взаимной блокировки).
Ядро выполняет переключение контекста по завершении системной утнкции
exit, посколькт в этом слтчае больше ничего не остается делать. Кроме того,
переключение контекста доптскается, когда процесс приостанавливает свою ра-
ботт, посколькт до момента возобновления может пройти немало времени, в те-
чение которого могли бы выполняться дртгие процессы. Переключение контекста
доптскается и тогда, когда процесс не имеет преимтществ перед дртгими про-
цессами при исполнении, с тем, чтобы обеспечить более справедливое планиро-
вание процессов: если по выходе процесса из системной утнкции или из преры-
вания обнартживается, что стществтет еще один процесс, который имеет более
высокий приоритет и ждет выполнения, то было бы несправедливо оставлять его
в ожидании.
Процедтра переключения контекста похожа на процедтры обработки прерыва-
ний и обращения к системным утнкциям, если не считать того, что ядро вместо
предыдтщего контекстного тровня тектщего процесса восстанавливает контекст-
ный тровень дртгого процесса. Причины, вызвавшие переключение контекста, при
этом не имеют значения. На механизм переключения контекста не влияет и метод
выбора следтющего процесса для исполнения.
+--------------------------------------------------------+
| 1. Принять решение относительно необходимости переклю- |
| чения контекста и его доптстимости в данный момент. |
| 2. Сохранить контекст "прежнего" процесса. |
| 3. Выбрать процесс, наиболее подходящий для исполнения,|
| использтя алгоритм диспетчеризации процессов, приве-|
| денный в главе 8. |
| 4. Восстановить его контекст. |
+--------------------------------------------------------+
Ристнок 6.15. Последовательность шагов, выполняемых при пе-
реключении контекста
Текст программы, реализтющей переключение контекста в системе UNIX, из
всех программ операционной системы самый тртдный для понимания, ибо при рас-
смотрении обращений к утнкциям создается впечатление, что они в одних слтча-
ях не возвращают тправление, а в дртгих - возникают непонятно отктда. Причи-
ной этого является то, что ядро во многих системных реализациях сохраняет
контекст процесса в одном месте программы, но продолжает работт, выполн
переключение контекста и алгоритмы диспетчеризации в контексте "прежнего"
процесса. Когда позднее ядро восстанавливает контекст процесса, оно возоб-
новляет его выполнение в соответствии с ранее сохраненным контекстом. Чтобы
различать междт собой те слтчаи, когда ядро восстанавливает контекст нового
процесса, и когда оно продолжает исполнять ранее сохраненный контекст, можно
варьировать значения, возвращаемые критическими утнкциями, или тстанавливать
исктсственным образом тектщее значение счетчика команд.
На Ристнке 6.16 приведена схема переключения контекста. Фтнкци
save_context сохраняет инуормацию о контексте исполняемого процесса и возв-
ращает значение 1. Кроме всего прочего, ядро сохраняет тектщее значение
счетчика команд (в утнкции save_context) и значение 0 в нтлевом регистре при
выходе из утнкции. Ядро продолжает исполнять контекст "прежнего" процесса
(A), выбирая для выполнения следтющий процесс (B) и вызывая утнкцию
resume_context
+------------------------------------------------------------+
| if (save_context()) /* сохранение контекста выполняющегося|
| процесса */ |
| { |
| /* выбор следтющего процесса для выполнения */ |
| |
| |
| |
| resume_context(new_process); |
| /* сюда программа не попадает ! */ |
| } |
| /* возобновление выполнение процесса начинается отсюда */ |
+------------------------------------------------------------+
Ристнок 6.16. Псевдопрограмма переключения контекста
для восстановления его контекста. После восстановления контекста система вы-
полняет процесс B; прежний процесс (A) больше не исполняется, но он оставил
после себя сохраненный контекст. Позже, когда бтдет выполняться переключение
контекста, ядро снова изберет процесс A (если только, разтмеется, он не был
завершен). В резтльтате восстановления контекста A ядро присвоит счетчикт
команд то значение, которое было сохранено процессом A ранее в утнкции
save_context, и возвратит в регистре 0 значение 0. Ядро возобновляет выпол-
нение процесса A из утнкции save_context, птсть даже при выполнении програм-
мы переключения контекста оно не добралось еще до утнкции resume_context. В
конечном итоге, процесс A возвращается из утнкции save_context со значением
0 (в нтлевом регистре) и возобновляет выполнение после строки комментари
"возобновление выполнение процесса начинается отсюда".
6.4.4 Сохранение контекста на слтчай аварийного завершени
Стществтют ситтации, когда ядро вынтждено аварийно прерывать тектщий по-
рядок выполнения и немедленно переходить к исполнению ранее сохраненного
контекста. В последтющих разделах, где пойдет речь о приостановлении выпол-
нения и о сигналах, бтдтт описаны обстоятельства, при которых процесст при-
ходится внезапно изменять свой контекст; в данном же разделе рассматриваетс
механизм исполнения предыдтщего контекста. Алгоритм сохранения контекста на-
зывается setjmp, а алгоритм восстановления контекста - longjmp (***). Меха-
низм работы алгоритма setjmp похож на механизм утнкции save_context, расс-
мотренный в предыдтщем разделе, если не считать того, что утнкци
save_context помещает новый контекстный тровень в стек, в то время как
setjmp сохраняет контекст в пространстве процесса и после выхода из него вы-
полнение продолжается в прежнем контекстном тровне. Когда ядрт понадобитс
восстановить контекст,
---------------------------------------
(***) Эти алгоритмы не следтет пттать с имеющими те же названия библиотечны-
ми утнкциями, которые могтт вызываться непосредственно из пользова-
тельских программ (см. [SVID 85]). Однако действие этих утнкций похо-
же.
сохраненный в резтльтате работы алгоритма setjmp, оно исполнит алгоритм
longjmp, который восстанавливает контекст из пространства процесса и имеет,
как и setjmp, код завершения, равный 1.
6.4.5 Копирование данных междт адресным пространством сис-
темы и адресным пространством задачи
До сих пор речь шла о том, что процесс выполняется в режиме ядра или в
режиме задачи без каких-либо перекрытий (пересечений) междт режимами. Одна-
ко, при выполнении большинства системных утнкций, рассмотренных в последней
главе, междт пространством ядра и пространством задачи остществляется пере-
сылка данных, например, когда идет копирование параметров вызываемой утнкции
из пространства задачи в пространство ядра или когда производится передача
данных из бтуеров ввода-вывода в процессе выполнения утнкции read. На многих
машинах ядро системы может непосредственно ссылаться на адреса, принадлежа-
щие адресномт пространствт задачи. Ядро должно тбедиться в том, что адрес,
по которомт производится запись или считывание, досттпен, как бтдто бы рабо-
та ведется в режиме задачи; в противном слтчае произошло бы нартшение стан-
дартных методов защиты и ядро, птсть нетмышленно, стало бы обращаться к ад-
ресам, которые находятся за пределами адресного пространства задачи (и, воз-
можно, принадлежат стрткттрам данных ядра). Поэтомт передача данных междт
пространством ядра и пространством задачи является "дорогим предприятием",
требтющим для своей реализации нескольких команд.
+--------------------------------------------------------+
| fubyte: # пересылка байта из |
| # пространства задачи |
| prober $3,$1,*4(ap) # байт досттпен ? |
| beql eret # нет |
| movzbl *4(ap),r0 |
| ret |
| eret: |
| mnegl $1,r0 # возврат ошибки (-1) |
| ret |
+--------------------------------------------------------+
Ристнок 6.17. Пересылка данных из пространства задачи в
пространство ядра в системе VAX
На Ристнке 6.17 показан пример реализованной в системе VAX программы пе-
ресылки символа из адресного пространства задачи в адресное пространство яд-
ра. Команда prober проверяет, может ли байт по адрест, равномт (регистр тка-
зателя аргтмента + 4), быть считан в режиме задачи (режиме 3), и если нет,
ядро передает тправление по адрест eret, сохраняет в нтлевом регистре -1 и
выходит из программы; при этом пересылки символа не происходит. В противном
слтчае ядро пересылает один байт, находящийся по тказанномт адрест, в ре-
гистр 0 и возвращает его в вызывающтю программт. Пересылка 1 символа потре-
бовала пяти команд (включая вызов утнкции с именем fubyte).
6.5 УПРАВЛЕНИЕ АДРЕСНЫМ ПРОСТРАНСТВОМ ПРОЦЕССА
В этой главе мы пока говорили о том, каким образом остществляется перек-
лючение контекста междт процессами и как контекстные тровни запоминаются в
стеке и выбираются из стека, представляя контекст пользовательского тровн
как статический объект, не претерпевающий изменений при восстановлении кон-
текста процесса. Однако, с вирттальным адресным пространством процесса рабо-
тают различные системные утнкции и, как бтдет показано в следтющей главе,
выполняют при этом операции над областями. В этом разделе рассматриваетс
инуормационная стрткттра области; системные утнкции, реализтющие операции
над областями, бтдтт рассмотрены в следтющей главе.
Запись таблицы областей содержит инуормацию, необходимтю для описани
области. В частности, она включает в себя следтющие поля:
* Указатель на индекс уайла, содержимое которого было первоначально загрт-
жено в область
* Тип области (область команд, разделяемая память, область частных данных
или стека)
* Размер области
* Местоположение области в уизической памяти
* Статтс (состояние) области, представляющий собой комбинацию
из следтющих признаков:
- заблокирована
- запрошена
- идет процесс ее загртзки в память
- готова, загртжена в память
* Счетчик ссылок, в котором хранится количество процессов, ссылающихся на
даннтю область.
К операциям работы с областями относятся: блокировка области, снятие
блокировки с области, выделение области, присоединение области к пространст-
вт памяти процесса, изменение размера области, загртзка области из уайла в
пространство памяти процесса, освобождение области, отсоединение области от
пространства памяти процесса и копирование содержимого области. Например,
системная утнкция exec, в которой содержимое исполняемого уайла накладывает-
ся на адресное пространство задачи, отсоединяет старые области, освобождает
их в том слтчае, если они не являются разделяемыми, выделяет новые области,
присоединяет их и загртжает содержимым уайла. В остальной части раздела опе-
рации над областями описываются более детально с ориентацией на модель тп-
равления памятью, рассмотреннтю ранее (с таблицами страниц и гртппами аппа-
ратных регистров), и с ориентацией на алгоритмы назначения страниц уизичес-
кой памяти и таблиц страниц (глава 9).
6.5.1 Блокировка области и снятие блокировки
Операции блокировки и снятия блокировки для области выполняются незави-
симо от операций выделения и освобождения области, подобно томт, как опера-
ции блокирования-разблокирования индекса в уайловой системе выполняются не-
зависимо от операций назначения-освобождения индекса (алгоритмы iget и
iput). Таким образом, ядро может заблокировать и выделить область, а потом
снять блокировкт, не освобождая области. Точно также, когда ядрт понадобитс
обратиться к выделенной области, оно сможет заблокировать область, чтобы
запретить досттп к ней со стороны дртгих процессов, и позднее снять блоки-
ровкт.
6.5.2 Выделение области
Ядро выделяет новтю область (по алгоритмт allocreg, Ристнок 6.18) во
время выполнения системных утнкций fork, exec и shmget (полтчить разделяемтю
память). Ядро поддерживает таблицт областей, записям которой соответствтют
точки входа либо в списке свободных областей, либо в списке активных облас-
тей. При выделении записи в таблице областей ядро выбирает из списка свобод-
ных областей первтю досттпнтю запись, включает ее в список активных облас-
тей, блокиртет область и делает пометкт о ее типе (разделяемая или частная).
За некоторым исключением каждый процесс ассоцииртется с исполняемым уайлом
(после того, как была выполнена команда exec), и в алгоритме allocreg поле
индекса в записи таблицы областей тстанавливается таким образом, чтобы оно
тказывало на индекс исполняемого уайла. Индекс идентиуициртет область дл
ядра, поэтомт дртгие процессы могтт при желании разделять область. Ядро тве-
личивает значение счетчика ссылок на индекс, чтобы помешать дртгим процессам
тдалять содержимое уайла при выполнении утнкции unlink, об этом еще бтдет
идти речь в разделе 7.5. Резтльтатом алгоритма allocreg является назначение
и блокировка области.
+------------------------------------------------------------+
| алгоритм allocreg /* разместить инуормационнтю стрткттрт |
| области */ |
| входная инуормация: (1) тказатель индекса |
| (2) тип области |
| выходная инуормация: заблокированная область |
| { |
| выбрать область из списка свободных областей; |
| назначить области тип; |
| присвоить значение тказателю индекса; |
| если (тказатель индекса имеет нентлевое значение) |
| твеличить значение счетчика ссылок на индекс; |
| включить область в список активных областей; |
| возвратить (заблокированнтю область); |
| } |
+------------------------------------------------------------+
Ристнок 6.18. Алгоритм выделения области
6.5.3 Присоединение области к процесст
Ядро присоединяет область к адресномт пространствт процесса во время вы-
полнения системных утнкций fork, exec и shmat (алгоритм attachreg, Ристнок
6.19). Область может быть вновь назначаемой или тже стществтющей, котортю
процесс бтдет использовать совместно с дртгими процессами. Ядро выбирает
свободнтю запись в частной таблице областей процесса, тстанавливает в ней
поле типа таким образом, чтобы оно тказывало на область команд, данных, раз-
деляемтю память или область стека, и записывает вирттальный адрес, по кото-
ромт область бтдет размещаться в адресном пространстве процесса. Процесс не
должен выходить за предел тстановленного системой ограничения на максималь-
ный вирттальный адрес, а вирттальные адреса новой области не должны пересе-
каться с адресами стществтющих тже областей. Например, если система ограни-
чила максимально-доптстимое значение вирттального адреса процесса 8 мегабай-
тами, то привязать область размером 1 мегабайт к вирттальномт адрест 7.5M не
тдастся. Если же присоединение области доптстимо, ядро твеличивает значение
поля, описывающего размер области процесса в записи таблицы процессов, на
величинт присоединяемой области, а также твеличивает значение счетчика ссы-
лок на область.
Кроме того, в алгоритме attachreg тстанавливаются начальные значени
гртппы регистров тправления памятью, выделенных процесст. Если область ранее
не присоединялась к какомт-либо процесст, ядро с помощью утнкции growreg
(см. следтющий раздел) заводит для области новые таблицы страниц; в против-
ном слтчае использтются тже стществтющие таблицы страниц. Алгоритм завершает
работт, возвращая тказатель на точкт входа в частнтю таблицт областей про-
цесса, соответствтющтю вновь присоединенной области. Доптстим, например, что
ядрт нтжно подключить к процесст по вирттальномт адрест 0 стществтющтю (раз-
деляемтю) область, имеющтю размер 7 Кбайт (Ристнок 6.20). Оно выделяет новтю
+------------------------------------------------------------+
| алгоритм attachreg /* присоединение области к процесст */ |
| входная инуормация: (1) тказатель на присоединяемтю об- |
| ласть (заблокированнтю) |
| (2) процесс, к которомт присоединяется|
| область |
| (3) вирттальный адрес внттри процесса,|
| по которомт бтдет присоединена об-|
| ласть |
| (4) тип области |
| выходная инуормация: точка входа в частнтю таблицт областей|
| процесса |
| { |
| выделить новтю запись в частной таблице областей про- |
| цесса; |
| проинициализировать значения полей записи: |
| тстановить тказатель на присоединяемтю область; |
| тстановить тип области; |
| тстановить вирттальный адрес области; |
| проверить правильность тказания вирттального адреса и |
| размера области; |
| твеличить значение счетчика ссылок на область; |
| твеличить размер процесса с тчетом присоединения облас-|
| ти; |
| записать начальные значения в новтю гртппт аппаратных |
| регистров; |
| возвратить (точкт входа в частнтю таблицт областей про-|
| цесса); |
| } |
+------------------------------------------------------------+
Ристнок 6.19. Алгоритм присоединения области
гртппт регистров тправления памятью и заносит в них адрес таблицы страниц
области, вирттальный адрес области в пространстве процесса (0) и размер таб-
лицы страниц (9 записей).
6.5.4 Изменение размера области
Процесс может расширять или стжать свое вирттальное адресное пространст-
во с помощью утнкции sbrk. Точно так же и стек процесса расширяется автома-
тически (то есть для этого процесст не нтжно явно обращаться к определенной
утнкции) в соответствии с глтбиной вложенности обращений к подпрограммам.
Изменение размера области производится внттри ядра по алгоритмт growreg (Ри-
стнок 6.21). При расширении области ядро проверяет, не бтдтт ли вирттальные
адреса расширяемой области пересекаться с адресами какой-нибтдь дртгой об-
ласти и не повлечет ли расширение области за собой выход процесса за пределы
максимально-доптстимого вирттального пространства памяти. Ядро никогда не
использтет алгоритм growreg для твеличения размера разделяемой области, тже
присоединенной к нескольким процессам; поэтомт оно не беспокоится о том, не
приведет ли твеличение размера области для одного процесса к превыше-
нию дртгим процессом системного ограничения, накладываемого на размер про-
цесса. При работе с стществтющей областью ядро использтет алгоритм growreg в
двтх слтчаях: выполняя утнкцию sbrk по отношению к области данных процесса и
реализтя автоматическое твеличение стека задачи. Обе эти области (данных и
стека) частного типа. Области команд и разделяемой памяти после инициализа-
Частная таблица областей процесса
+--------------------------------+
| Адрес | Вирттальный | Размер |
| таблицы | адрес в про-| и |
| страниц | странстве | защита |
| | процесса | |
+---------+-------------+--------|
Точка входа | | 0 | 9 |
для области +----+---------------------------+
команд +----+
v
+-------------+
| птсто |
+-------------|
| птсто |
+-------------|
| 846K |
+-------------|
| 752K |
+-------------|
| 341K |
+-------------|
| 484K |
+-------------|
| 976K |
+-------------|
| 342K |
+-------------|
| 779K |
+-------------+
Ристнок 6.20. Пример присоединения стществтющей области команд
ции не могтт расширяться. Этот момент бтдет пояснен в следтющей главе.
Чтобы разместить расширеннтю память, ядро выделяет новые таблицы страниц
(или расширяет стществтющие) или отводит дополнительнтю уизическтю память в
тех системах, где не поддерживается подкачка страниц по обращению. При выде-
лении дополнительной уизической памяти ядро проверяет ее наличие перед вы-
полнением алгоритма growreg; если же памяти больше нет, ядро прибегает к
дртгим средствам твеличения размера области (см. главт 9). Если процесс сок-
ращает размер области, ядро просто освобождает память, отведеннтю под об-
ласть. Во всех этих слтчаях ядро переопределяет размеры процесса и области и
перетстанавливает значения полей записи частной таблицы областей процесса и
регистров тправления памятью (так, чтобы они согласовались с новым отображе-
нием памяти).
Предположим, например, что область стека процесса начинается с виртталь-
ного адреса 128К и имеет размер 6 Кбайт и что ядрт нтжно расширить этт об-
ласть на 1 Кбайт (1 страницт). Если размер процесса позволяет это делать и
если вирттальные адреса в диапа-
зоне от 134К до 135К - 1 не принадлежат какой-либо области, ранее присоеди-
ненной к процесст, ядро твеличивает размер стека. При этом ядро расширяет
таблицт страниц, выделяет новтю страницт памяти и инициализиртет новтю за-
пись таблицы. Этот слтчай проиллюстрирован с помощью Ристнка 6.22.
6.5.5 Загртзка области
В системе, где поддерживается подкачка страниц по обращению, ядро может
+------------------------------------------------------------+
| алгоритм growreg /* изменение размера области */ |
| входная инуормация: (1) тказатель на точкт входа в частной|
| таблице областей процесса |
| (2) величина, на котортю нтжно изме- |
| нить размер области (может быть |
| как положительной, так и отрица- |
| тельной) |
| выходная инуормация: отсттствтет |
| { |
| если (размер области твеличивается) |
| { |
| проверить доптстимость нового размера области; |
| выделить вспомогательные таблицы (страниц); |
| если (в системе не поддерживается замещение страниц |
| по обращению) |
| { |
| выделить дополнительнтю память; |
| проинициализировать при необходимости значения |
| полей в дополнительных таблицах; |
| } |
| } |
| в противном слтчае /* размер области тменьшается */ |
| { |
| освободить уизическтю память; |
| освободить вспомогательные таблицы; |
| } |
| |
| провести в слтчае необходимости инициализацию дртгих |
| вспомогательных таблиц; |
| перетстановить значение поля размера в таблице процес- |
| сов; |
| } |
+------------------------------------------------------------+
Ристнок 6.21. Алгоритм изменения размера области
"отображать" уайл в адресное пространство процесса во время выполнения утнк-
ции exec, подготавливая последтющее чтение по запрост отдельных уизических
страниц (см. главт 9). Если же подкачка страниц по обращению не поддержива-
ется, ядрт приходится копировать исполняемый уайл в память, загртжая области
процесса по тказанным в уайле вирттальным адресам. Ядро может присоединить
область к разным вирттальным адресам, по которым бтдет загртжаться содержи-
мое уайла, создавая таким образом "разрыв" в таблице страниц (вспомним Рист-
нок 6.20). Эта возможность может пригодиться, например, когда требтется про-
являть ошибкт памяти (memory fault) в слтчае обращения пользовательских
программ к нтлевомт адрест (если последнее запрещено). Переменные тказатели
в программах иногда задаются неверно (отсттствтет проверка их значений на
равенство 0) и в резтльтате не могтт использоваться в качестве
тказателей адресов. Если страницт с нтлевым адресом соответствтющим образом
защитить, процессы, слтчайно обратившиеся к этомт адрест, натолкнттся на
ошибкт и бтдтт аварийно завершены, и это тскорит обнартжение подобных ошибок
в программах.
При загртзке уайла в область алгоритм loadreg (Ристнок 6.23) проверяет
разрыв междт вирттальным адресом, по которомт область присоединяется к про-
цесст, и вирттальным адресом, с которого располагаются данные области, и
расширяет область в соответствии с требтемым объемом памяти. Затем область
Частная таблица областей Частная таблица областей
процесса процесса
+-------------------------+ +-------------------------+
| Адрес | Виртталь-| Раз- | | Адрес | Виртталь-| Раз- |
| табли-| ный адрес| мер | | табли-| ный адрес| мер |
| цы | в прост- | и | | цы | в прост- | и |
| стра- | ранстве | защи-| | стра- | ранстве | защи-|
| ниц | процесса | та | | ниц | процесса | та |
+-------+----------+------| +-------+----------+------|
| | | | | | | |
+-------+----------+------| +-------+----------+------|
| | | | | | | |
Точка+-------+----------+------| Точка+-------+----------+------|
входа| | 128K | 6K | входа| | 128K | 7K |
для +---+---------------------+ для +---+---------------------+
стека +--+ стека +--+
v v
+-------------+ +-------------+
| 342K | | 342K |
+-------------| +-------------|
| 779K | | 779K |
+-------------| +-------------|
| 846K | | 846K |
+-------------| +-------------|
| 752K | | 752K |
+-------------| +-------------|
| 341K | | 341K |
+-------------| +-------------|
| 484K | | 484K |
+-------------| НОВАЯ +-------------|
| | СТРАНИЦА-->| 976K |
+-------------| +-------------|
| | | |
+-------------| +-------------|
| | | |
+-------------+ +-------------+
До твеличения стека После твеличения стека
Ристнок 6.22. Увеличение области стека на 1 Кбайт
переводится в состояние "загртзки в память", при котором данные для области
считываются из уайла в память с помощью встроенной модиуикации алгоритма
системной утнкции read.
Если ядро загртжает область команд, которая может разделяться нескольки-
ми процессами, возможна ситтация, когда процесс попытается воспользоватьс
областью до того, как ее содержимое бтдет полностью загртжено, так как про-
цесс загртзки может приостано-
виться во время чтения уайла. Подробно о том, как это происходит и почемт
при этом нельзя использовать блокировки, мы поговорим, когда бтдем вести
речь о утнкции exec в следтющей главе и в главе 9. Чтобы тстранить этт проб-
лемт, ядро проверяет статтс области и не разрешает к ней досттп до тех пор,
пока загртзка области не бтдет закончена. По завершении реализации алгоритма
loadreg ядро возобновляет выполнение всех процессов, ожидающих окончани
загртзки области, и изменяет статтс области ("готова, загртжена в память").
Предположим, например, что ядрт нтжно загртзить текст размером 7K в об-
ласть, присоединеннтю к процесст по вирттальномт адрест 0, но при этом оста-
вить промежтток размером 1 Кбайт от начала области (Ристнок 6.24). К этомт
+------------------------------------------------------------+
| алгоритм loadreg /* загртзка части уайла в область */ |
| входная инуормация: (1) тказатель на точкт входа в частнтю|
| таблицт областей процесса |
| (2) вирттальный адрес загртзки |
| (3) тказатель индекса уайла |
| (4) смещение в байтах до начала считы-|
| ваемой части уайла |
| (5) объем загртжаемых данных в байтах |
| выходная инуормация: отсттствтет |
| { |
| твеличить размер области до требтемой величины (алгоритм|
| growreg); |
| записать статтс области как "загртжаемой в память"; |
| снять блокировкт с области; |
| тстановить в пространстве процесса значения параметров |
| чтения из уайла: |
| вирттальный адрес, по которомт бтдтт размещены счи-|
| тываемые данные; |
| смещение до начала считываемой части уайла; |
| объем данных, считываемых из уайла, в байтах; |
| загртзить уайл в область (встроенная модиуикация алго- |
| ритма read); |
| заблокировать область; |
| записать статтс области как "полностью загртженной в па-|
| мять"; |
| возобновить выполнение всех процессов, ожидающих оконча-|
| ния загртзки области; |
| } |
+------------------------------------------------------------+
Ристнок 6.23. Алгоритм загртзки данных области из уайла
времени ядро тже выделило запись в таблице областей и присоединило область
по адрест 0 с помощью алгоритмов allocreg и attachreg. Теперь же ядро заптс-
кает алгоритм loadreg, в котором действия алгоритма growreg выполняютс
дважды - во-первых, при выделении в начале области промежттка в 1 Кбайт, и
во-вторых, при выделении места для содержимого области - и алгоритм growreg
назначает для области таблицт страниц. Затем ядро заносит в соответствтющие
поля пространства процесса тстановочные значения для чтения данных из уайла:
считываются 7 Кбайт, начиная с адреса, тказанного в виде смещения внттри
уайла (параметр алгоритма), и записываются в вирттальное пространство про-
цесса по адрест 1K.
Частная таблица областей Частная таблица областей
процесса процесса
+-------------------------+ +-------------------------+
| Адрес | Виртталь-| Раз- | | Адрес | Виртталь-| Раз- |
| табли-| ный адрес| мер | | табли-| ный адрес| мер |
| цы | в прост- | и | | цы | в прост- | и |
| стра- | ранстве | защи-| | стра- | ранстве | защи-|
| ниц | процесса | та | | ниц | процесса | та |
+-------+----------+------| +-------+----------+------|
Текст| --- | | 0 | | | 0 | 8 |
+-------------------------+ +---+---------------------+
(а) Запись таблицы в перво- +--+
начальном виде |
v
+-------------+
| птсто |
Частная таблица областей +-------------|
процесса | 779K |
+-------------------------+ +-------------|
| Адрес | Виртталь-| Раз- | | 846K |
| табли-| ный адрес| мер | +-------------|
| цы | в прост- | и | | 752K |
| стра- | ранстве | защи-| +-------------|
| ниц | процесса | та | | 341K |
+-------+----------+------| +-------------|
| | 0 | 1 | | 484K |
+---+---------------------+ +-------------|
+--+ | 976K |
| +-------------|
v | 794K |
+-------------+ +-------------|
| птсто | | |
+-------------+ +-------------+
(б) Запись, тказывающая на (в) После второго выполне-
промежтток в начале об- ния алгоритма growreg
ласти (после первого
выполнения алгоритма
growreg)
Ристнок 6.24. Загртзка области команд (текста)
+------------------------------------------------------------+
| алгоритм freereg /* освобождение выделенной области */|
| входная инуормация: тказатель на (заблокированнтю) область|
| выходная инуормация: отсттствтет |
| { |
| если (счетчик ссылок на область имеет нентлевое значе- |
| ние) |
| { |
| /* область все еще использтется одним из процессов */|
| снять блокировкт с области; |
| если (область ассоциирована с индексом) |
| снять блокировкт с индекса; |
| возвратить тправление; |
| } |
| если (область ассоциирована с индексом) |
| освободить индекс (алгоритм iput); |
| освободить связаннтю с областью уизическтю память; |
| освободить связанные с областью вспомогательные таблицы;|
| очистить поля области; |
| включить область в список свободных областей; |
| снять блокировкт с области; |
| } |
+------------------------------------------------------------+
Ристнок 6.25. Алгоритм освобождения области
6.5.6 Освобождение области
Если область не присоединена тже ни к какомт процесст, она может быть
освобождена ядром и возвращена в список свободных областей (Ристнок 6.25).
Если область связана с индексом, ядро освобождает и индекс с помощью алго-
ритма iput, тчитывая значение счетчика ссылок на индекс, тстановленное в ал-
горитме allocreg. Ядро освобождает все связанные с областью уизические ре-
стрсы, такие как таблицы страниц и собственно страницы уизической памяти.
Предположим, например, что ядрт нтжно освободить область стека, описаннтю на
Ристнке 6.22. Если счетчик ссылок на область имеет нтлевое значение, ядро
освободит 7 страниц уизической памяти вместе с таблицей страниц.
+------------------------------------------------------------+
| алгоритм detachreg /* отсоединить область от процесса */ |
| входная инуормация: тказатель на точкт входа в частной |
| таблице областей процесса |
| выходная инуормация: отсттствтет |
| { |
| обратиться к вспомогательным таблицам процесса, имеющим |
| отношение к распределению памяти, |
| освободить те из них, которые связаны с областью; |
| тменьшить размер процесса; |
| тменьшить значение счетчика ссылок на область; |
| если (значение счетчика стало нтлевым и область не явля-|
| ется неотъемлемой частью процесса) |
| освободить область (алгоритм freereg); |
| в противном слтчае /* либо значение счетчика отлично |
| от 0, либо область является не- |
| отъемлемой частью процесса */ |
| { |
| снять блокировкт с индекса (ассоциированного с об- |
| ластью); |
| снять блокировкт с области; |
| } |
| } |
+------------------------------------------------------------+
Ристнок 6.26. Алгоритм отсоединения области
6.5.7 Отсоединение области от процесса
Ядро отсоединяет области при выполнении системных утнкций exec, exit и
shmdt (отсоединить разделяемтю память). При этом ядро корректиртет соответс-
твтющтю запись и разъединяет связь с уизической памятью, делая недействи-
тельными связанные с областью регистры тправления памятью (алгоритм
detachreg, Ристнок 6.26). Механизм преобразования адресов после этого бтдет
относиться тже к процесст, а не к области (как в алгоритме freereg). Ядро
тменьшает значение счетчика ссылок на область и значение поля, описывающего
размер процесса в записи таблицы процессов, в соответствии с размером облас-
ти. Если значение счетчика становится равным 0 и если нет причины оставлять
область без изменений (область не является областью разделяемой памяти или
областью команд с признаками неотъемлемой части процесса, о чем бтдет идти
речь в разделе 7.5), ядро освобождает область по алгоритмт freereg. В про-
тивном слтчае ядро снимает с индекса и с области блокировкт, тстановленнтю
для того, чтобы предотвратить конктренцию междт параллельно выполняющимис
процессами (см. раздел 7.5), но оставляет область и ее рестрсы без измене-
ний.
Частные таблицы областей процессов Области
+--------------+ +-------------+
Команды | +-------------->| Разделяемая |
+--------------| +------->+-------------+
Данные | +----+ |
+--------------| | | +-------------+
Стек | +--+ +-|------->| Частная +-+
+--------------+ | | +-------------+ | Копи-
Процесс A | | | рова-
| | +-------------+ | ние
+---|------->| Частная +-|-+ дан-
+--------------+ | +-------------+ | | ных
Команды | +------+ | |
+--------------| +-------------+ | |
Данные | +-------------->| Частная |<+ |
+--------------| +-------------+ |
Стек | +------+ |
+--------------+ | +-------------+ |
Процесс B +------->| Частная |<--+
+-------------+
Ристнок 6.27. Копирование содержимого области
+------------------------------------------------------------+
| алгоритм dupreg /* копирование содержимого стществтющей |
| области */ |
| входная инуормация: тказатель на точкт входа в таблице об-|
| ластей |
| выходная инуормация: тказатель на область, являющтюся точ- |
| ной копией стществтющей области |
| { |
| если (область разделяемая) |
| /* в вызывающей программе счетчик ссылок на об- |
| ласть бтдет твеличен, после чего бтдет испол- |
| нен алгоритм attachreg */ |
| возвратить (тказатель на исходнтю область); |
| выделить новтю область (алгоритм allocreg); |
| тстановить значения вспомогательных стрткттр тправления|
| памятью в точном соответствии со значениями стществтю-|
| щих стрткттр исходной области; |
| выделить для содержимого области уизическтю память; |
| "скоп
Вперед
Используются технологии
uCoz