Выполнение кода ОС по отношению к процессам

Поскольку ОС тоже является программой, то возникает вопрос: является ли ОС процессом? Если да, то как осуществляется управление этим процессом?

Существуют следующие подходы к разработке ОС.

Ядро вне процессов (автономное ядро)

Используется во многих ранних ОС. Концепция процесса применяется только к пользовательским программам. Код ОС выполняется как некий отдельный объект, работающий в привилегированном режиме (рис. 3.3, а).

Выполнение кода ОС по отношению к процессам - №1 - открытая онлайн библиотека

Ядро в составе пользовательских процессов

Используется в небольших ЭВМ (ПК, рабочих станциях). Почти все программы ОС выполняются в контексте пользовательского процесса (рис. 3.3, б). Типичный образ процесса также показан на рис. 3.3, б. При вызове системных процедур, работающих в режиме ядра, и возврата из них используется отдельный стек ядра. Код и данные ОС находятся в совместно используемом адресном пространстве и доступны для использования всеми пользовательскими процессами. Таким образом, при прерывании, включая системный вызов, переключения процессов не происходит, переключается только режим работы процессора (пользовательский <-> ядра) в рамках одного и того же процесса. В ходе процесса могут выполняться и пользовательские программы, и программы ОС. Программы ОС, выполняемые в разных пользовательских процессах, являются идентичными.

ОС на основе процессов

На рис. 3.3, в показана структура ОС на основе процессов. Преимущества такого подхода: 1) способствует разработке модульных ОС с простыми межмодульными интерфейсами; 2) некоторые второстепенные функции ОС удобно реализовывать в виде отдельных процессов; эти функции может вызывать только ОС, и такие процессы могут чередоваться с пользовательскими; в многопроцессорных и многокомпьютерных ВС отдельные службы ОС могут выполняться на разных процессорах и, соответственно, будет выше производительность системы.

Вопросы для самоконтроля

1. Дайте определение понятию "процесс".

2. В результате каких событий создаются процессы?.

3. Перечислите причины завершения процессов.

4. Какой процесс называется родительским?

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

6. Перечислите состояния процесса в модели с двумя состояниями.

7. Перечислите состояния процесса в модели с пятью состояниями.

8. Какие переходы между состояниями существуют в модели процесса с пятью состояниями? При каких условиях осуществляются эти переходы?

9. Какие переходы, не показанные на рис. 3.2, могут существовать в модели процесса с пятью состояниями?

10. Что такое вытеснение процесса?

11. Дайте определение понятию "образ процесса".

12. Какая информация входит в управляющий блок процесса?

13. Каковы дествия ОС при создании процесса?

14. В какие моменты может произойти переключение процессов?

15. Чем отличаются переключение режима работы процессора и переключение процессов?

16. Каковы действия ОС при переключении процессов?

17. Перечислите варианты выполнения кода ОС по отношению к процессам.

18. Для чего в ОС Windows, UNIX и др. код операционной системы является частью пользовательского процесса?

Тема 4. Системные вызовы управления процессами в ОС UNIX

На рис. 3.4 приведена упрощенная диаграмма процесса в ОС UNIX. Идентификатор процесса называется PID (Process Identifier).

Выполнение кода ОС по отношению к процессам - №2 - открытая онлайн библиотека

Создание процесса

Для создания нового процесса предназначен системный вызов fork.

#include <unistd.h>

pid_t fork(void);

Вызывающий процесс становится родительским, а новый процесс – его потомком. Функция fork возвращает 0 – в дочерний процесс; PID потомка – в родительский процесс; При ошибке (недостаточно памяти или места в системных таблицах) fork возвращает -1.

Процесс-потомок является точной копией своего родительского процесса. Его адресное пространство полностью повторяет адресное пространство родительского процесса. После возврата из fork оба процесса начинают работать в пользовательском режиме – выполняют команды, следующие за fork.

Фрагмент программы для создания процесса:

#include <unistd.h>

int pid;

pid=fork();

if(pid==-1) {perror("fork()"); exit(1);}

if (pid==0)

{/*команды дочернего процесса*/}

else

{/*остальная часть кода родительского процесса*/}

Как работает fork. В ранних версиях UNIX fork создавал копию адресного пространства родительского процесса физическим копированием адресного пространства родителя в дочерний процесс. Но если затем потомок вызывал exec, меняя, таким образом, свой образ памяти, то вся работа по копированию адресного пространства была лишней.

В современных версиях UNIX используется механизм "Копирование при записи". Сразу после создания дочерний процесс получает копию адресного пространства родителя путем копирования только таблицы страниц. При этом все страницы помечаются атрибутом "только для чтения". Если один из процессов попытается произвести запись, то возникнет исключение, ОС создаст новую страницу и снимет атрибут "только для чтения" с соответствующей страницы в обоих процессах. Таким образом, процессы разделяют страницы кода и страницы с теми данными, которые не изменялись. Те же страницы, данные на которых изменялись, – разные для обоих процессов.

Завершение процесса

Системный вызов exit завершает процесс.

#include <unistd.h>

void exit(int status);

Здесь status – код возврата, который может быть получен родительским процессом при помощи системного вызова wait.

Системный вызов exit освобождает адресное пространство процесса и другие ресурсы, но не освобождает управляющий блок процесса (в ОС Linux – это структура task_struct) и посылает родителю сигнал SIGCHLD. Если родительский процесс завершается раньше дочернего, то последний удочеряется системным процессом init (с PID=1).