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


  10.3.9. ПРОЦЕССТЕРДІҢ ҮЙЛЕСІМДІЛІГІ



Pdf көрінісі
бет126/158
Дата01.07.2023
өлшемі3.83 Mb.
#475485
түріОқулық
1   ...   122   123   124   125   126   127   128   129   ...   158
операциялық жуйелер

205 
10.3.9. ПРОЦЕССТЕРДІҢ ҮЙЛЕСІМДІЛІГІ 
Себептері алдыңғы тарауларда көрсетілген сигналдарды жоғалту 
мәселелерін болдырмас үшін процестер аралығында сигналдар 
алмасуын, қабылдаушы-процестің оны дұрыс өңдейтін жағдайда 
болғанда, таратушы-процесс кезекті сигналды
ертерек бергенге дейін 
ұйымдастыру қажет.
Осындай тәсілді іске асыруда мүмкін болатын әдістердің бірі - 
жіберуші-процесс сигналды уақыт аралығында береді, алдыңғы 
сигналдың өңделуін және өңделушінің қалпына келуін көп талап ететін 
қабылдаушы-процесс. Мысалы, келесі бағдарлама екі процесті іске 
асырады— оның іске асырылуы кезінде туындайтын аталық және fork() 
іске қосылумен туған еншілес. Еншілес процесс жіберуші рөліне түседі 
және аталық процеске SIGINT сигналын 1 секундта жіберілімдер 
арасында 10 интервалмен жібереді. Қабылдаушы (аталық процесс) 
сигналды қабылдауға жауап ретінде сигнал, олармен қабылданған 
SIGINT сигналдардың жалпы санын шығарады. Серияларды жіберу 
үшін 10 сигналдан SIGINT жіберушісі SIGTERM қабылдаушысына оны 
аяқтай отырып, сигнал жібереді, одан кейін өзінің орындалуын 
аяқтайды:
#include 
 /* Linux –ке қажет емес*/
#include 
#include 
#include 
int num;
void handler(int sig_no)
{
signal(sig_no, &handler); 
num++;
printf("%d\n", num);
}
int main()
{
pid_t pid; 
int i; num 
= 0;
setvbuf(stdout,(char*)NULL,_IONBF,0);
switch (pid=fork())
{


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 тұрақты шамалардың көмегімен еленбеуі қажет.


Достарыңызбен бөлісу:
1   ...   122   123   124   125   126   127   128   129   ...   158




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

    Басты бет