Примерный контекст задачи в 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) |
конец |