Министерство Образования Российской Федерации
Хабаровский Государственный Технический Университет
Лабораторная работа №6
По дисциплине «Операционные системы»
Тема: «Межпроцессные коммуникации - каналы и сигналы»Цель работы: Изучение средств межпроцессных коммуникаций, предоставляемых ОС Linux, на примере неименованных каналов. Знакомство с сигналами ОС и с функциями для работы с ними.
Задание:
Реализуйте следующий сценарий. Родительский процесс создает одинаковые дочерние процессы, которые работают параллельно и выполняют какие-либо действия за случайный интервал времени. Родительский процесс и дочерние процессы общаются (предают друг другу сообщения) через каналы. При наступлении какого-либо события в дочернем процессе, этот процесс оповещает сигналом родительский процесс, который после обработки данного сигнала завершает этот дочерний процесс. После завершения всех дочерних процессов родительский процесс завершает свою работу. На время работы программы необходимо запретить прерывание программы по Ctrl-C. Количество дочерних процессов должно задаваться с командной строки. Все процессы должны выводить на экран сообщения о своей работе и время сообщения.
Пример работы дочернего процесса: генерация случайных чисел (или символьных последовательностей) в зависимости от принятых данных от родительского процесса.
Событие: сумма чисел (или длина последовательности) становится больше какой-либо константы.
Описание функционирования программы:
После запуска программы с параметром (число дочерних процессов, запускаемых главным процессом) главный (родительский) процесс создаёт каналы и запускает потоки (описание функционирования потока приводится далее), предназначенные для прослушивания канала каждого дочернего процесса (кол-во потоков = кол-ву дочерних процессов), и сами дочерние процессы (описание далее), далее родительский процесс активизирует запущенные потки с помощью глобальной переменной, захватывает мьютекс и запускает цикл, в котором “засыпает” до получения сигнала от потока и после получения его выводит строку с данными, полученными потоком от дочернего процесса, и сам посылает подтверждение получения дочернему процессу, после чего цикл повторяется до тех пор, пока все дочерние процессы не завершатся.
Поток работает следующим образом: ждёт, пока родительский процесс активизирует его, начинает выполнять цикл, в котором принимает число от дочернего процесса, если число равно нулю, то поток завершает свою работу, иначе захватывает мьютекс, передаёт данные родительскому процессу через глобальные переменные и посылает ему сигнал “пробуждения”, освобождает мьютекс.
Функционирование дочернего процесса: выполняет цикл, в котором генерирует случайное число и отправляет его по своему каналу потоку, ждёт подтверждение получения от родительского процесса, добавляет число в сумму. Цикл выполняется, пока сумма не превысит заданное значение. После выполнения цикла дочерний процесс отправляет в канал завершения свой PID и оповещает родительский процесс сигналом. Родительский процесс обрабатывает этот сигнал следующим образом: получает из канала завершения PID и завершает процесс с таким PID, изменяет глобальную переменную, содержащую кол-во “живых” дочерних процессов.
Текст
и результат работы программы:
Листинг программы:
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <time.h>
#include <math.h>
#define SUM 10
#define KOLVO 100
int gl_PID, gl_n, gl_GenNum;
int cond_sig=0;
int PID[KOLVO], n[KOLVO], GenNum[KOLVO];
int fd0[2];
int fd1[KOLVO][2], fd2[KOLVO][2];
int cnt_alive_chd, chds_start, start_thrds;
pthread_mutex_t my_mux, end_mux;
pthread_cond_t gl_cond;
time_t curtime;
/*begin of SigHndlr*/
void SigHndlr()
{
pthread_mutex_lock(&end_mux);
int res,sig_data;
close(fd0[1]);
res=read(fd0[0],(void*)&sig_data,sizeof(int));
kill(sig_data,SIGKILL);
time(&curtime);
printf("Child with PID=%d is killed (res=%d)!!! Current time: %s",sig_data,res,ctime(&curtime));
cnt_alive_chd--;
if(cnt_alive_chd==0)
{
cond_sig=1;
pthread_cond_signal(&gl_cond);
}
pthread_mutex_unlock(&end_mux);
}
/*end of SigNndlr*/
/*begin of read_thread*/
void *read_thrd(void *p)
{
int thr_end=0;
int num_of_chl, res;
num_of_chl=(int)p;
while(start_thrds!=1){};
printf("Thread #%d begin PID=%d\n",num_of_chl,getpid());
while(thr_end!=1)
{
close(fd2[num_of_chl][1]);
res=read(fd2[num_of_chl][0],(void*)&GenNum[num_of_chl],sizeof(int));
Уважаемый посетитель!
Чтобы распечатать файл, скачайте его (в формате Word).
Ссылка на скачивание - внизу страницы.