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


  Семаформен жұмыс жасауға арналған



Pdf көрінісі
бет186/220
Дата25.02.2022
өлшемі2,22 Mb.
#26438
түріОқулық
1   ...   182   183   184   185   186   187   188   189   ...   220
Байланысты:
қазақша кітап

10.5.2.  Семаформен жұмыс жасауға арналған 
жүйелік шақыртулар 
 
 
UNIX-жүйелерінде  семаформен  жұмыс  жасауға  арналған  бірнеше 
интерфейстер  бар.    Бұл  тарауда  қарастырылатын басқаларынан  бұрын 
пайда  болған  және  «System  V  семафорлы  интерфейс»  атауына  ие 
болған.  Мұнда  бір  бүтін  болып  қарастырылатын,    семафор-  есептегіш 
жинағы  ұғымы  қолданылады.    Жинақтың  әр  элементі  жеке  семафор-
есептегіш  ұсынады,  сонымен  қатар  жинаққа  жүргізілетін  жалғыз 
операция  көмегімен  жинаққа  енетін  семафор  мәндерін  өзгертуге 
болады, яғни бір уақытта бірнеше P немесе V операцияларын қолдануға 
болады, немесе осы операцияларды біріктіруге болады.  
 
Пайда болған семафорлар жинағын ашу немесе құру үшін UNIX –те 
semget() функциясы қолданылады:
 
#include 
 
/*В Linux - #include */ int 
semget (key_t key, int num, int flag);
 
Параметр  key,    семафор  жинағы  идентификаторын  береді,  егер 
оның  орнына  _PRIVATE  тұрақты  шамасы  көрсетілген  болса;  семафор 
жинағы  жинақпен  және  оның  топтарымен  құрылған    тек  процеспен 
қолданылуы мүмкін.  Параметр num, жинақтағы  семафор санын береді, 
көптеген    UNIX-тәрізді  ОЖ-де  бұл    параметр  25-  тен  аспауы  қажет. 


 
224 
 
Параметр flag, келесі мәндерге ие болуы мүмкін:
 
■ 
0  —  егер  key  идентификаторлы    семафор  жинағы  болса,  онда 
функция оның дескрипторын қайтарады;
 
■ 
IPC_CREAT — key  идентификаторлы жаңа жинағын құрады. 
 
Егер    IPC_CREAT  тұрақты  шамасы,  логикалық  қосылу 
операциясының  IPC_EXCL  тұрақты  шамасымен  біріккен  болса,  онда 
бұл  жағдайда  егер,  мұндай  идентификаторлы    семафорлардың 
болуында,  функция  -1  қайтарады.  Семафор  жинағына  қол  жеткізу 
құқығын  беру  үшін  олардың  сегіздік  ұсынуларымен  қалған  тұрақты 
шамаларын біріктіру қажет. 
 
Семафор  жинағына  арналған  R  қол  жеткізу  құқығы,  оның  мәнін 
оқуға,    w  қолжетімділік  құқығы    —  семафор  мәнін  өзгертуге,  ал    x  
қолжетімділік  құқығы—  семафор  жинағының    параметрін  өзгертуге  
мүмкіндік береді.
 
Semget() функциясының типтік шақыртуы мынадай көрінеді: 
int 
sem_descr;
 
sem_descr = semget(ftok("A",1), 1, IPC_CREAT | IPC_EXCL 
| 0644);
 
 
Семафорды 
құрғаннан 
кейін 
оның 
мәні 
ешқандай 
инизацияланбайды,  сондықтан  оны  пайдаланбас  бұрын  жинақтың  әр 
семафорына  бастапқы  мәнін  тағайындау  керек.  Бұны  semctl() 
функциясының көмегімен іске асыруға болады:
 
#include 
 
/*В Linux - #include */
 
int semctl (int semfd, int num, int cmd, union
 
semun arg);
 
Параметр  semfd    семафор  жинағының  дескрипторын  береді; 
параметр  num  —  жинақтағы  семафор  нөмірі;  cmd  семафорда 
орындалатын команданы береді.  Міндетті емес төртінші параметр arg 
командалар  параметрін береді.
 
