LINUX.ORG.RU

Некорректная работа учебной программы обработки сигналов

 ,


0

1

Добрый вечер , увжаемые форумчане! Хочу попросить знающих людей посмотреть мой код и объяснить несколько вещей по нему .Прошу сильно не пинать - программа это задние по предмету в инсте, под позикс впервый раз проги пишу., писал все по не самому лучшему рукрвдоству, данному преподавтелем. Компилирую в gcc под Fedora 17.

Собственно, интересуют 2 вещи 1)Почему в дочернем процессе Childprocess после подключения обработчика handler_FPE и первого деления m/e (e=0) происходит зацикливание обработчика.? 2) вопросы по обработчику handler_CHLD 2.1 Почему если убрать комментарии с if (нужны по условию задачи), то обработчик будет зависать при исполнении? 2.2 По условию задачи обраюботчик должен заносить в струтуру все изменеия состояния дочернего процесса (при приостанвке , передаче работы основному процессу и при выходе). Сейчас туда заносится информация только один раз при завершении дочернего процесса. Как можно реализовать требуемй функционал ?

Вот код (на комментарии не обращайте внимания? в цедом они правильные, но я их пока для себя писал, часто копипастил и не все поправлял) :

#include <sched.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdio.h>
#include <time.h>
#include <signal.h>
#include <errno.h>

//Глобальные переменные
int a,b,c,d,g,i,n;
int k=0;
  //Переменная для идентификатора процесса
int pid_child;

siginfo_t siginfo;

struct StructChild
{
  int pid;
  int status;
  int code;
};
 
struct StructChild StrChld[4];

//Обработчик сигнала 1
void handler1(int signo)
{  
   printf("\nhandler1\n");
  //Присваиваем значение 1 переменной g при поступлении сигнла SIGUSR1
  if (signo==SIGUSR1)
   {
    g = 1;
    printf("\nVariable g - %d\n", g); 
   }  
 //Присваиваем значение 2 переменной g при поступлении сигнла SIGUSR2
   if (signo==SIGUSR2)
    {
     g = 2;
     printf("\nVariable g - %d\n", g );
    }
}

//Обработчик сигнала SIGUSR1
void handler_SIGUSR1()
{
  printf("\nhandler_SIGUSR1\n");
  //Увеличиваем значение переменной a и выводим для проверки
  a += 1;
  printf("\nVariable a - %d\n", a);
 //Увеличиваем значение переменной b и выводом для проверки
  b += 1;
  printf("\nVariable b - %d\n", b );
}

//Обработчик сигнала SIGUSR2
void handler_SIGUSR2()
{ 
  printf("\nhandler_SIGUSR2\n");
  //Увеличиваем значение переменной a и выводим для проверки
  a += 1;
  printf("\nVariable a - %d\n", a);
 //Увеличиваем значение переменной b и выводом для проверки
  c += 1;
  printf("\nVariable c - %d\n", c );
}

//Обработчик сигнала SIGFPE
void handler_SIGFPE()
{
  //Увеличиваем значение переменной a и выводим для проверки
  a += 1;
  printf("\nVariable a - %d\n", a);
 //Увеличиваем значение переменной b и выводом для проверки
  d += 1;
  printf("\nVariable d - %d\n", d );
}

//Обработчик сигнала SIGCHLD
void handler_CHLD()
{
  printf("\nhandler_CHLD\n");
  StrChld[k].pid=siginfo.si_pid;
  StrChld[k].status=siginfo.si_status;
  StrChld[k].code=siginfo.si_code; 
  k+=1;
  if ((siginfo.si_code==CLD_EXITED) || (siginfo.si_code==CLD_DUMPED) ||(siginfo.si_code==CLD_KILLED)) 
 {
  if (siginfo.si_pid==pid_child)
 {
    //значение переменной i и выводим для проверки
    i = 1;
    printf("\nVariable i - %d\n", i);
  }
 }
  
}


