Добрый вечер , увжаемые форумчане! Хочу попросить знающих людей посмотреть мой код и объяснить несколько вещей по нему .Прошу сильно не пинать - программа это задние по предмету в инсте, под позикс впервый раз проги пишу., писал все по не самому лучшему рукрвдоству, данному преподавтелем. Компилирую в 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);
}
}