Материал: Sb97308

Внимание! Если размещение файла нарушает Ваши авторские права, то обязательно сообщите нам

3. ВЗАИМОДЕЙСТВИЕ ПОТОКОВ ЧЕРЕЗ НЕИМЕНОВАННЫЕ КАНАЛЫ

Цель работы – знакомство со средством взаимодействия потоков и процессов – неименованными каналами – и с системными вызовами, обеспечивающими создание и закрытие неименованных каналов, а также передачу и прием данных через неименованные каналы.

Общие сведения

Одним из средств взаимодействия процессов и потоков является неименованный канал. Канал не только обеспечивает передачу данных, но и поддерживает синхронизацию между потоками и процессами. Свойствами канала являются следующие положения: «при попытке записать данные в полный канал процесс блокируется» и «при попытке чтения данных из пустого канала процесс блокируется».

Канал создается с помощью вызова

int pipe(int filedes[2]),

где filedes[2] – массив из двух файловых дескрипторов, один из которых используется для записи данных (filedes[1]), а второй (filedes[0]) – для чтения данных.

Чтение данных из канала производится операцией ssize_t read(int fd, void *buf, size_t count),

где fd – файловый дескриптор для чтения; buf – адрес буфера для чтения данных; count – размер буфера.

Для записи данных в канал используется операция ssize_t write(int fd, const void *buf, size_t count),

где fd – файловый дескриптор для записи; buf – адрес буфера для записи данных; count – количество байт, предназначенных для записи.

Каждый из дескрипторов канала отдельно закрывается следующим вызовом int close(int fd).

Указания к выполнению работы

Написать программу, содержащую 2 потока, обменивающихся информацией через неименованный канал (pipe).

Шаблон программы:

объявить флаг завершения потока 1; объявить флаг завершения потока 2;

11

объявить идентификатор неименованного канала; функция потока 1()

{

объявить буфер; пока (флаг завершения потока 1 не установлен)

{

сформировать сообщение в буфере; записать сообщение из буфера в неименованный канал; задержать на время;

}

}

функция потока 2()

{

объявить буфер; пока (флаг завершения потока 2 не установлен)

{

очистить буфер; прочитать сообщение из неименованного канала и записать его в буфер;

вывести сообщение на экран;

}

}

основная программа()

{

объявить идентификатор потока 1; объявить идентификатор потока 2; создать неименованный канал; создать поток из функции потока 1; создать поток из функции потока 2; ждать нажатия клавиши; установить флаг завершения потока 1;

установить флаг завершения потока 2; ждать завершения потока 1; ждать завершения потока 2; закрыть неименованный канал;

}

12

Вопросы для самопроверки

1.Как обеспечивается синхронизация записи и чтения в неименованном канале?

2.Как использовать неименованный канал для взаимодействия процессов?

3.Как для неименованного канала организовать чтение и запись данных «без ожидания»?

4.Как реализовать функциональность неименованного канала с помощью семафоров?

5.Как с помощью неименованных каналов организовать двунаправленное взаимодействие?

6.Каким отношением должны быть связаны процессы для организации взаимодействия между ними через неименованные каналы?

13

4. СИНХРОНИЗАЦИЯ ПРОЦЕССОВ С ПОМОЩЬЮ ИМЕНОВАННЫХ СЕМАФОРОВ

Цель работы – знакомство со средством синхронизации процессов – именованными семафорами – и с системными вызовами, обеспечивающими создание, закрытие и удаление именованных семафоров, а также захват и освобождение именованных семафоров.

Общие сведения

Именованные семафоры позволяют организовать синхронизацию процессов в операционной системе. За счет того, что при создании и открытии именованного семафора ему передается «имя» – цепочка символов, 2 процесса могут получить указатель на один и тот же семафор. Другими словами, в отличие от мьютексов и неименованных семафоров именованные семафоры могут координировать доступ к критическому ресурсу не только на уровне нескольких потоков одной программы, но и на уровне нескольких выполняющихся программ – процессов.

В системе этот семафор реализуется в виде специального файла, время жизни которого не ограничено временем жизни процесса, его создавшего.

Существует несколько видов программных интерфейсов для создания именованных семафоров. В данном случае рассматривается программный интерфейс POSIX.

Именованный семафор создается следующим вызовом: sem_t *sem_open(const char *name,

int oflag, mode_t mode,

unsigned int value),

где name – имя семафора; oflag – флаг, управляющий операцией создания семафора, при создании семафора необходимо указать флаг O_CREAT; mode

– права доступа к семафору, могут быть установлены, например, в 0644; value – начальное состояние семафора.

Именованный семафор закрывается вызовом int sem_close(sem_t *sem).

При входе в критический участок необходимо вызвать функцию int sem_wait(sem_t *sem).

При выходе из критического участка необходимо вызвать функцию int sem_post(sem_t *sem).

14

Именованный семафор удаляется вызовом

int sem_unlink(const char *name).

Указания к выполнению работы

Поскольку именованные семафоры используются для координации взаимодействия процессов, то для выполнения работы необходимо написать две программы.

Необходимо выбрать общий ресурс, например файл, и записывать в него данные из двух программ.

Обе программы должны создать (или открыть, если создан) один и тот же именованный семафор, должны создать (или открыть, если создан) один и тот же файл, но записывать в файл разные символы.

Необходимо убедиться, что при отсутствии именованного семафора процессы выводят символы в файл в произвольном порядке, например:

1212121212121212121212121212121212121212121212121212121212121.

При использовании именованного семафора процессы выводят символы в файл в определенном порядке, например:

111111111122222222221111111111222222222211111111112222222222.

Шаблон одной из программ (вторая программа отличается от первой выводом в файл другого символа):

объявить флаг завершения потока; объявить идентификатор именованного семафора; объявить дескриптор файла; функция потока()

{

объявить переменную типа символ и присвоить ей значение ‘1’; пока (флаг завершения потока не установлен)

{

захватить именованный семафор; в цикле несколько раз выполнять

{

выводить символ в файл; задержать на время;

}

15