//Дочерний процесс
void childProcess()
{
  //Запоминаем текущий приоритет
  struct sched_param sch_pCHLD;
  int CurrentChildPrioritet=sched_getparam(getpid(),&sch_pCHLD);
  //Объявляем структуру в которой хранится информация об обработчике сигналов
  struct sigaction sa1;
  
   //Указываем обработчик сигнала 
  sa1.sa_handler = handler1;

  //Присваиваем обработчик сигналам SIGUSR1 и SIGUSR2
  sigaction(SIGUSR1, &sa1, 0); 
  sigaction(SIGUSR2, &sa1, 0); 
 //Объявляем набор сигналов set1
  sigset_t set1;
 //Инициируем этот набор,включая внего все сигналы в системе (все сигналы блокируются)
  sigfillset(&set1);
//Исключаем сигналы SIGUSR1 , SIGUSR2 и SIGFPE из этого набора
  sigdelset(&set1, SIGUSR1);
  sigdelset(&set1, SIGUSR2);
  sigdelset(&set1, SIGFPE);
//Проверяем наличие сигналов SIGUSR1 , SIGUSR2 и SIGFPE в наборе
  if (sigismember(&set1, SIGUSR1)==1)
   {
     printf("\nError! Signal SIGUSR1 is in set1!\n");
     
   }
  if (sigismember(&set1, SIGUSR2)==1)
   {
     printf("\nError! Signal SIGUSR2 is in set1!\n");
     
   }
  if (sigismember(&set1, SIGFPE)==1)
   {
     printf("\nError! Signal SIGFPE is in set1!\n");
     
   }
 //Устанавливаем текущим набор сигналов set1
  sigprocmask(SIG_SETMASK,&set1,0);
 //Проверяем правильность установленной маски  
  if(sigprocmask(SIG_SETMASK,0,&set1)==1)
    {
     printf("\nError! Set1 is not in current mask!\n");
     
    }
 //Обнуляем g 
    g=0;
 //Приостанавливаем работу tsk1
   sigsuspend(&set1);
 //Проверяем значение переменной g = 1 после выхода из приостанова  
   if (g!=1)
    {
      printf("\nError! Variable g!=1\n");
      
    }
 //Вновь приостанавливаем работу tsk1
    sigsuspend(&set1);
 //Проверяем значение переменной g = 2 после выхода из приостанова  
    if (g!=2)
     {
       printf("\nError! Variable g!=1\n");
       
     }
  //Объявляем набор сигналов set2
  sigset_t set2;
 //Инициируем этот набор,включая внего все сигналы в системе (все сигналы блокируются)
  sigfillset(&set2);

//Объявляем структуру в которой хранится информация об обработчике сигналов
  struct sigaction saUSR1;
  
   //Указываем обработчик сигнала 
  saUSR1.sa_handler = handler_SIGUSR1;
  saUSR1.sa_flags = 0;
  saUSR1.sa_mask = set2;
  //Присваиваем обработчик сигналам SIGUSR1 и SIGUSR2
  sigaction(SIGUSR1, &saUSR1, 0); 


  //Объявляем набор сигналов set3
  sigset_t set3;
  //Инициируем этот набор,включая внего все сигналы в системе (все сигналы блокируются)
  sigemptyset(&set3);
  //Объявляем структуру в которой хранится информация об обработчике сигналов
  struct sigaction saUSR2;
  
   //Указываем обработчик сигнала 
  saUSR2.sa_handler = handler_SIGUSR2;
  saUSR2.sa_flags = 0;
  saUSR2.sa_mask = set3;
  //Присваиваем обработчик сигналам SIGUSR1 и SIGUSR2
  sigaction(SIGUSR2, &saUSR2, 0); 
 
  //Объявляем структуру в которой хранится информация об обработчике сигналов
  struct sigaction saFPE;
  
   //Указываем обработчик сигнала 
  saFPE.sa_handler = handler_SIGFPE;
  saFPE.sa_flags = 0;
  saFPE.sa_mask = set2;
  //Присваиваем обработчик сигналам SIGUSR1 и SIGUSR2
  sigaction(SIGFPE,&saFPE, 0);
  //Обнуляем переменные 
   a=0;
   b=0;
   c=0;
   d=0;
  //Запускаем цикл тестирования перемнной а на нулевое значение
  for(;;)
  {
    if (a!=0)
    {break;}
   }
  //Уменьшаем значение переменной а на 1
   a-=1;
 //Проверяем значение переменной b = 1 
   if (b!=1)
    {
      printf("\nError! Variable b!=1\n");
          }

  struct timespec req;
  struct timespec rem;
 
  // 2 секунды , 300 наносекунд
  req.tv_sec = 2;
  req.tv_nsec = 300;

  //nanosleep(&req,&rem);

 //Запускаем цикл тестирования перемнной а на нулевое значение
   for(;;)
   {
    if (a!=0)
    {break;}
   }
//Уменьшаем значение переменной а на 1
   a-=1;
//Проверяем значение переменной c = 1   
   if (c!=1)
    {
      printf("\nError! Variable с!=1\n");
      
    }
 //Модифицируем набор сигналов 1, добавляем в него сигнал SIGUSR1 (он будет заблокирован)
   sigaddset(&set1, SIGUSR1);
 
//Проверяем наличие сигнала SIGUSR1  в наборе сигналов 1
  if (sigismember(&set1, SIGUSR1)!=1)
   {
     printf("\nError! Signal SIGUSR1 is not in set1!\n");
     
   }

//Объявляем наборы сигналов set4,oldset
  sigset_t set4;
  sigset_t oldset;
  
//Устанавливаем текущим набор сигналов set4 и запоминаем текущий набор в oldset
  sigprocmask(SIG_SETMASK,&set4,&oldset);

 //Проверяем правильность установленной маски  
  //if(oldset!=set1)
   // {
   //  printf("\nError! Oldset is not equal to Set1!\n");
     
  //  }

  sigprocmask(SIG_BLOCK,&set1,0);
//Запускаем цикл тестирования перемнной а на нулевое значение
  for(;;)
  {
    if (a!=0)
   { break;}
   }
//Уменьшаем значение переменной а на 1
   a-=1;
 //Проверяем значение переменной b = 1  
   if (b!=1)
    {
      printf("\nError! Variable b!=1\n");
      
    }
//Проверяем значение переменной c = 2  
   if (c!=2)
    {
      printf("\nError! Variable с!=2\n");
      
    }
//Присоединяем все сигналы, ожилающие в заблокированном сотсняии набору 4
    sigpending(&set4);

//Проверяем наличие сигнала в наборе 4
  if (sigismember(&set4, SIGUSR1)!=1)
   {
     printf("\nError! Signal SIGUSR1 is not in set4!\4");
     
   }
//Устанавливаем текущим набор сигналов set4 и разблокируем в нем сигналы
  sigprocmask(SIG_UNBLOCK,&set4,0);
//Запускаем цикл тестирования перемнной а на нулевое значение
  for(;;)
  {
    if (a!=0)
     {break;}
   }
//Уменьшаем значение переменной а на 1
   a-=1;
//Проверяем значение переменной b = 2
   if (b!=2)
    {
      printf("\nError! Variable b!=2\n");
      
    }
//Проверяем значение переменной c = 2  
   if (c!=2)
    {
      printf("\nError! Variable с!=2\n");
     
    }
//Объявляем набор сигналов set5
  sigset_t set5;
//Инициируем этот набор,включая внего все сигналы в системе (все сигналы блокируются)
  sigemptyset(&set5);
  //Добавляем сигналы SIGUSR1 и SIGUSR2 в этот набор
  sigaddset(&set5, SIGUSR1);
  sigaddset(&set5, SIGUSR2);
//Устанавливаем текущим набор сигналов set5 и запоминаем текущий набор в oldset
  sigprocmask(SIG_BLOCK,&set5,0);
//Проверяем наличие сигналов SIGUSR1 , SIGUSR2  в наборе
  if (sigismember(&set5, SIGUSR1)!=1)
   {
     printf("\nError! Signal SIGUSR1 is not in set5!\n");
     
   }
  if (sigismember(&set5, SIGUSR2)!=1)
   {
     printf("\nError! Signal SIGUSR2 is not in set5!\n");
     
   }
//

  nanosleep(&req,&rem);
//Определяем перменные м и е
  int m,e;
  m=1;
  e=0;
  //m=m/e;

 //Проверяем значение переменной a = 1  
   if (a!=1)
    {
      printf("\nError! Variable a!=1\n");
      
    }
//Проверяем значение переменной d = 1 
   if (d!=1)
    {
      printf("\nError! Variable d!=1\n");
      
    }
  //nanosleep(&req,&rem);
//Объявляем структуру в которой хранится информация об обработчике сигналов
  struct sigaction saOLD;
//Присваиваем  игноррование в качестве обработчика сигналу SIGFPE
  saFPE.sa_handler=SIG_IGN;
  sigaction(SIGFPE, &saFPE, &saOLD); 
//Уменьшаем значение а на 1
  a-=1;
//Опять делим е на м чтобы получить сигнал SIGFPE
  m=1;
  m=m/e;
 //Проверяем значение переменной a = 0 
   if (a!=0)
    {
      printf("\nError! Variable a!=0\n");
      
    }

//Определяем обработчик сигнала , имеющийся в системе по умолчанию сигналу SIGFPE

  saFPE.sa_handler=SIG_DFL;
  sigaction(SIGFPE,&saFPE, 0);
//Опять делим е на м
  e=0;
  m=1;
  m=m/e;
 kill(0,SIGCHLD);
   
}


void main()
{

  // Объявляем структуру которая хранит параметры приоритетов
  struct sched_param sch_p;

  // Запоминаем приоритет и политику планировщика
  int currentPriority = sched_getparam(getpid(),&sch_p);
  int currentPolicy = sched_getscheduler(getpid());
  

  //Устанавливаем политику FIFO
  sched_setscheduler(getpid(), SCHED_FIFO, &sch_p);
 
  
//Объявляем обработчки сигнала SIGCHLD с установкой флагов

  struct sigaction saCHLD;
  saCHLD.sa_handler = handler_CHLD;
  saCHLD.sa_flags = SA_SIGINFO;
  sigaction(SIGCHLD, &saCHLD, 0); 

//

    int n = 3;
//Создаем структуры которые хранят время для nanosleep
  struct timespec req;
  struct timespec rem;

  // 2 секунды , 300 наносекунд
  req.tv_sec = 2;
  req.tv_nsec = 300;
 

  // Создаем дочерний процесс, если вернулся ноль, то мы в дочернем процессе и идем в функцию childProcess
  if ((pid_child= fork()) == 0)
     childProcess();

  //А в это время основной процесс приостанавливается на 2 секунды 100 наносекунд
  nanosleep(&req, &rem);


  while (n>0)
    {
      kill(pid_child,SIGUSR1);
      if(n!=2)
      {
       nanosleep(&req,&rem);
      }
      kill(pid_child,SIGUSR2);
      nanosleep(&req,&rem);
      n-=1;
     }


//Запускаем цикл тестирования перемнной i на нулевое значение
  for(;;)
  {
    if (i!=0)
    {break;}
   }

 printf("\nVector StrChld in %i elements:\n",k);
 int s;
 for (s=0;s<k;s++)
 {
  printf("\npid=%i , status=%i , code=%i\n",StrChld[s].pid,StrChld[s].status,StrChld[s].code);
  }
 }

