Оқулық «Федералдық білім беруді дамыту институты»


  СИГНАЛДАРДЫ  ӨҢДЕУШІМЕН



Pdf көрінісі
бет176/220
Дата25.02.2022
өлшемі2,22 Mb.
#26438
түріОқулық
1   ...   172   173   174   175   176   177   178   179   ...   220
10.3.5.  СИГНАЛДАРДЫ  ӨҢДЕУШІМЕН 
БАСҚАРУ 
 
Процеспен сигналды алған соң бұл сигналға сәйкес келетін- сигнал-
өңдеуші  кестесінің  жолы  өшіріледі.  Егер  процеспен  сигналды 
қабылдаған  соң,  сигнал  өңдеушісі  қайта  құрылмаса,  онда  сигналды 
аларда әдеттегідей өңдеуші шақырылады.   Сигналды өңдеушіні қайта 
құру  үшін  әдетте  сигналдың  өңдеуші-функциясы  денесіне  signal() 
шақыру  функциясын  сыйғызады.  Мысалы,  келесі  бағдарлама  әр 
SIGINT  сигналын  алуы  кезінде,  сонымен  қатар  сигналды  қабылдау 
үнемі күтетін  «Сигнал қабылданды» жолын шығарады: 
 
#include 
 
#include  
 
void handler(int sig_no)
 