Төртінші параметрдің құрылымы келесі:  
union semun {
 
int val; /* SETVAL командасымен қолданылады*/ struct 
semid_ds *buf; /* 
 
IPC_SET және IPC_STAT 
командасымен қолданылады */
 
ushort *array; /* SETALL командасымен қолданылады.
 


225 
 
 
Семафорда жүретін негізгі командалар, мыналар:
 
■ 
IPC_RMID — семафор жинағын өшіреді;
 
■ 
IPC_SET — семафор жинағына  arg.buf  құрылымынан мәндерімен 
параметр орнатады;
 
■ 
IPC_GET — arg.buf құрылымында семафор жинағының параметрлер 
мәндерін оқиды;
 
■ 
GETALL — arg.array алабында семафордың барлық мәндерін оқиды;
 
■ 
SETALL — arg.array алабынан барлық семафордың мәндерін оқиды;
 
■ 
GETVAL — num нөмірімен семафордың мәнін қайтарады. Аргумент 
arg қолданылмайды;
 
■ 
SETVAL — num  нөмірімен семафор мәндерін  arg.val орнатады.
 
Сәтсіз орындалуы кезінде функция -1 қайтарады.
 
Барлық  семафор  мәндерін  орнату  үшін  SETALL    командасын 
немесе  SETVAL    командасының  циклдік  шақыртуын  қолдануға 
болады:
 
#include 
 
#include  /* В Linux - #include  
*/
 
typedef int semnum; int main()
 
{
 
int i;
 
int sem_descr; union semnum arg; arg.val = 4;
 
sem_descr = semget(ftok("A"), 3,
 
IPC_CREAT | IPC_EXCL | 0644); for (i=0;i<3;i++)
 
{
 
semctl(sem_descr, i, SETVAL, arg);
 
}
 
}
 
Семафорларды  инициализациялау  және  құру  операцияларын  бөлу, 
семафор  жинағы  құрылған,  бірақ  инициализацияланбаған  жағдайға 
әкеп  соқтыруы  мүмкін,    ал  басқа  процес  оны  қолдануға  тырысады. 
Мұндай  жағдайдың  алдын  алу  үшін  семафор  құрылған  соң  шамалы 
уақыттан  кейін  оны  еріксіз  қолдануды  бастауға  болады.  Мұндай 
жағдайдан  қашудың  тиімді,  бірақ  күрделі    тәсілдері  [18] 
қарастырылған.
 
Қазіргі  уақытта  жүйеде  құрылған  барлық  семафорды  қарау  үшін 
ipcs командасы қолданылады. Оны командалық жолдан -s параметрмен 
іске асыруға болады.


226 
 
 
 
 
 
 
Семафор  параметрлері  kernel.sem.    құрауыш  параметрлерімен 
анықталады.  Бұл  параметр  бірнеше    параметршілерге  ие:  semmni, 
semmsl,  semmns  және  semopm.  Semmni  параметрі  семафор  алабының 
максималды  санын,  semmsl  —  алаптағы  семафордың  максималды 
санын  анықтайды,  semmns  параметрі  жүйедегі  семафордың 
максималды санын береді және semmsl және semmni туындысы сияқты 
есептеледі.  Параметр  semopm  семафорда  жүргізілетін,  бір  рет 
орындалатын  операциялардың максималды санын береді.
 
Бұл  параметрлер  хабарламалардың  кезегі  жүйесінің  параметрлері 
сияқты оперативті өзгертуге болады. 
 
echo 250 256000 32 1024 > /proc/sys/kernel/sem
 
Бірінші  сан  semmsl  параметрінің,  екінші  —semmns  параметрінің, 
үшінші  —seopm  параметрі  мен  төртінші  —semni  параметрінің  мәнін 
береді.
 
Бұл  жүйедегі  өзгерістерді  сақтау  үшін  және  қайта  жүктелімнен 
кейін  бұл  файлдардың  жаңа  мәнін  /etc/sysctl.conf  (kernel.sem=250 
256000  32  1024)  файлға  енгізу  керек  немесе  sysctl  -w  kernel.sem="250 
256000 32 1024" командасын пайдалану керек. 
 
Семафор параметрінің мәні туралы ақпарат ipcs –ls командасының 
көмегімен алуға болады:
 
 
 
 
 
$ ipcs -ls
 
Semaphore Limits
 
max number of arrays = 128 
SEMMNI
 
//
 
max semaphores per array = 250 
SEMMSL
 
//
 
max semaphores system wide = 32000 
SEMMNS
 
//
 
max ops per semop call = 32 
SEMOPM
 
semaphore max value = 327 67
 
//
 
 
 


227 
 
 
Жинақтағы семафор мәнін басқару үшін semop() функциясы қызмет 
етеді:
 
#include 
 
/* В Linux - #include  */
 
int semop(int semfd, struct sembuf* opPtr, int
 
len);
 
Параметр  semfd,    семафор  жинағының  дескрипторын  береді,  opPtr 
—әр  элементі  жинақтағы  семафорға  жүргізетін  бір  операцияны 
беретін, алаптарды көрсетеді; параметр len, жинақтың қанша элементті 
құрайтынын анықтайды. 
 
ОpPtr алабының элементтері келесі түрмен анықталады: 
 
struct sembuf {
 
short sem_num; /* жинақтағы семафор нөмірі*/ 
short sem_op; /* семафорға жүргізілетін операция 
*/ short sem_flg; /* операция жалауы */
 
}
 
Sem_op 
семорына  жүргізілетін  операция  келесі  мәндерді 
қабылдайды: 
 
■ 
0  —  семафор  мәнін  оқу;  егер  ол  нөлге  тең  болса,  онда  процесс 
орындалуы, семафор мәні оң болғанға дейін тоқтатыла тұрады; 
 
■ 
Оң сан — семафор мәнін берілген бірлікке дейін арттырады; 
 
■ 
Теріс сан — семафор мәнін берілген бірлікке дейін азайтады; 
 
Егер  семафор  мәні  теріс  болса,    онда  ядро  сол  сияқты  процестің 
орындалуын тоқтатады. Процестің  орындалуы,  семафор мәні  теріс 
болмағанда ғана жалғасады. 
 
Егер  sem_flg  жалаушасы  ретінде  IPC_NOWAIT  тұрақты  шамасын 
берсе,  процесс  тоқтатылуы  болмайды.    Егер  жалауша  ретінде 
SEM_UNDO  тұрақты  шамасын  көрсетсе,  ядро  семафор  өзгерісін 
аңдиды.  Егер  процесс,  семафор  мәнін  нөлге  дейін  немесе  теріс  санға 
дейін  азайтса,  онда  аяқталады,  семафорды  ашу  үшін  процестерді  
«мәңгі»  күтуді шақырмас үшін онымен жасалған өзгерістер болмайды. 
 
UNIX 
әр 
түрлі 
нұсқаларында 
sembuf 
 
құрылымында 
жолақшалардың  бақылау  реті  айырылады,  сондай-ақ  басқа  да 
жолақшалар  қатысуы  мүмкін,  сондықтан  мәндерді  ретімен  емес,  ал 
жолақшалардың атауы көмегімен тағайындалады.  
Келесі  үлгіде  екі  процесс  семафорды  экранға  мәтінді  шығару 
процесін  диспетчерлендіру  үшін  қолданады.  Екі  процесс  экранға 
мәтіндік  жолдарды  кезекпен  шығарады,  сонымен  қатар  sleep() 
функциясының  көмегімен  «шығару»  топ-процесі  4  с,  аталық  —  1  с 
алады.  Шығарудың  кезектігін  сақтау  үшін  ресурсты  сақтау  (берілген 


228 
 
 
жағдайда—  терминал),  процестің  әрі  V  операциясын  орындайды,  ал 
босағаннан  соң    —P  операциясы  орындалады.  Семафорға  жүргізілген 
барлық операциялар төменде келтіретін үлгіде ор алабында сақталады, 
сонымен  қатар  op[0]  мәні,    семафор  мәнін  бірлікке  азайтады  және  V 
операциясына сәйкес келетін op[1] семафор мәнін нөлге тексереді және 
мысалда  қолданылмайды,  op[1]  семафор  мәнін  бірлікке  арттырады 
және  P операциясына сәйкес келед 
 
#include 
 
/* В Linux - #include  */
 
#include 
 
#include 
 
#include 
 
#include 
 
struct sembuf *op[3]; /* семафорға жүргізілетін 
операциялар:
 
op[0] – мәнін азайтады
 
op[1] - тексереді
 
op[2] – мәнін арттырады */
 
int main(void)
 
{
 
int fd, i,j, *status; pid_t pid;
 
setvbuf(stdout,(char*)NULL,_IONBF,0); for (i=0;i<3;i++)
 
{
 
/* операцияда жадыны белгілейді*/
 
p[i]=(struct sembuf*)malloc(sizeof(struct sembuf));
 
}
 
for (i=-1;i<2;i++)
 
{ /* операцияларды толтыру */ op[i+1]->sem_num = 0; 
op[i+1]->sem_op = i; op[i+1]->sem_flg = 0;
 

/* нәтижесінде  {0,-1,0},{0,0,0},{0,1,0} */ witch (pid = 
fork() )
 
{
 
case -1 аламыз:
 
perror("Bad fork\n");
 
exit(1);
 
break;
 
case 0:
 
/* child body */ sleep(1);
 


229 
 
 
/*  семафорды ашу */
 
fd = semget(ftok("A",1), 1, 0);
 
for (i=0;i<10;i++)
 
{
 
semop(fd, op[0], 1); /* V семафор */ printf("c%d ",i);
 
/* процесс ұзындығын имитациялау (4 сек) */ sleep(4);
 
semop(fd, op[2], 1); /* P семафорда */
 
}
 
break;
 
default:
 
/* parent body */
 
/* семафорды құру */
 
fd=semget(ftok("A",1), 1, IPC_CREAT | 0644);
 
/* семафордың бастапқы мәнін орнату в 1 */ semctl(fd, 0, 
SETVAL, 1); for (i=0;i<10;i++)
 
{
 
semop(fd, op[0], 1); /* V семафор */ printf("p%d ",i);
 
/* қысқа процесті имитациялау (1 сек) */ sleep(1);
 
semop(fd, op[2], 1); /* P семафор */
 
}
 
wait(&status); /* ұрақтың аяқталуын күту */ semctl(fd, 
0, IPC_RMID); /* семафорды жою */ break;
 
}
 
printf("\n");
 
/* операция жадын босату */ for (i=0;i<3;i++) 
free(op[i]); return 0;
 
}
 
Бұл  бағдарламаны  іске  қосудың  нәтижесінде  экранға  келесі 
реттілікті  шығарады,  онда  процестің  біріктірілуінің  орындалуын 
көрсетеді:
 
c0 p0 cl pi c2 p2 c3 p3 c4 p4 c5 p5 c6 p6 c7 p7 c8 p8 c9 
р9
 
яғни аталық-процесс, семафор ашылғанға дейін шығарылуы 1 с алады,  
 
3 с күтеді, баяу топ-процеспен қондырылатын, шығарылым 4 с алады. 
Ең баяу процесс, ресурс босағанға дейін 1 с күтеді.
 
Егер  жоғары  келтірілген  бағдарламалар  semop()  функциясы 
шақыртуларын кетірсе, онда бағдарламаның шығуы мынадай болады:
 
c0 p0 pl p2 p3 cl p4 p5 p6 p7 c2 p8 p9 c3 c4 c5 c6 c7 c8 
c9
 


230 
 
 
Екі 
нұсқаны 
салыстырмасынан 
синхрондаудің 
жоқтығының 
айырмашылықтары  анық  көрініп  тұр—  бұл  уақытта  топ-процесі,  бір 
«сХ»  реттілігін  шығарып  үлгереді,  аталық      төрт  «pX»  тізбектілігін 
шығарады. 
 
 
10.7-  сурет.  Процестерді  синхрондау  үшін  семафорды  қолданудың 
уақытша диаграммасы


231 
 
 
 
 
Семаформен  жұмыс  процесін  уақыт  сызығында  сипаттасақ  10.7-
суретте  көрсетілген  бейнені  алуға  болады.  Суретте  бірнеше  уақыт 
сызықтары  бейнеленген,  әрі  процесс  күйінің  немесе  семафордың 
өзгеруіне сәйкес келеді. 
 
Уақыт  сызығында  тіктөртбұрыштар  процестің  белсенділігіне 
(алғашқы екі сызық) және семафор мәнінің оң (ашық) кезеңіне (үшінші 
сызық)    сәйкес  келеді.    Уақыттың  төменгі  сызығы  семафорға 
жүргізілетін  операцияны  көрсетеді;  төменге  бағытталған  нұсқармен 
семафордың  мәні  азаюын  және  жоғарыға  бағытталған  нұсқалар— 
мәндердің  артуын  белгілейді.  Нұсқалардың  жанында  операцияны 
орындаған  процесс  көрсетіледі.  «Р»  әрпімен  аталық  -  процесс,  «с» 
әрпімен — топ-процесс бейнеленген.
 
Екі  процесс  бір  уақытта  басталады  және  алдымен  жеке 
ақпараттарын инициализациялайды, сонымен бірге  аталық семафорды 
ашады  (А  кесіндісі).  Инициализация  аяқталған  соң,  аталық-процесс 
семафорды  жабады,  осымен  сыни  секцияны  бастайды  (  графиктегі  Б 
және p1  кесіндісі).
 
Топ-процесс  семафорды  жабу  кезінде  тоқтайды.  Өзінің  сыни 
секциясы аяқталған соң аталық семафорды ашады және сыни секцияға 
кірмейтін бағдарламалық кодты орындауды жалғастырады (графиктегі 
x).  Осы  сәтте  топ-процесс  белсенді  болады,    семафордың  мәнін 
азайтады  және  критикалық  секцияда  өзінің  орындалуын  бастайды  ( 
графиктегі В және с1 кесіндісі).
 
Аталық  критикалық  секцияға  кірмейтін  код  аяқталған  соң, 
семафорды  жабу  кезінде  өзінің  орындалуын  тоқтата  тұрады  және 
семафор  мәнін  азайта  алған  соң    өзінің  жұмысын  бастайды  (  Г 
кесіндісі). Одан кейін процесс қайталанады.
 


Достарыңызбен бөлісу:
1   ...   182   183   184   185   186   187   188   189   ...   220




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

    Басты бет