LORCODE для слабаков?

erfea ★★★★★ ()
Ответ на: комментарий от v9lij

Понимаю, код плохо читабелен.При добавлении в редакторе он нормально отображался, но при нажатии отправить все строки стали как сейчас Не подскажешь, как сделать, чтобы он норально отображлся?

Bennett ()

Лучше разбивайте код на маленькие примеры и задавайте вопрос по каждому отдельно.

1)Почему в дочернем процессе Childprocess после подключения обработчика handler_FPE и первого деления m/e (e=0) происходит зацикливание обработчика

После завершения обработчика sigfpe следующей выполенной инструкцией будет та, в которая привела к ошибке, а не следующая.
Ответ легко гуглится: http://technopark02.blogspot.ru/2005/10/handling-sigfpe.html

gv ()
Ответ на: комментарий от gv

Спасибо большое за помощь! С SIGFPE поправил, теперь все ок. Я просто не очень хорошо гуглую по теме на Инглише.. А про комментарии я писал быстро тогда и немного не точно описал , а потом при редактировании здесь на форуме изменил немного код Имелось ввиду вот что : if ((siginfo.si_code==CLD_EXITED) || (siginfo.si_code==CLD_DUMPED) ||(siginfo.si_code==CLD_KILLED)) { if (siginfo.si_pid==pid_child)

С этими ифами (они были закомментирвоаны просто в изначальном варианте кода, что я выкладывал) программа зависает.и яне пойму по чему.А по условию задачи эта ппроверка нужна. Без них все рабтает и вмассиве стуртур формируетя одна сруктра (а по условию должно бытькак я в 2.2 описал)..

Bennett ()
Ответ на: комментарий от Bennett

В каком месте зависает?

Попробуйте объявить i как volatile.
Попробуйте убрать printf из обработчика.

Если не поможет - выкладывайте тогда минимальный пример, который не работает, в этот вряд ли люди вчитываться будут.

gv ()

C ифами вобработчике разобрался. Осталочь решить вопрос с вызовом обработчика сигнала SIGCHLD не только в конце работы, дочернего процесса, но и при его присотановке и предаче управления родлительскому процессу. Внятного объяснения работы SIGCHLD и сосбенностей его вызовов я ,к сожалению ,не нашел...

Bennett ()
Ответ на: комментарий от Bennett

А что такое приостановка и что такое предача управления родительскому процессу?

Почитайте man ptrace, может это то, что вам нужно.

gv ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.