206
case -1:
perror("Fork error");
exit(1);
break; case 0:
sleep(5); /* аталыққа қою үшін уақыт береміз */
/* өңдеуші */
for (i=0; i<10; i++)
{
kill( getppid(), SIGINT); /* Шлем SIGINT */ sleep(1); /*
қабылдаушының дайын болғанын күтеміз */
}
kill( getppid(), SIGTERM); /* қабылдауды аяқтаймыз */
_exit(0); /* жіберушіні аяқтаймыз */
break;
default:
signal( SIGINT, &handler);
while (1) pause();
_exit(0);
break;
}
return 0;
}
Бұл бағдарламаны орындаудың нәтижесінде экранға 1 ден 10
сандарының тізбегі шығады. Егер сигналдарды үздіксіз жіберілімдер
арасында
жіберсек, (sleep (1) шақыртуын алып), онда сигналдарды
жоғалту қаупі артады, сондай ақ бұл қауіп артқан сайын жүйе
процестің орындалуымен жүктеледі. Бұл жағдайда сигналдарды
жоғалту 1 ден 10 ға дейін емес, ал
аз санға дейін болуымен
тұжырымдалады (мысалы, 8-ге дейін).
Бұл бағдарламаның негізгі кемшілігі, бұл процесс аралық өзара
әрекеттесудің уақыты өте көп және уақыттың біраз бөлігін
қабылдаушы-процесс сигнал күтумен алады.
Жұмыс уақытын азайту үшін және ақпарат санын арттыру үшін
уақыт бірлігінде сигналдар көмегімен жіберілетін,
олардың арасында
екі бағытты сигналдар жіберілуін ұйымдастыра отырып, қабылдаушы
мен жіберушінің орындалуын үйлестіреді. Сонымен қатар, жіберуші
қабылдаушыға сигнал жібереді, ал қабылдаушы сигналдарды
қабылдауға дайын және келесі сигналды өңдей алатынын хабарлаушы
жауап-сигналдарын жібереді. Өндірілмейтін кідірістер мұндай схема
кезінде, өзара әрекеттесу минимумға түседі.
Келесі үлгіде жіберуші-процес, қабылдаушы-процеске сигналдар
207
өңдеушісін орнату үшін (өңдеушілерді орнату үшін қажет, милисекунд
бірлігінен азды- көпті нақты уақыт), сигналдар жіберу алдында 5 сек
күтеді. Жіберуші мен қабылдаушы
арасындағы ары қарай өзара
әрекеттесуі екі бағытты — жіберуші SIGINT сигналын жібереді,
қабылдаушы hdlrInt() функциясы арқылы сигналды өңдейді, өңдеуші
қалпына келтіреді және жіберушіге SIGALRM қабылдаушының
дайындығын куәландыратын сигнал –жауабын жібереді:
#include
/* Linux-ке қажет емес */
#include
#include
#include
int num;
void hdlrInt(int sig_no)
{
signal(sig_no, &hdlrInt);
num++;
printf("%d\n", num);
}
void hdlrAlarm(int sig_no)
{
signal(sig_no, &hdlrAlarm);
}
int main()
{
pid_t pid;
int i;
setvbuf(stdout,(char*)NULL,_IONBF,0);
switch ( pid = fork() )
{
case -1:
perror("Fork error\n");
_exit(1); break; case 0:
signal(SIGALRM, &hdlrAlarm);
sleep(5); /* қабылдаушының инилизациясын күтеді */
for (i=0; i<10; i++)
{
kill(getppid(), SIGINT); /* SIGINT жібереміз */
pause(); /* Ждем SIGALRM */
208
}
kill(getppid(), SIGTERM); /* қабылдауды аяқтаймыз */
_exit(0); /* жіберуді аяқтаймыз */
break;
default:
signal(SIGINT, &hdlrInt);
while (1)
{
pause(); /* Ждем SIGINT */
kill(pid, SIGALRM); /* hdlrInt-тен қайту */
/* және жауап жібереміз */
}
_exit(0);
break;
}
return 0;
}
Келтірілген үлгі әдейі қарапайымдандырылған.
Келесіге назар
аударған жөн, қабылдаушы да жіберуші де тек SIGALRM және SIGINT
сигналдарымен ғана емес, кез келген сигналмен үзіліс жағдайынан
(pause() функциясы кезінде) шығып кетуі мүмкін. Дұрыс жұмыс
жасауы үшін қалған сигналдар сигналды перденің көмегімен не
SIG_IGN тұрақты шамалардың көмегімен еленбеуі қажет.
Достарыңызбен бөлісу: