Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лаб_процессы.doc
Скачиваний:
1
Добавлен:
27.11.2019
Размер:
225.28 Кб
Скачать

Содержание

1. Теоретическая часть 2

1.1 Процессы. Создание процессов – функция fork() 2

1.2 Передача управления: execve() 5

1.3 Семейство exec(). 7

1.4 Ожидание процесса wait(). 8

1.5 Межпроцессорное взаимодействие, каналы( pipe() ). 10

2. Описание базовых программ 14

3. Список заданий 19

4. Список использованной литературы. 20

1. Теоретическая часть

1.1 Процессы. Создание процессов – функция fork()

Термин "процесс" впервые появился при разработке операционной системы Multics и имеет несколько определений, которые используются в зависимости от контекста. Процесс - это:

1) программа на стадии выполнения.

2) "объект", которому выделено процессорное время.

3) программа + системные данные.

Для описания состояний процессов используется несколько моделей. Самая простая модель - это модель трех состояний. Модель состоит из:

1) состояния выполнения

2) состояния ожидания

3) состояния готовности

Выполнение - это активное состояние, во время которого процесс обладает всеми необходимыми ему ресурсами. В этом состоянии процесс непосредственно выполняется процессором.

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

Готовность - это тоже пассивное состояние, процесс тоже заблокирован, но в отличие от состояния ожидания, он заблокирован не по внутренним причинам (ведь ожидание ввода данных - это внутренняя, "личная" проблема процесса - он может ведь и не ожидать ввода данных и свободно выполняться - никто ему не мешает), а по внешним, независящим от процесса, причинам.

Над процессами можно производить следующие операции:

1) Создания

2) Уничтожения

4) Изменения приоритет

5) Блокирования

6) Пробуждения

7) Запуск процесса (или его выбор)

Для создания процесса операционной системе нужно:

1) Присвоить процессу имя и номер

2) Добавить информацию о процессе в системную таблицу процессов

3) Определить приоритет процесса

4) Предоставить процессу нужные ему ресурсы

Каждому процессу в системе назначаются числовые идентификаторы (личные номера) в диапазоне от 1 до 65535 (PID – Process Identifier – идентификатор процесса) и идентификаторы родительского процесса (PPID – Parent Process Identifier – идентификатор родительского процесса). PID является именем процесса, по которому он адресуется в операционной системе. PID каждого процесса уникальный, т.е. не может быть два запущенных процесса , имеющих один и тот же PID. Зачастую PID возрастают в значениях, т.е. PID порожденного процесса обычно имеет большее значения чем PID его родителя, но в случае переполнения, порожденный процесс создается с любым меньшим не используемым номером PID. PPID определяет родственные отношения между процессами, которые в значительной степени определяют его свойства и возможности.Если родительский процесс завершается, порожденному процессу в качестве родителя назначается родитель родителя. Если процесса верхнего уровня нет, то в качестве родителя назначается системный процесс init, PID которого равен 1.

Для порождения нового процесса предназначен системный вызов fork(), объявленный в заголовочном файле unistd.h следующим образом:

pid_t fork(void);

Системный вызов fork() порождает процесс методом “клонирования”. Это значит, что новый процесс является точной копией своего родителя и выполняет ту же самую программу.

Листинг 1.1 fork1.c

#include <unistd.h>

#include <stdio.h>

int main(void)

{

fork();

printf(“Helo World!\n”);

sleep(20);

return 0;

}

В результате мы получим, что фраза “Hello World!” напечаталась 2 раза. Это объясняется тем, что каждый процесс продолжил самостоятельно выполнять одну и туже программу.

Чтобы в контексте программы отделить один процесс от другого, достаточно знать, что системный вызов fork(), возвращает в текущем процессе PID порожденного потомка (или -1 в случае ошибки). А новый процесс возвращает 0.

Листинг 1.2 fork2.c

#include <unistd.h>

#include <stdio.h>

#include <sys/types.h>

int main(void)

{

pid_t result = fork();

if (result == -1)

{

fprintf(strerr,”Error\n”);

return 1;

}

if (result == 0)

printf(“I’m child whit PID = %d\n”,getpid());

else

printf(“I’m parent whit PID = %d\n”,getpid());

return 0;

}

Системный вызов getppid() возвращает PID родителя, а системный вызов getpid() – PID текущего процесса, оба системных вызова определены в <unistd.h>. Обработка ошибок с помощью библиотечной функции stderr() из модуля <errno.h>, получение номеров родителя и потомка представлены в листинге 2.1.

Листинг 1.3 getpid.c.

#include <sys/types.h>

#include <unistd.h>

#include <stdio.h>

#include <errno.h>

int main(int argc, char** argv)

{

pid_t pid_number, child, parent;

printf("\nOriginal parent: %d\n", getpid());/*перед fork()*/

if ((pid_number = fork()) < 0)

{

fprintf(stderr,"%s: fork of child failed: %s\n", argv[0],strerror(errno));

exit(1);

}

else if (pid_number == 0 )

{

child = getpid();

parent = getppid();

printf("Child: my PID%d my PPID= %d \n ",child, parent);

}

else {

printf("Parent: my PID = %d my PPID = %d \n", getpid(), getppid());

printf("Parent: my child process PID = %d \n ", pid­_number);

exit(0);/*родитель завершается после fork()*/

}

/*нижележащий код выполняет только порожденный процесс*/

….

exit(0);

}

После завершения функции fork() в ОС присутствуют уже два одинаковых процесса, различающихся только своими PID и PPID.

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