{
 
signal(sig_no, &handler); 
printf("Signal caught\n");
 

 
int main()
 
{
 
signal( SIGINT, &handler); 
while(1)
 
{
 
printf("Waiting for signal...\n"); 
pause();
 
}
 
return 0;
 

 
 
 


 
194 
 
 
 
 
Бұл 
бағдарламаны 
іске 
қосарда 
(ағымдағы 
каталогтағы 
орындалатын файл — signal3) келесі міндеттер: 
 
#!/bin/bash  
./signal3 &  
pid=$!  
sleep 1
 
kill -SIGINT $pid  
sleep 1
 
kill -SIGINT $pid  
sleep 1
 
kill -SIGTERM $pid 
 
экранға шығарылады: 
 
Waiting for signal...
 
Signal caught  
Waiting for signal...
 
Signal caught  
Waiting for signal...
 
./signal3.sh: line 10: 1044 Terminated 
 
Берілген  бағдарлама  SIGINT  сигнал  өңдеушісін  —  handler() 
функциясын  орнатады,  одан  кейін  шексіз  циклге  кіреді,  ол  өзінің 
орындалуын  сигналды  қабылдағанға  дейін  тоқтатады,  бұл  сәйкес 
келетін хабарламаны шығарады. Сигналды қабылдаумен қатар басқару 
handler()  функциясына  беріледі,  ол  пайдаланушыны  сигналдың  түсуін 
хабарлайтын  хабарламаны  шығарады  және  сигналдың  өңделуін 
қалпына  келтіреді.  Осыдан  кейін  басқару  pause()  кейінгі  командаға 
беріледі, яғни шексіз циклдің келесі итерациясы басталады. 
 
Өңдеуші  кестені,  келесі  сигналдың  осы  өңдеушімен  өңделетіндей 
етіп  қалпына  келтіруі  міндетті  емес.  Өңдеушілердің  қалпына  келуін 
процесстің  сигналға  реакциясы  ағымдағы  уақытпен  алмасуы  міндетті 
болатын жағдайларда пайдалануға болады. 
 
Мысалы,  келесі  SIGINT  сигналының  тақ  санын  алуы  кезінде  
бағдарлама A әрпін шақырады (бірінші, үшінші және т.б.) және SIGINT 
сигналының  жұп  санын  алу  кезінде  B  әрпін  шақырады  (екінші, 
төртінші  және  т.б.).  Бұл  әсерге,  SIGINT  өңдеуші  сигналдың  сатылы 


195 
 
 
ауысымымен ғана жетуге болады: 
 
#include 
 
#include  
 
void handler1(int sig_no); 
void handler2(int sig_no); 
 
void handler1(int sig_no)
 
{
 
signal(sig_no, &handler2); 
printf("A\n");
 

 
void handler2(int sig_no)
 
{
 
signal(sig_no, &handler1); 
printf("B\n");
 
}
 
int main()
 
{
 
signal(SIGINT, &handler1); 
while (1)  
pause();  
return 0;
 

 
Келесі 
тапсырмада 
осы 
бағдарламаны 
орындау 
кезінде 
(бағдарламаның  орындалатын  файлдың  атауы  —  signal4  деп 
тұжырымдалады): 
 
#!/bin/bash  
./a &  
pid=$!  
sleep 1
 
kill -SIGINT $pid 
sleep 1
 
kill -SIGINT $pid 
sleep 1
 
kill -SIGINT $pid 
sleep 1
 
kill -SIGINT $pid 
sleep 1
 


 
196 
 
kill -SIGTERM $pid
 
 
экранға шығарылады: 
 
A
 
B
 
A
 
B
 
./signal4.sh: line 14: 2452 Terminated
 
 
Жоғарыда  қарастырылған  сигналдар  механизмінің  уақытша 
шектеулері  —  пайдаланушы  өңделуінің  орнатылуына  дейін  сигналды 
қабылдау  кезінде  әдеттегідей  өңдеушіні  шақыру  –  тек  бағдарламаның 
негізгі  функцияларын  орындау  уақытында  ғана  емес,  өңдеуші-
функцияның орындалу уақытында да әрекет етеді. 
 
Осылайша,  егер  өңделушінің  бірінші  командасымен  сигнал 
өңделуін  қалпына  келтірсе  (алдыңғы  үлгілерде  жасалғандай) 
өңдеушінің кез келген келесі команданы орындау сәтінде сигналды алу 
кезінде  өңдеушінің  өңделушінің  орындалуы  тоқтатылуына  болады. 
Сигналды  қабылдау  сәтінде  өңделуші  қалпына  келген  болса,  онда  ол 
қайта  жаңадан  іске  қосылады.  Егер  оның  орындалу  уақытында  жаңа 
сигнал қабылданбаса, басқару сол өңдеуші-функциясына қайта келеді. 
 
Мұндай  тәртіп  функцияның  рекурсивтік  шақыртуларымен  ұқсас 
келеді, сонымен қатар мұндай «рекурсияның» тереңдігі, өңдеушілердің 
орындалу  уақытында  алынған  сигналдардың  санына  тең  болады. 
Әдебиетте әдетте, «өңдеушінің рекурсивтік шақырылуы» деген термин 
кездеседі.  Мұндай  атау  тіпті  дұрыс  емес,  себебі  қарапайым 
рекурсиямен ешқандай ортақтығы жоқ. 
 
Өңдеушінің  соңғы  жолына  signal()  шақырту  функциясын  сыйғыза 
отырып, өңдеушінің қалпына келтірсе, процестің күйі басқаша болады. 
Осылайша  өңдеуші  шақыртуларының  қайталауынан  құтылуға  болады, 
бірақ  процес  оның  өңделушімен  қалпына  келу  сәтіне  дейін,  сигнал 
қабылдап  алса,  процестің  орындалуын  аяқтайтын  әдеттегідей  өңдеуші 
шақырылады. 
 
Жоғарыда  көрсетілген  қиындықтардан  құтылу  үшін  үш  нұсқаның 
біреуін пайдалануға болады:  
1)  Көлемді  және  сигнал  өңдеушінің  бағдарламалық  кодының 
қиындығын  азайту,  осылайша  оның  орындалу  уақытын  азайтамыз, 
демек, өңдеушінің орындалуы кезінде сигнал қабылдау мүмкіндігі;
 
2) Өңдеуші  тәсілдері  туралы  қабылданған  шешімдерді  кейінге 
қалдыру  және  SIG  IGN  сигналдарын  елемейтін  тұрақты  шамалардың 
көмегімен елемеу. 
 


197 
 
 
SIG_IGN  тұрақты  шамалары  өңдеуші  функцияның  мекенжайы 
орнына,  signal()  функциясының  параметрі  ретінде  ұсынылады.  
Сигналды елемеуді орнатқаннан кейін олар үшін ешқандай өңдеуші — 
әдеттегідей  пайдаланушы  да,  өңдеуші  де  шақырылмайды.  Осылайша, 
өзі  қайталанатын  шақырулардан  және  әдеттегідей  өңдеушінің 
шақыруынан  қорғай  отырып,  өңдеуші-функцияның  басында  сигналды 
елемеу  режимін  орнатуға  болады,  ал  өңдеушіні  функцияның  аяғында 
қалпына келтіруге болады. 
 
 
Типтік өңдеуші бұл жағдайда мынадай болады:  
 
void handler(int sig_no)
 
{
 
signal( sig_no, SIG_IGN); 
... 
... 
signal( sig_no, &handler);
 
}
 
3)  Сигналды пердені пайдалану. 
 
 
 
 


Достарыңызбен бөлісу:
1   ...   172   173   174   175   176   177   178   179   ...   220




©emirsaba.org 2024
әкімшілігінің қараңыз

    Басты бет