Модель, реализуемая в данной работе, следующая:

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

Мы привели первый вариант реализации, чтобы показать, что с помощью сигналов можно реализовать достаточно сложные "диалоги" между процессами. Второй вариант представляется нам более изящным, он использует некоторые специфические свойства сигналов. Синхронизация действий процессов выполняется в этом варианте следующим образом:


 

© life-prog.ru