Модель, реализуемая в данной работе, следующая:
Мы предлагаем два варианта реализации такой модели. В обоих вариантах действуют процесс-Ганеша и процессы-Слоны, их создание происходит так же, как и в работе N1.
В первом варианте синхронизация действий процессов выполняется следующим образом:
Кодовые модули, реализующие этот вариант программной модели ganesha2.c и elephant2.c показаны ниже. Фрагменты кодов, заимствованные из программы работы N9.
Готовый проект с откомпилированным кодом вы можете скачать здесь:)
|
Программный модуль, реализующий деятельность Ганеши
/**********************************************/
/* Пример для работы N10 */
/**********************************************/
/* СИГНАЛЫ */
/**********************************************/
/* Монитор Слонов - файл ganesha2.c */
/**********************************************/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <time.h>
#include <signal.h>
#include <sys/resource.h>
#include "../common/curtime.h"
#include "../common/ganesha.h"
#include "../common/elephant.h"
/*static*/ char chld_name[]="./elephant2";
/*static*/ int ne; /* параметр циклов */
/*static*/ meleph mel[NE]; /* управляющая информация о Слонах */
int cnt; /* число запущенных Слонов */
void usrHandler(int sig)
{
if (sig==SIGUSR1) mel[ne].status=1;
else mel[ne].status=2;
}
/********************************************************/
main()
{
int stat; /* состояние процесса при завершении */
/* строки для символьного представления параметров */
char t1[PARAMSTR_LENGTH], t2[PARAMSTR_LENGTH],
t3[PARAMSTR_LENGTH], t4[PARAMSTR_LENGTH];
/* идентификаторы процессов */
pid_t pw;
/* текст сообщения об ошибке */
char eee[ERRMES_LENGTH];
/* начало работы */
srand(time(NULL));
printf("%s Начало работы\n",curtime());
/* установка обработчика сигналов */
signal(SIGUSR1,usrHandler);
signal(SIGUSR2,usrHandler);
*t3=*t4=0;
/* цикл по массиву Слонов */
for (ne=0; ne<NE; ne++)
{
/* запись личных данных в управляющую информацию */
mel[ne].el=&ee[ne];
/* представление нестроковых данных в строковом виде */
sprintf(t1,"%d",mel[ne].el->age);
sprintf(t2,"%lf",mel[ne].el->weight);
/* порождение процесса */
pw=fork();
if (pw==0)
{
/* для дочернего процесса - запуск программы-Слона */
/* личные данные передаются через параметры */
if (execl(chld_name, mel[ne].el->name, t1, t2, t3, t4, NULL)<0)
{
/* если загрузка программы-Слона почему-либо не удалась,
печатается сообщение об ошибке, и процесс завершается */
perror(eee);
printf("%s\n",eee); exit(0);
}
/* если вызов execl выполнился успешно, то далее в
дочернем процессе выполняется программа elephant1 */
}
/* эта часть - только для процесса - Ганеши */
/* заполнение управляющей информации о процессе */
/* состояние процесса пока что - не запущен */
mel[ne].status=-1;
/* установка случайной добавки к приоритету */
mel[ne].prty=(int)(10.* rand()/RAND_MAX);
setpriority(PRIO_PROCESS,pw,mel[ne].prty);
/* запоминание ID процесса-Слона */
mel[ne].chpid=pw;
}
/* пауза, чтобы процессы успели загрузить Слонов */
sleep(1);
/* перебор запущенных процессов */
for (cnt=ne=0; ne<NE; ne++)
{
/* проверка - не закончился ли процесс */
pw=waitpid(mel[ne].chpid,&stat,WNOHANG);
if (pw==mel[ne].chpid)
/* если процесс закончился, значит, запуск Слона не удался */
printf("Слон %s не запущен\n",mel[ne].el->name);
else
{
/* состояние процесса - запущен */
mel[ne].status=0;
/* подсчет запущенных Слонов */
cnt++;
}
}
/* если счетчик запущенных 0 - завершение Ганеши */
if (!cnt) exit(0);
/* пауза монитора, Слоны в это время выполняются */
sleep(5);
printf("%s ВРЕМЯ ОЖИДАНИЯ ИСТЕКЛО\n",curtime());
/* перебор всех запущенных Слонов */
for (ne=0; ne<NE; ne++)
{
/* если состояние процесса "не запущен", он не проверяется */
if (mel[ne].status<0) continue;
/* проверка завершения Слона с заданным ID, без ожидания завершения */
pw=waitpid(mel[ne].chpid,&stat,WNOHANG);
if (mel[ne].chpid==pw)
{
/* если Слон завершился - сообщение о его успешном завершении */
printf("%s Слон %s нормально завершился\n",
curtime(),mel[ne].el->name);
cnt--;
}
else
{
/* если Слон не завершился, ему посылается сигнал USR1 */
if (kill(mel[ne].chpid,SIGUSR1)==0)
{
/* ожидание обработки ответного сигнала */
while (!mel[ne].status);
kill(mel[ne].chpid,SIGTERM);
printf("%s Слону %s послан SIGTERM\n",curtime(),mel[ne].el->name);
}
else cnt--;
}
}
while (cnt)
{
pw=wait(&stat);
for (ne=0; ne<NE; ne++)
if (pw==mel[ne].chpid) break;
if (stat)
printf("%s Слон %s погиб\n",curtime(),mel[ne].el->name);
else
printf("%s Слон %s нормально завершился \n",
curtime(),mel[ne].el->name);
cnt--;
}
}
|
|
Программный модуль, реализующий деятельность одного Слона
/**********************************************/
/* Пример для работы N10 */
/**********************************************/
/* Дочерний процесс,
моделирующий поведение Слона */
/**********************************************/
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/time.h>
#include <time.h>
#include <sys/resource.h>
#include <signal.h>
#include "../common/wait.h"
#include "../common/curtime.h"
#include "../common/elephant.h"
extern /*static*/ int waitFactor; // счетчик циклов ожидания и функции ожидания
/*static*/ elephant this;
/*static*/ int thisState;;
/* обработчик сигнала SIGUSR1 */
void usr1Handler(int sig_num)
{
if (!thisState)
kill(getppid(),SIGUSR1);
else kill(getppid(),SIGUSR2);
}
/* обработчик сигнала SIGTERM */
void termHandler(int sig_num)
{
if ( !thisState || (waitFactor>1000) )
exit(8);
else
printf("%s Слон %s получил отсрочку (%d)\n",
curtime(),this.name,waitFactor);
}
main(int an, char *av[]) {
int need;
int opt;
/* установка обработчика сигнала SIGUSR1 */
signal(SIGUSR1,usr1Handler);
signal(SIGTERM,termHandler);
/* прием параметров */
strcpy(this.name,av[0]);
sscanf(av[1],"%d",&(this.age));
sscanf(av[2],"%lf",&(this.weight));
/* инициализация генератора случайных чисел */
srand(time(NULL));
/* состояние - 0 */
thisState=0;
/* сообщение о начале */
printf("%s - Слон %s поиск начал, приоритет=%d\n",
curtime(),this.name,getpriority(PRIO_PROCESS,getpid()));
/* время поиска воды - случайная величина, отчасти зависящая от возраста */
a1wait(10*(60-this.age));
/* поиск окончен, состояние - 1 */
thisState=1;
/* сообщение об окончании поиска */
printf("%s - Слон %s нашел воду\n",curtime(),this.name);
/* время насыщения зависит от веса Слона */
a0wait((int)(this.weight*30));
/* сообщение об окончании водопоя */
printf("%s - Слон %s напился\n",curtime(),this.name);
exit(0);
}
|
Ниже приводится пример выполнения этой модели
08:18:51.186 - Начало работы 08:18:51.196 - Слон Tandy поиск начал, приоритет=3 08:18:51.207 - Слон Aun поиск начал, приоритет=0 08:18:51.316 - Слон BakZap поиск начал, приоритет=0 08:18:51.326 - Слон Assam поиск начал, приоритет=6 08:18:51.355 - Слон Maya поиск начал, приоритет=6 08:18:51.438 - Слон Hathy поиск начал, приоритет=0 08:18:51.506 - Слон Kitty поиск начал, приоритет=0 08:18:51.516 - Слон Hao поиск начал, приоритет=3 08:18:55.481 - Слон BakZap нашел воду 08:18:59.503 - Слон Hathy нашел воду 08:19:04.574 - Слон Assam нашел воду 08:19:06.766 - Слон Maya нашел воду 08:19:09.521 - Слон BakZap напился 08:19:16.268 - Слон Hao нашел воду 08:19:16.519 - Слон Hathy напился 08:19:18.800 ВРЕМЯ ОЖИДАНИЯ ИСТЕКЛО 08:19:19.290 Слону Tandy послан SIGTERM 08:19:19.591 Слону Aun послан SIGTERM 08:19:19.830 Слону Assam послан SIGTERM 08:19:20.020 Слону Maya послан SIGTERM 08:19:20.021 Слон BakZap нормально завершился 08:19:20.240 Слону Hao послан SIGTERM 08:19:20.240 Слон Hathy нормально завершился 08:19:20.390 Слон Hao получил отсрочку (846) 08:19:20.480 Слону Kitty послан SIGTERM 08:19:20.480 Слон Maya погиб 08:19:20.480 Слон Assam погиб 08:19:20.480 Слон Aun погиб 08:19:20.480 Слон Tandy погиб 08:19:20.530 Слон Kitty погиб 08:19:21.078 - Слон Hao напился 08:19:21.079 Слон Hao нормально завершился |
Мы привели первый вариант реализации, чтобы показать, что с помощью сигналов можно реализовать достаточно сложные "диалоги" между процессами. Второй вариант представляется нам более изящным, он использует некоторые специфические свойства сигналов. Синхронизация действий процессов выполняется в этом варианте следующим образом:
for (d=30; d=sleep(d); );
Этот оператор выполняется следующим образом. Поскольку начальное
значение переменной d - 30, процесс "погружается в сон"
на 30 сек. Однако из этого "сна" процесс может быть выведен (и неоднократно) сигналом
SIGCHLD. Если такой сигнал приходит, то после его обработки
вызов sleep завершается
"досрочно" и возвращает число недобранных секунд сна. Если это число
нулевое, происходит выход из цикла ожидания, если же ненулевое -
процесс опять погружается в сон на оставшееся время.
© life-prog.ru |