13 Взаимодействие процессов.pptx
- Количество слайдов: 29
ВЗАИМОДЕЙСТВИЕ ПРОЦЕССОВ
СИТУАЦИИ, ТРЕБУЮЩИЕ ВЗАИМОДЕЙСТВИЯ ПРОЦЕССОВ Процесс 1 Процесс 2 Несколько процессов используют один и тот же ресурс. Например, принтер или разделяемую память. Требуется: определить порядок использования этого ресурса. ресурс Процесс 1 Процесс 2 Процессы работают в разных адресных пространствах и не могут взаимодействовать друг с другом напрямую. Решение выполняется процессами. одной задачи несколькими Требуется: реализовать механизм передачи данных между процессами.
ВЗАИМОДЕЙСТВИЕ ПРОЦЕССОВ. ПЕРЕДАЧА ДАННЫХ • каналы (программные, FIFO); • очереди сообщений; • разделяемая память + семафоры; • механизм сокетов (UNIX, IP); • Active. X (OLE); • буфер обмена.
ВЗАИМОДЕЙСТВИЕ ПРОЦЕССОВ, ОПРЕДЕЛЕНИЕ СОСТЯЗАНИЯ Ситуация, в которой два (или более) процессов используют один ресурс, причем характер использования зависит от последовательности предоставления ресурса, называется состоянием состязания. Требуется реализовать взаимное исключение (взаимоисключение) – механизм, определяющий последовательность предоставления ресурса.
ВЗАИМОИСКЛЮЧЕНИЕ, КРИТИЧЕСКАЯ ОБЛАСТЬ. Критическая секция – время, в течение которого используется разделяемые ресурс. Условия справедливого использования ресурса: • количество и скорость работы процессов не регламентируется; • в один момент времени в критической секции может находиться только один процесс; • процесс, находящийся вне критической области не может блокировать другие процессы. • необходимо исключить ситуацию вечного нахождения процесса в критической области.
Для того, чтобы обеспечить нахождения только одного процесса в критической области каждый процесс обязан: При входе: • проверить есть ли кто в критической области; • объявить о том, что он находится в критической области (запретив при этом доступ в критическую область другим процессам). При выходе сообщить, что в критической области больше никого нет (разрешив тем самым доступ к критической области другим процессам). Если проверке доступности критической секции процесс обнаружил, что она недоступна, то он может: • продолжать проверять доступность критической секции; • заблокироваться и ждать сообщения от операционной системы, что критическая область освободилась. Первый способ называется активным ожиданием (спин-блокировкой) и сопровождается нерациональным использованием процессора.
УСЛОВИЕ РАЗНЫХ СКОРОСТЕЙ ПРОЦЕССОВ Имеется критический участок. Требуется организовать его взаимоисключающее использование.
ПРИНЦИП РАБОТЫ ВЗАИМОИСКЛЮЧЕНИЯ Процесс, желающий попасть в критическую область проверяет занята ли она. Если нет, то он входит в неё и сигнализирует об этом другим процессам, которым приходится ждать. После выхода из критической области процесс сигнализирует об этом. Ситуация повторяется с другим процессом.
СОСТОЯНИЕ СОСТЯЗАНИЯ. Имеется разделяемый ресурс – очередь печати файлов. 0 1 файл 1 Демон печати Специальная программа выбирает файлы из очереди, печатает их на принтере и удаляет из очереди 2 3 файл 2 4 5 файл 3 проц. 1 6 проц. 2 4 6 5 Процесс 1 Процесс 2 _ 4 5 _ Для указания очередной свободной ячейки в очереди используется разделяемая переменная. Процессы сначала определяют значение этой переменной, записывают его в свои локальные переменные, затем записывают имя файла в соответствующую ячейку.
МОДЕЛЬ «ПРОИЗВОДИТЕЛЬ-ПОТРЕБИТЕЛЬ»
МОДЕЛЬ «СПЯЩИЙ БРОДОБРЕЙ»
МОДЕЛЬ ОБЕДАЮЩИХ ФИЛОСОФОВ Сформулирована в 1965 году Дейкстрой. Пять философов сидят за круглым столом, и у каждого есть тарелка со спагетти. Спагетти настолько скользкие, что надо обязательно две вилки, чтобы с ними управиться. На столе между тарелками лежит по одной вилке. Жизнь философа состоит из чередующихся периодов размышлений и поглощения пищи. Когда философ голоден он пытается получить две вилки: левую и правую (в любом порядке). Если ему это удалось, то приём пищи занимает некоторое время, после чего он кладёт вилки назад и продолжает размышлять. Требуется: разработать алгоритм поведения каждого философа таким образом, чтобы исключить состязание за вилки.
Алгоритм, не работающий в случае разных скоростей процессов Begin Boolean ПЕРЕКЛЮЧАТЕЛЬ 1, ПЕРЕКЛЮЧАТЕЛЬ 2; ПЕРЕКЛЮЧАТЕЛЬ 1 : = false; ПЕРЕКЛЮЧАТЕЛЬ 2 : = false; parbegin ПРОЦЕСС 1: do while (true); ЦИКЛ 1: do while (ПЕРЕКЛЮЧАТЕЛЬ 2); end; ПЕРЕКЛЮЧАТЕЛЬ 1 : = true /* критическая область */ ПЕРЕКЛЮЧАТЕЛЬ 1 : = false; /* Выход из критической области */ end; ПРОЦЕСС 2: do while (true); ЦИКЛ 2: do while (ПЕРЕКЛЮЧАТЕЛЬ 1); end; ПЕРЕКЛЮЧАТЕЛЬ 2 : = true /* критическая область */ ПЕРЕКЛЮЧАТЕЛЬ 2 : = false; /* Выход из критической области */ end; parend end.
АЛГОРИТМ ДЕККЕРА C 1 = 0, C 2 = 0, ОЧЕРЕДЬ = 1; ПРОЦЕСС 1{ C 1 = 1; do while (c 2 = 1) { if (ОЧЕРЕДЬ = 2) { C 1 : = 0; do while (ОЧЕРЕДЬ = 2) ; C 1 = 1; } } /* Критический участок */ C 1 = 0; ОЧЕРЕДЬ = 2; /* Выход из критического участка */ } ПРОЦЕСС 2 { begin c 2 = 1; do while (c 1 == 1) { if (ОЧЕРЕДЬ = 1) { C 2 = 0; while (ОЧЕРЕДЬ = 1) ; C 2 = 1 } } /* Критический участок */ с2 = 0; ОЧЕРЕДЬ = 1; /* Выход из критического участка */ }
Алгоритм Петерсона # define FALSE 0 # define TRUE 1 # define N 2 int turn; interested [N] = {0}; void enter_region (int process) { int other; other = 1 – process interested [process] = TRUE; turn = process; while (turn == process && interested [other] == TRUE) ; } void leave_region (int process) { interested [process] = FALSE; }
СЕМАФОР Одним из первых механизмов, предложенных для синхронизации поведения процессов, стали семафоры, концепцию которых описал Дейкстра (Dijkstra) в 1965 году. Семафор – это целая переменная, принимающая неотрицательные значения, доступная всем процессам через операции: – – P (от датского слова proberen — проверять). Широко распространен вариант – down. V (от verhogen — увеличивать). Широко распространён вариант up(). Операция P определяется как атомарная последовательность следующий действий: – – – проверить значение семафора; если значение семафора равно нулю, заблокировать процесс до тех пор, пока оно не станет отличным от нуля; если значение отлично от нуля, уменьшить его на 1. Операция P определяется как увеличение значения семафора на единицу.
«ПРОИЗВОДИТЕЛЬ-ПОТРЕБИТЕЛЬ» с использованием семафоров # define N 100 typedef int semaphore; semaphore mutex = 1; semaphore empty = N; semaphore full = 0; void produces (void) { int item; while (TRUE){ item = produce_item(); down (&empty); down (&mutex); insert_item (item); up (&mutex); up (&full); } } void consumer (void) { int item; while (TRUE){ down (&full); down (&mutex); item = remove_item (); up (&mutex); up (&empty); consume_item (item); } }
«ОБЕДАЮЩИЕ ФИЛОСОФЫ» с использованием семафоров. # define N 5 # define LEFT (i – 1) % N # define RIGHT (i + 1) % N /* номер левой вилки */ /* номер правой вилки */ # define THINKING 0 # define HUNGRY 1 # define EATING 2 /* состояние размышлений */ /* состояние голода */ /* состояние поглощения пищи */ typedef int semaphore; int state [N]; semaphore mutex = 1; semaphore s [N]; /* новый тип – семафор */ /* состояние философов */ /* блокирующая переменная */ /* семафоры для философов */
«ОБЕДАЮЩИЕ ФИЛОСОФЫ» с использованием семафоров. void philisophier (int i) { while (TRUE){ think (); take_forks (i); eat (); put_forks (i); } } void take_forks (int i) { down (&mutex); state [i] = HUNGRY; test (i); up (&mutex); down (&s[i]); }
«ОБЕДАЮЩИЕ ФИЛОСОФЫ» с использованием семафоров. void put_forks (int i) { down (&mutex); state [i] = THINKING; test (LEFT); test (RIGHT); up (&mutex); } void test (int i) { if (state[i] == HUNGRY && state [LEFT] != EATING && state [RIGHT] != EATING){ state [i] = EATING; up (&s[i]); } }
«БРОДОБРЕЙ» с использованием семафоров # define CHAIRS 5 semaphore customers = 0, barbers = 0, mutex = 1; int waiting = 0; void barber (void) { while (TRUE){ down (&customers); down (&mutex); waiting = waiting – 1; up (&barbers); up (&mutex); cut_hair (); } } void customer (void) { down (&mutex); if (waiting < CHAIRS){ waiting = waiting + 1; up (&customers); up &(mutex); down (&barbers); get_haircut (); } else { up (&mutex); } }
СОЗДАНИЕ ВЕКТОРА СЕМАФОРОВ. #include <sys/types. h> #include <sys/ipc. h> #include <sys/sem. h> int semget (key_t key, int nsems, int semflag) • • • key – ключ sems – количество семафоров semflag – флаги, определяющие права доступа и те операции, которые должны выполняться (открытие семафора, проверка, и т. д. ). Возвращает целочисленный идентификатор созданного разделяемого ресурса, либо -1, если ресурс не удалось создать.
СОЗДАНИЕ КЛЮЧА ДОСТУПА. #include <sys/types. h> #include <sys/ipc. h> int ftok (const char * pathname, char proj_id) – – pathname – имя файла proj_id – символ, идентифицирующий проект Возвращает целочисленный идентификатор созданного разделяемого ресурса, либо -1, если ресурс не удалось создать.
ОПЕРАЦИИ НАД ВЕКТОРАМИ СЕМАФОРОВ #include <sys/types. h> #include <sys/ipc. h> #include <sys/sem. h> int semop (int semid, struct sembuf *semop, size_t nops) • • • semid – идентификатор ресурса semop – указатель на структуру, определяющую операции, которые нужно призвести над семафором nops– количество указателей на эту структуру, которые передаются функцией semop() (операций может быть несколько и операционная система гарантирует их атомарное выполнение).
Операции над семафором Операции определяются структурой: struct sembuf { short sem_num; /*номер семафора в векторе*/ short sem_op; /*производимая операция*/ short sem_flg; /*флаги операции*/ } Значение семафора с номером num равно val. Если semop 0 то { ждать до тех пор, пока (val + semop) > 0; val = val + semop } Если semop = 0 то жать до тех пор, пока val 0
УПРАВЛЕНИЕ МАССИВОМ СЕМАФОРОВ #include <sys/types. h> #include <sys/ipc. h> #include <sys/sem. h> int semctl (int semid, int num, int cmd, union semun arg) • semid – дескриптор массива семафоров • num – индекс семафора в массиве • cmd – операция – IPC_SET заменить управляющие наборы семафоров на те, указаны в arg. buf – IPC_RMID удалить массив семафоров и др. которые • arg – управляющие параметры Возвращает значение, соответствующее выполнявшейся операции (по умолчанию 0), в случае неудачи – -1
Управление массивом семафоров #include <sys/types. h> #include <sys/ipc. h> #include <sys/sem. h> int semctl (int semid, int num, int cmd, union semun arg) union semun { int val; /* значение одного семафора *. struct semid_ds *buf; /* параметры массива семафоров в целом (количество, права доступа, статистика доступа)*/ ushort *array; /* массив значений семафоров */ }
#include <stdio. h> #include <sys/types. h> #include <sys/ipc. h> #include <sys/sem. h> #include <string. h> #define NMAX semctl (semid, 0, SETVAL, (int) 0); sops. sem_num = sops. sem_flg = 0; do { printf(“Введите строку: ”); if (fgets(str, NMAX, stdin) == NULL) strcpy(str, “Q”); sops. sem_op = 3; semop(semid, &sops, 1); /* обработка строки */ sops. sem_op = 0; semop(semid, &sops, 1); } while (str[0] != ‘Q’); shmctl(shmid, IPC_RMID, NULL); return 0; 256 int main(int argc, char **argv) { key_t key; int semid; struct sembuf sops; char str[NMAX]; key = ftok(“. /hhh. exe”, ’S’); semid = semget(key, 1, 0666 | IPC_CREAT); }
13 Взаимодействие процессов.pptx