Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
VSOS_2014.doc
Скачиваний:
0
Добавлен:
01.07.2025
Размер:
1.9 Mб
Скачать
    1. Операции над процессами

В большинстве систем, допускающих параллельное выполнение процессов, последние могут создаваться и удаляться динамически. Следовательно, такие системы должны иметь механизмы создания и завершения процессов. Рассмотрим, каким образом эти операции выполняются в ОС UNIX и Windows.

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

Процесс может создать несколько новых процессов с помощью соответствующего системного вызова в течение своего выполнения. Порождающий процесс называется родительским (parent process) или процессом-отцом, а новый порожденный родительским – процессом-потомком (children process) или процессом-сыном, дочерним по отношению к порождающим. Каждый из новых процессов может породить другие процессы, формируя дерево процессов (см. рис. 6.2).

Большинство операционных систем (включая семейства UNIX и Windows) присваивают каждому процессу уникальный идентификатор, как правило, целое положительное число.

Если некоторый процесс порождает новый, то существуют две возможности для продолжения работы:

  • процесс-отец продолжает выполняться вместе со своими сыновьями;

  • процесс-отец ожидает завершения работы одного или нескольких своих потомков.

Кроме того, возможны два варианта использования адресного пространства порожденным процессом:

  • процесс-сын является клоном родительского процесса;

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

Рисунок 6.10 – Дерево процессов в UNIX-системах

Порождение процессов в системе UNIX происходит в результате выполнения системного вызова fork. ОС строит образ порожденного процесса, являющийся точной копией образа породившего процесса, то есть дублируются дескриптор, контекст и образ процесса. Вновь созданному процессу ОС присваивает целочисленный идентификатор, уникальный на весь период функционирования системы.

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

Обычно, после развилки одним из процессов выполняется системный вызов exec(), чтобы заменить пространство памяти процесса с новой программой. Этот системный вызов загружает двоичный файл в память (уничтожая образ программы, содержащей exec() обращение к операционной системе) и начинает его выполнение. Таким образом, два процесса способны взаимодействовать, а затем выполняться по разным программам. Родитель может затем породить других потомков; или, если у него нет других задач, подождать завершения потомка путем обращения к системному вызову wait() (см. рис. 6.3).

Рисунок 6.11 – Схема порождения нового процесса в UNIX

Ниже приводится программа, иллюстрирующая описанный подход.

#include <sys/types.h>

#include <stdio.h>

#include <unistd.h>

int main()

{

pid t pid;

/* развилка */

if ((pid = fork())< 0)

{/* обнаружена ошибка */

fprintf(stderr, “Fork failed\n”);

exit (-1) ;

}

else if (pid == 0)

{/* дочерний процесс*/

execlp ("/bin/ls", "ls", HULL) ;

}

else

{/* родительский процесс */

wait !MULL) ;

printf("Child Complete\n");

exit (0);

}

}

Таким образом, в UNIX порождение нового процесса происходит в два этапа – сначала создается копия процесса-родителя, затем у нового процесса производится замена кодового сегмента на заданный.

В качестве альтернативы рассмотрим создание процесса в Windows. Для создания процесса в Win32 API используется функция CreateProcess(), которая подобна функции fork() в том, что родитель создает новый процесс. Однако, тогда как при использовании fork() порожденный процесс наследует адресное пространство родителя, использование CreateProcess() приводит к загрузке указанной программы в адресное пространство порожденного процесса при его создании. К тому же, системный вызов fork() не требует задания параметров, а для функции CreateProcess() их требуется не менее 10.

Программа на языке C, приведенная ниже иллюстрирует работу функции CreateProcess(), которая создает новый процесс для приложения mspaint.exe. Для большинства параметров, передаваемых в CreateProcess() выберем значения по умолчанию.

#include <stdio.h>

#include <windows.h>

int main (void)

{

STARTUPINFO si;

PROCESS_INFORMATION pi;

// выделение памяти

zeromemory(&si, sizeof (si));

si.cb = sizeof (si);

zeromemory(&pi, sizeof (pi));

// создание дочернего процесса

if (!CreateProcess( NULL, // команднаю строка во 2 параметре

'C:\\WINDOWS\\system32\\mspaint.exe', // команда

NULL, // атрибуты защиты процесса по умолчанию

NULL, // атрибуты защиты главного потока по умолчанию

FALSE, // идентификаторы не наследуются

0, // флаги создания не используются

NULL, // наследовать окружение родителя

NULL, // наследовать текущий каталог

&si,

&pi

)

)

{

fprintf(stderr,”Create Process failed\n”);

return -1;

}

// Родительский процесс ожидает окончания дочернего

WaitForSingleObject(pi.hProcess, INFINITE);

printf(”Child complete\n”);

// закрытие объектов

CloseHandle(pi.hProcess,INFINITE);

CloseHandle(pi.hThread);

}

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]