Модель, реализуемая в данной работе, следующая:
Мы предлагаем два варианта реализации такой модели. В обоих вариантах действуют процесс-Ганеша и процессы-Слоны, их создание происходит так же, как и в работе 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 |
|