original in it Leonardo Giordani
it to en: Leonardo Giordani
en to tr �can Gngr
A { d->d+1 } & B { d->output }
Burada "&" ezamanal ilemi ifade eder.Birinci mmkn �lma:
(-) d = 5 (A) d = 6 (B) output = 6
ama eer nce B �lrsa unu elde ederiz :
(-) d = 5 (B) output = 5 (A) d = 6
Bu rnekten ezamanal �lmann doru ynetilmesinin nemini anlyorsunuz.Verilerin
ayn olmamas riski byktr ve kabul edilemez.Bu veri kmelerinin banka
hesaplarnz olduunu dnn.Bu sorunu asla k�msemezsiniz.
Bir nceki makalede waitpid(2) fonksiyonu kullanarak ezamanlamann
ilk bi�mini grmtrk.Bu fonksiyon, bir ilemin devam etmeden nce baka
bir ilemin bitmesi i�n beklemeye yarar.Aslnda bu, okuma-yazma
annda oluabilecek karmakl byk l�de engeller.Bir veri kmesi
zerinde P1 �lyorsa, P2 ayn veri kmesinde veya bir alt kmesinde
�lacaksa nce P1'in bitmesini beklemek zorundadr.
A�kca bu yntem bir �zmdr.fakan en iyisi deildir.P2, P1'in ileminin
bitmesi i�n -�k ksa srecekse bile- uzun zaman bekleyecektir.Biz kontrolmzn
alann daraltmalyz.�nein:tek bir veriye ya da veri kmesine
erime gibi.Bu sorunun �zm ktphanelerin temeli olan,SysV IPC(System
V InterProcess Communication-SistemV �lemleraras �etiim) ad verilen
bir takm ktphane ile verilir.
key_t ftok(const char *pathname, int proj_id);
Bu fonksiyon, var olan bir dosya adn (pathname) ve bir tam say kullanr.Anahtarn
tek olacann garantisi yoktur �nk dosyadan alnan parametreler (i-node
says ve src numaras), benzer kombinasyonlar oluturabilir.Var
olan anahtarlar kontrol eden ve ayn anahtarn kullanmasn engelleyecek
k�k bir ktphane oluturmak iyi bir �zm olacaktr.
int semget(key_t key, int nsems, int semflg);
Burada key,IPC anahtardr.nsems, oluturmak istediimiz semafor saysdr.semflg,
12 bitlik eriim kontorldr.�k 3' oluturma politikasna gre deiir,
dier 9' ise kullanc, group ve dierlerinin (Unix dosya sistemindeki
gibi) okuma ve yazma haklardr.Tam a�klama i�n ipc(5)'nin kullanma klavuzunu
okuyun.Farkettiiniz
gibi SysV bir semafor kmesini kontrol eder ve bu sebeple kod daha k�ktr.
�k semaforumuzu oluturalm:
#include <stdio.h>
#include <stdlib.h>
#include <linux/types.h>
#include <linux/ipc.h>
#include <linux/sem.h>
int main(void)
{
key_t key;
int semid;
key = ftok("/etc/fstab", getpid());
/* Bir semafor i�en bir semafor kmesi oluturalm */
semid = semget(key, 1, 0666 | IPC_CREAT);
return 0;
}
�eride semaforlarn nasl ynetildiini ve silindiini reneceiz.Semaforu ynetme fonksiyonu semctl(2)'dir:
int semctl(int semid, int semnum, int cmd, ...)
Burada parametreler semafor kmesinin veya (istenirse) sadece semnum ile belirtilen semaforun ilevine bal olarak cmd ile verilir.Biz gereksinim duyduk� baz se�nekleri anlatacaz.Ama tm liste kullanma klavuzunda verilmitir.cmd ilevine bal olarak fonksiyon i�n baka parametreler de tamnlamak gerekebilir.� ekildedir:
union semun {
int val;
/* SETVAL deeri */
struct semid_ds *buf; /* IPC_STAT, IPC_SET
i�n tampon*/
unsigned short *array; /* GETALL, SETALL i�n
dizi*/
/* Linux'a zg ksm */
struct seminfo *__buf; /* IPC_INFO i�n tampon*/
};
Semafora deer verebilmek i�n SETVAL ynergesi kullanmladr ve bu deer semun birliinde (union) belirtilmelidir:Bir nceki programdaki semforun deerini 1 yapalm:
[...]
/* Bir semaforlu bir semafor kmesi olutur */
semid = semget(key, 1, 0666 | IPC_CREAT);
/* 0 numaral semaforun deerini 1 yap */
arg.val = 1;
semctl(semid, 0, SETVAL, arg);
[...]
�mdi semafor i�n ayrlm yeri boaltmamz gerekiyor.Bu ilem, semctl fonksiyonunda IPC_RMID ynergesi ile yaplr.Bu ilem semaforu siler ve bu kaynaa ulamak i�n bekleyen butn ilemlere bir ileti gnderir.Yukardaki programn devam olarak:
[...]
/* Semafore 0'in deerini 1 yap */
arg.val = 1;
semctl(semid, 0, SETVAL, arg);
/* Semaforu sil */
semctl(semid, 0, IPC_RMID);
[...]
Daha nce de grdmz gibi ezamanl ilerleri oluturmak ve ynetmek
zor deildir.Hata ynetimi iin i�ne girdiinde, kodun karmakll
a�sndan iler biraz zorlaacak.
Artk semafor semop(2) fonksiyonu ile kullanlabilir:
int semop(int semid, struct sembuf *sops, unsigned nsops);
Burada semid, kmenin belirteci; sops, yaplacak ilemler dizisi ve nsops bu ilemlerin saysdr.Btn ilemler sembuf yapsyla temsil edilir:
unsigned short sem_num; short sem_op; short sem_flg;
�nein kmedeki semaforun numaras (sem_num), ilem (sem_op) ve bekleme
politikasn ayarlayan bayrak (imdilik sem_flg 0 olsun).Belirleyeceimiz
ilemler tam saylardr ve aadaki kurallara uyar:
Doluluk, O semaforunun deerini artamamak ile; boluk, U semaforunu deerini azaltamamak ile anlalr.
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <linux/types.h>
#include <linux/ipc.h>
#include <linux/sem.h>
int main(int argc, char *argv[])
{
/* IPC */
pid_t pid;
key_t key;
int semid;
union semun arg;
struct sembuf lock_res = {0, -1, 0};
struct sembuf rel_res = {0, 1, 0};
struct sembuf push[2] = {1, -1, IPC_NOWAIT, 2, 1, IPC_NOWAIT};
struct sembuf pop[2] = {1, 1, IPC_NOWAIT, 2, -1, IPC_NOWAIT};
/* Dierleri */
int i;
if(argc < 2){
printf("Kullanm: bufdemo [boyut]\n");
exit(0);
}
/* Semaforlar */
key = ftok("/etc/fstab", getpid());
/* 3 semafor i�ren semafor kmesi olutur */
semid = semget(key, 3, 0666 | IPC_CREAT);
/* Semaphore #0'n deerini 1 yap - Kaynak kontrol */
arg.val = 1;
semctl(semid, 0, SETVAL, arg);
/* Semafor #1'in deerini buf_length yap- Doluluk kontrol */
/* Sem'in deeri 'tampondaki bo yer'dir */
arg.val = atol(argv[1]);
semctl(semid, 1, SETVAL, arg);
/* Semafor #2'nin deeri buf_length'dir - Boluk kontrol */
/* Sem'in deeri 'tampondaki eleman says'dr */
arg.val = 0;
semctl(semid, 2, SETVAL, arg);
/* Ayrma */
for (i = 0; i < 5; i++){
pid = fork();
if (!pid){
for (i = 0; i < 20; i++){
sleep(rand()%6);
/* Kayna kilitlemeyi dene - sem #0 */
if (semop(semid, &lock_res, 1) == -1){
perror("semop:lock_res");
}
/* Bir serbest boluu kilitle - sem #1 / Bir eleman koy - sem
#2*/
if (semop(semid, &push, 2) != -1){
printf("---> �lem:%d\n", getpid());
}
else{
printf("---> �lem:%d TAMPON DOLU\n", getpid());
}
/* Kayna brak */
semop(semid, &rel_res, 1);
}
exit(0);
}
}
for (i = 0;i < 100; i++){
sleep(rand()%3);
/* Kayna kilitlemeyi dene - sem #0 */
if (semop(semid, &lock_res, 1) == -1){
perror("semop:lock_res");
}
/* Serbest boluun kilidini kaldr - sem #1 / Bir
eleman al - sem #2 */
if (semop(semid, &pop, 2) != -1){
printf("<--- �lem:%d\n", getpid());
}
else printf("<--- �lem:%d TAMPON BO�n",
getpid());
/* Kayna brak */
semop(semid, &rel_res, 1);
}
/* Seamforlar sil */
semctl(semid, 0, IPC_RMID);
return 0;
}
Koddaki u ilgin�satlara bakalm:
struct sembuf lock_res = {0, -1, 0};
struct sembuf rel_res = {0, 1, 0};
struct sembuf push[2] = {1, -1, IPC_NOWAIT, 2, 1, IPC_NOWAIT};
struct sembuf pop[2] = {1, 1, IPC_NOWAIT, 2, -1, IPC_NOWAIT};
Bu drt satr, semaforlar zerinde yapabileceimiz ilemlerdir: �k
ikisi tek ilem iken dier iki ilem �ft ilemdir.�k ilem, lock_res,
kayna kilitmeyi dener:Bu ilem ilk semaforun (0 numaral) deerini -eer
semaforun deeri sfr deilse- bir azaltr.Kaynan kilitli olmas durunda
politika hi�iri deildir (rnein ilem bekleme durumunda).rel_res, lock_res'e
benzer ama kaynak braklr( deeri pozitiftir) .
Ekleme ve �karma ilemleri biraz zeldir.Bunlar iki ilem dizisidir.Birincisi
1 numaral semafor zerinde ve ikincisi 2 numaral semafor zerindedir.Birincisi
artrma iken ikincisi azaltmadr veya tam tersi.Ama politika artk bekleme
durumu deildir:IPC_NOWAIT, ilemi, kaynak kilitli ise �lmasna devam
etmesi i�n zorlar.
/* Semafo #0'in deerini 1 yap - Kaynak kontrol */
arg.val = 1;
semctl(semid, 0, SETVAL, arg);
/* Semafor #1'i buf_length yap - Doluluk kontrol */
/* Sem'in deeri 'tampondaki bo yer'dir */
arg.val = atol(argv[1]);
semctl(semid, 1, SETVAL, arg);
/* Semafor #2'yi buf_length yap - Boluk kontrol */
/* Sem'in deeri 'tampondaki eleman says'dir */
arg.val = 0;
semctl(semid, 2, SETVAL, arg);
Burada semaforlara ilk deerlerini veririz..Birincisini 1 yaparz �nk belirili bir kaynaa ulamay kontrol eder.�incisini, tamponun uzunluuna eitleriz.�ncsn ise boluk ve doluluu gsterir.
/* Kayna kilitlemeye �l - sem #0 */
if (semop(semid, &lock_res, 1) == -1){
perror("semop:lock_res");
}
/* Bir bo yer kilitle - sem #1 / Bir eleman koy - sem #2*/
if (semop(semid, &push, 2) != -1){
printf("---> �lem:%d\n", getpid());
}
else{
printf("---> �lem:%d TAMPON DOLU\n", getpid());
}
/* Kaynaktaki kilidi kaldr */
semop(semid, &rel_res, 1);
Y ilemi, kayna lock_res fonksiyonunu kullanarak kilitlemeya �lr.Bunu ger�kletirdikten sonra kaynaa bir eleman koyar ve bunu ekrana yazar.Eer bu ilemi yapamazsa ekrana "TAMPON DOLU" iletisini yazar.Daha sonra kayna serbest brakr.
/* Kayna kilitlemeyi dene - sem #0 */
if (semop(semid, &lock_res, 1) == -1){
perror("semop:lock_res");
}
/* Serbest boluun kilidini kaldr - sem #1 / Bir
eleman al - sem #2 */
if (semop(semid, &pop, 2) != -1){
printf("<--- �lem:%d\n", getpid());
}
else printf("<--- �lem:%d TAMPON BO�n",
getpid());
/* Kayna brak */
semop(semid, &rel_res, 1);
O ilemi, az �k Y kadar �ltrlr:Kayna kilitler, bir eleman alr ve kayna serbest brakr.
Bir sonraki makalede, ileti kuyruklarndan, �lemleraras �etiimin
ve ezamanlamann farkl bir yapsndan bahsedeceiz.Bu makaleyi kullanarak
yazdnz programlar -basit olsalar bile- bana da gnderin ( isim ve
e-posta adreslerinizle birlikte ).Bunlar okumaktan memnun olacam.�i
�lmalar.