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


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



Pdf көрінісі
бет132/158
Дата01.07.2023
өлшемі3.83 Mb.
#475485
түріОқулық
1   ...   128   129   130   131   132   133   134   135   ...   158
операциялық жуйелер

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   ...   128   129   130   131   132   133   134   135   ...   158




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

    Басты бет