Примерный контекст задачи в UNIX

АП в режиме задачи Управляющая информация Окружение процесса Аппаратный контекст
Код Данные Стек Разделяемая память   Proc u-area Данные для отображения виртуального АП в физическое Переменные окружения Их значения по умолчанию   Системный контекст Регистровый контекст  
Код и данные библиотек

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

Cоздание процесса в 2 этапа:

1. Порождение нового процесса - соответствующему системному вызову fork()

2. Системный вызов exec() - загрузка на выполнение, загрузка исполняемого кода данных в АП и запуск кода.

pid_f fork(void) - выполняет родительский процесс и создает точную копию самого себя.

Наследование:

· идентификатор пользователя, группы

· переменные окружения

· диспозиция сигналов и их обработки

· ограничения накладываются на текущий корневой каталог

· маска создания файлов

· все файловые дескрипторы , включая файловые указатели

· управляющий терминал

После возврата из вызова fork() в родительском и в потомке выполняется одна и та же инструкция.

Различия между потомками и родителями :

- дочернему присваивается свой PID, PPID у них различные

- дочерний процесс свободен от сигналов ожидающих доставки

- значение, возвращенное вызовом fork() в родителе и потомке различны. В потомке - 0 , а родителю возвращается PID потомка

- дочерний процесс получает свою копию u-area

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

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

Действия, которые выполняются при сист. вызове fork():

1. Резервируется место под swap для сегмента кода и данных из стека процесса

2. Размещается новая запись в /proc в таблицу процессов и присваивается новый PID - идентификатор процесса

3. Инициализируется структура proc

4. Размещение необходимых карт отображения для трансляции адреса.

5. Размещение структуры u-area для нового процесса и копирование информации родительского.

6. Создание соответствующей области процесса, часть из которой соответствует родительскому процессу, сообразно таблице наследования.

7. Инициализация аппаратного контекста процесса, пока как копия родительского.

8. Установка в "0" значения возвращаемое fork() процессу - потомку (и равное PID потомка для процесса - родителя)

9. Пометка как готового и установка в очередь готовых процессов.

В зависимости от версии UNIX по-разному осуществляется перенос в АП полезного кода

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

main ()

{

int pid;

pid = fork();

if (pid == -1)

{

perror (“fork”);

exit();

}

if (pid == 0)

{

// код, выполняемый потомком. Если хотим ещё параллельно потомков, то ещё вызов fork()

}

else

{

// код, выполняемый родителем.

}

printf (“something\n”); // выведется дважды, и потомком, и родителем

return 0;

}

 

Жизненный цикл процесса

Kill Sig-number Pid прерывание процессов (Sig-number номер сигнала т. к. они все пронумерованы)

Kill$! – отсылка сигнала процессу, с которым последний раз работали.

Proc& - запуск процесса в фоновом режиме.

Этап exec()

Выполняет 2 функции:

1. Заполняет АП из исполняемого файла

2. Запуск на исполнение

 

int execve(path,argv,envp)
int execv(const char *path,const char *argv)
int execvp(file,argv)
int execle(path,arg0,...,argN,0,envp)
int execl(file,arg0,...,argN,0)
int execl(path,arg0,...,argN,0)
Различные варианты вызовов exec() с различным набором параметров
ядро UNIX

#include <unistd.h>

 

С точки зрения полноты параметров наиболее близка функция execve().

Наследуются: PID, PPID родителя идентификатор пользователя и группы, эффективный идентификатор пользователя и группы (EUID, EGID) без флага SUID , ограничения на процесс, текущий и корневой каталог, маска создаваемых файлов, управляющий терминал, файловый дескриптор.

Системный вызов обычно содержит следующие аргументы exec():

1.Имя исполняемого файла (программы) (file)

2.Набор аргументов (args)

3.Список переменных окружения (envp)

В большинстве случаев не создаётся АП, а происходит замена АП как есть после вызова fork().(зависит от версии UNIX).

Все возвращаемые значения типа int

В большинстве обрабатываемых системных вызовах, если возвращается -1 то это ошибка.

 

Функции завершения

wait(&status) – блокировка выполнения процесса до смерти какого-либо из непосредственных потомков

waitid(id_type, id) – определяет потомка и все его изменения

waitpid(id_group или process_all) – позволяет контролировать определённое множество потомков. Контроль группы потомков – создаётся ID этой группы. Состояние всех потомков – process_all.

Возврат состояния – переменная stat_log. Её можно анализировать с помощью специальной макрокоманды.


Алгоритм выполнения системного вызова exec():

exec()
проверка прав доступа
чтение заголовка файла
исполнит. или нет ?
нет
да
анализ 1-ой строки #!shellname передача аргумента (если он есть) запуск программы Shell Name
скрипт
есть SUID(SGID) ?
Измен EUID (EGID) на UID (GID) исполняемого файла  
Аргументы exec() , переменные окружения записываются в АП ядра
Резервирование в области swap для сегмента кода, данных, стека
конец
освобождение старого АП процесса в обл. swap
размещение + инициализация карт отображения в память
сегмент кода активный ?
область заполняется содержимым соотв. раздела исполняемого файла или инициализируется 0  
данная область используется совместно
копирование производится на основе механизма страничного замещения
копирование сохраненных аргументов и переменных окружения в стек процесса
установка обработчиков сигналов, присвоение значений по умолчанию игнорированные и заблокированные не затрагиваются (установки не меняются)
инициализация аппаратного контекста. Присваивание IP адреса точку входа для новой программы
нет
да
нет
да
транслирование имени файла
2 3
запуск интерпретатора + передача файла на вывод(XPGH)
конец