*/ 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 кесіндісі).
Аталық критикалық секцияға кірмейтін код аяқталған соң,
семафорды жабу кезінде өзінің орындалуын тоқтата тұрады және
семафор мәнін азайта алған соң өзінің жұмысын бастайды ( Г
кесіндісі). Одан кейін процесс қайталанады.
Достарыңызбен бөлісу: