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

2.2.9. Задание 5

Цель работы — осуществить синхронизация с применением блокировки чтения-записи.

Порядок выполнения

Дописать алгоритм работы второго потока.

2.2.10. Задание 6

Цель работы — осуществить синхронизация с применением блокировки чтения-записи.

Порядок выполнения

Дописать алгоритм работы четвертого потока.

2.2.11. Контрольные вопросы

1. Дайте определение потока.

2. Как осуществляется запуск потока?

3. Какие атрибуты использует поток «flags»? Их назначение.

4. Какие атрибуты использует поток «scheduling»? Их назначение.

5. Как осуществляется синхронизация потоков с помощью метода «присоединения»?

6. Как осуществляется синхронизация потоков с помощью барьера?

7. Дайте определение мьютекса.

8. Как осуществляется синхронизация потоков с использованием мьютексов?

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

7.Взаимодействие между процессами с помощью сообщений. Модель «клиент/сервер». Таймеры

Цель работы — освоение взаимодействия между процессами с помощью сообщений. Освоение работы с таймерами.

2.3.1. Порядок выполнения работы

1. Ознакомиться с методами взаимодействия между процессами с помощью сообщений. Ознакомиться с методами работы с таймерами.

2. Изучить метод и алгоритм решения поставленной задачи;

3. Разработать алгоритм взаимодействия между процессами.

4. Реализовать данный алгоритм в виде программы. Отладить программу.

5. Составить отчёт, который должен содержать:

‑ постановку задачи взаимодействия между процессами;

‑ описание данных задачи;

‑ схему алгоритма и программу для ЭВМ;

‑ содержательную интерпретацию полученных результатов:

‑ выводы о проделанной работе.

4. Ответить устно на контрольные вопросы.

2.3.2. Методические указания

В QNX обмен сообщениями является основной механизмом при взаимодействии процессов друг с другом. Микроядро ОС обеспечивает передачу сообщений. СРВ в QNX реализуются по модели «клиент/сервер». Программа, выполняющие функции сервера (уровень 1), является более «главной» по отношению к программе клиента (уровень 2), которая в свою очередь может быть сервером для клиента более низкого уровня (уровень 3) и она уже в свою очередь будет «главнее» программы третьего уровня иерархии и т.д. Клиент отправляет серверу сообщения. Сервер их получает, обрабатывает и отвечает клиенту. При таком способе обмена сообщениями возникает необходимость следовать строгой иерархии обмена. Поток своего уровня иерархии должен посылать сообщения (отвечать) потоку более низкого уровня, а не своего или высшего. Т.е. ответ идет от потока являющегося более главным (сервер) по отношению к потоку, который его запрашивает (клиент).

Приведем пример взаимодействия между двумя процессами на основе обмена сообщениями.

#include <stdio.h>

#include <sys/neutrino.h>

#include <string.h>

#include <errno.h>

#include <sys/types.h>

#include <process.h>

#include <sys/stat.h>

#include <fcntl.h>

//for write

#include <unistd.h>

void server(void *not_user)

{

int rcvid; //идентификатор отправителя

int chid; //идентификатор канала

char message[512];//буфер для отправки сообщения

int pid; //идентификатор процесса

pid = getpid(); // получение дескриптора процесса

//создание канала

Сервер должен создать канал, к которому будет присоединяться клиент при вызове функции ConnectAttach(). Канал создается с помощью функции ChannetCreate(), а уничтожается с помощью функции ChannelDestroy(). Для этого необходимо добавить заголовочный файл #include <sys/neutrino.h>.

chid = ChannelCreate(0);

После этого сервер создал канал с атрибутами канала, используемыми по умолчанию. После этого клиенты могут к нему подсоединиться и начать передачу сообщений. Для этого клиент использует функцию ConnectAttach(), которой необходимо указать дескриптор узла (Node descriptor – ND), идентификатор процесса (Process ID – PID) и идентификатор канала (Channel ID – CHID). Предположим, что два процесса работают на одном ПК. Для того, чтобы клиент смог определить PID и CHID, сервер записывает эти параметры в файл "/etc/mes2.pid" в формате PID/CHID.

//запись в файл идентификатора процесса и канала pid/chid

char *pname_file = "/etc/mes2.pid";

char buff[20];

int sizeread; //число байт, считанных из файла

int fd;

fd = open(pname_file, O_CREAT | O_RDWR | O_CREAT);//открытие файла

if ( fd == -1){

печать сообщение об ошибке открытия файла

}

sprintf(buff, "%i/%d\n", pid, chid);//формирование массива для записи в файл

int size_written = write( fd, buff, sizeof( buff ) );//запись в файл

if(size_written != sizeof( buff) ){

печать сообщения об ошибке записи в файл

}

close(fd);

Далее идет непосредственно обработка сообщений от сервера. Она для сервера проходит в два этапа:

  • этап приема сообщения (recive);

  • этап ответа на сообщение (reply).

Рис.2.3.1. Использование функции MsgReceive() для ожидания сообщений от клиентов

Для ожидания сообщений от клиентов используется функция MsgReceive(), рис.2.3.1.

int MsgReceive(int chid,//идентификатор канала

void *rmsg,//указатель на принимаемое сообщение

int rbytes,//размер сообщения

struct msg_info *info

);

Для ответа клиенту сервер использует функцию MsgReply().

int MsgReply(int rcvid, //идентификатор отправителя

int status,//значение анализируется клиентом

const void *msg,//указатель на отправляемое сообщение

int nbytes //размер сообщения

);

while(1){

//получение сообщения от клиента

rcvid = MsgReceive(chid, message, sizeof(message), NULL);

printf("server: message from client : %s \n", message);

printf("id client - rcvid = %X\n", rcvid);

//ответ сервера

strcpy(message,"das ist beantwort des servers");

MsgReply(rcvid, EOK, message, sizeof(message));

}

}

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