e�r�s: Le�r�s: Le�r�s: Le�r�s: Le�r�s: Le�r�s: Le�r�s: Le�r�s: Le�r�s: D:\!SO2\html\buttons\n_prev.gif  e�r�s: Le�r�s: Le�r�s: Le�r�s: Le�r�s: Le�r�s: Le�r�s: Le�r�s: Le�r�s: D:\!SO2\html\buttons\n_up.gif  e�r�s: Le�r�s: Le�r�s: Le�r�s: Le�r�s: Le�r�s: Le�r�s: Le�r�s: Le�r�s: D:\!SO2\html\buttons\n_next.gif  e�r�s: Le�r�s: Le�r�s: Le�r�s: Le�r�s: Le�r�s: Le�r�s: Le�r�s: Le�r�s: D:\!SO2\html\buttons\n_home.gif

Szemaforok (semaphores)

Olyan jelek, amelyek megmutatj�k, hogy egy folyamat v�grehajthat-e egy programr�szt vagy sem...


 

e�r�s: Le�r�s: Le�r�s: Le�r�s: Le�r�s: Le�r�s: Le�r�s: Le�r�s: Le�r�s: D:\!SO2\html\buttons\n_link.gif  Defin�ci�

e�r�s: Le�r�s: Le�r�s: Le�r�s: Le�r�s: Le�r�s: Le�r�s: Le�r�s: Le�r�s: D:\!SO2\html\buttons\n_link.gif  Műveletek szemaforokkal

e�r�s: Le�r�s: Le�r�s: Le�r�s: Le�r�s: Le�r�s: Le�r�s: Le�r�s: Le�r�s: D:\!SO2\html\buttons\g_link.gif  L�trehoz�s (semget)

e�r�s: Le�r�s: Le�r�s: Le�r�s: Le�r�s: Le�r�s: Le�r�s: Le�r�s: Le�r�s: D:\!SO2\html\buttons\g_link.gif  Szemafor adatainak lek�rdez�se, m�dos�t�sa �s t�rl�se (semctl)

e�r�s: Le�r�s: Le�r�s: Le�r�s: Le�r�s: Le�r�s: Le�r�s: Le�r�s: Le�r�s: D:\!SO2\html\buttons\g_link.gif  Szemafor �rt�k�nek n�vel�se �s cs�kkent�se (semop)

e�r�s: Le�r�s: Le�r�s: Le�r�s: Le�r�s: Le�r�s: Le�r�s: Le�r�s: Le�r�s: D:\!SO2\html\buttons\n_link.gif  P�ld�k

e�r�s: Le�r�s: Le�r�s: Le�r�s: Le�r�s: Le�r�s: Le�r�s: Le�r�s: Le�r�s: Le�r�s: D:\!SO2\html\buttons\n_link.gif  POSIX kieg�sz�t�s

 

 


 

 

e�r�s: Le�r�s: Le�r�s: Le�r�s: Le�r�s: Le�r�s: Le�r�s: Le�r�s: Le�r�s: D:\!SO2\html\buttons\n_link_p.gif  �zenetsorok (message queues)

e�r�s: Le�r�s: Le�r�s: Le�r�s: Le�r�s: Le�r�s: Le�r�s: Le�r�s: Le�r�s: D:\!SO2\html\buttons\n_book.gif  Defin�ci�

A processzor maxim�lis kihaszn�l�sa �rdek�ben az oper�ci�s rendszerek jelentős r�sze – �gy a Unix is – enged�lyezi a folyamatoknak a p�rhuzamos (egyidőben t�rt�nő) fut�st. Ez a megold�s igen hat�kony, de mi t�rt�nik akkor, ha k�t folyamat egyidőben pr�b�lja el�rni ugyanazt az erőforr�st? Ilyen "�rz�keny" erőforr�sok p�ld�ul a nyomtat� vagy a mem�ria, amelyet egyszerre csak egy folyamat haszn�lhat, k�l�nben a műveletnek előre nem l�that� k�vetkezm�nyei lehetnek.

Kritikus szakasznak nevezz�nk teh�t egy olyan m�dos�t�st a rendszeren, amelyet nem szabad megszak�tani. A kritikus szakasz erőforr�shoz k�t�tt (p�ld�ul a nyomtat�hoz).

A szemaforok lehetőv� teszik a felhaszn�l�k sz�m�ra a folyamatok szinkroniz�l�s�t. �ltal�ban a szemafor egy eg�sz v�ltoz�, amelyhez hozz�rendel�nk egy e0(v) kezdeti �rt�ket, egy e(v) aktu�lis �rt�ket �s egy f(v) v�rakoz�si sort.

Az al�bbiakban bemutatjuk a legismertebb szinkroniz�ci�s P �s V elj�r�sokat.

P(v)
{
  e(v) = e(v) - 1;
  if (e(v) < 0)
  {
    folyamat_allapota = WAIT;
    f(v) sorba <- folyamat;
  }
}

V(v)
{
  e(v) = e(v) + 1;
  if (e(v) <= 0)
  {
    folyamat <- f(v) sorb�l;
    kivalasztott_folyamat_allapota = READY;
  }
}

A szemafor aktu�lis �llapot�t a k�vetkező k�plet adja:

e(v) = e0(v) + n�V(v) – n�P(v)

ahol:

n�V(v)  –  a v szemaforon v�grehajtott V elj�r�sok sz�ma,

n�P(v)  –  a v szemaforon v�grehajtott P elj�r�sok sz�ma.

Teh�t egy kritikus szakasz megval�s�t�sa a k�vetkezők�ppen t�rt�nik: a szemafor kezdeti �rt�ke 1 lesz, a kritikus szakaszt pedig a P �s V elj�r�sok hat�rolj�k k�r�l.

P(v)
kritikus szakasz
V(v)
folyamat t�bbi r�sze

Megjegyezz�k, hogy a P �s V elj�r�s �s �ltat�ban a szinkroniz�l� elj�r�sok feloszthatatlanok (atomi műveletek).

A UNIX System V verzi�ban a szemafor fogalm�t �ltal�nos�tott�k. Ez�rt egy szemafor eset�ben egyidőben ak�r t�bb műveletet is megadhatunk (a P �s V elj�r�sok m�s-m�s időben h�v�dnak meg a folyamaton bel�l), �s az e(v) �rt�k�nek n�vel�se vagy cs�kkent�se nem felt�tlen�l 1-el kell t�rt�njen. Minden a rendszer �ltal v�grehajtott művelet feloszthatatlan. Teh�t ha a rendszer nem tudja elv�gezni a folyamat �ltal k�rt �sszes műveletet, nem v�gzi el egyiket sem, �s a folyamat v�rakoz�si �llapotba ker�l eg�szen az �sszes művelet v�grehajt�s�ig.

Egy folyamat l�trehozhat egy eg�sz szemafork�teget. A k�tegnek van egy bemenete a szemafort�bl�ban, amely a szemafork�teg fejl�c�t tartalmazza. A folyamathoz rendelt t�bl�zat pontosan annyi elemből �ll, amennyi szemafor tartozik a k�teghez. Minden elem megőrzi az illető szemaforhoz rendelt �rt�ket.

A szemaforok kezel�se nagyon hasonl�t az osztott mem�ria �s az �zenetsorok kezel�s�hez. Ez�rt egy folyamatnak csak akkor van joga hozz�f�rni egy szemaforhoz, ha ismeri a hozz�rendelt kulcsot. Belsőleg a szemafork�teget egy eg�sz sz�mmal azonos�tjuk, ez�rt a folyamat b�rmelyik szemaforhoz hozz�f�rhet 

Teh�t minden szemafork�tegnek van egy azonos�t�ja (amely egy pozit�v eg�sz sz�m) �s egy semid_ds t�pus� adatszerkezete.

struct semid_ds
{
  struct ipc_perm sem_perm;  /* defini�lja a jogokat �s a tulajdonost */
  struct sem *sem_base;      /* pointer az első szemaforra a k�tegből */
  int sem_nsens;             /* a k�tegben tal�lhat� szemaforok sz�ma */
  time_t sem_otime;          /* utols� semop() művelet ideje */
  time_t sem_ctime;          /* utols� strukt�ram�dos�t�s ideje */
};

Egy folyamat csak akkor f�rhet hozz� egy szemafork�teghez ha:

- a folyamat a superuser-�,

- a felhaszn�l� ID-je (uid) megegyezik az sem_perm.cuid-vel vagy az sem_perm.uid-vel �s az sem_perm.mode tartalmazza a k�v�nt jogokat,

- a felhaszn�l� csoportazonos�t�ja (gid) megegyezik az sem_perm.cgid vagy sem_perm.gid �rt�kek egyik�vel �s az sem_perm.mode tartalmazza a k�v�nt jogokat,

- a felhaszn�l� beleesik a "t�bbi felhszn�l�" kateg�ri�ba �s az sem_perm.mode tartalmazza a megfelelő jogokat.

Egy szemaforhoz rendelt adatszerkezet a k�vetkező:

struct sem
{
  ushort semval;    /* a szemafor �rt�ke (semval>=0) */
  pid_t sempid;     /* utols�, műveletet v�gző folyamat ID-ja */
  ushort semncnt;   /* azon foly. sz�ma, amelyek a semval n�veked�s�t v�rj�k */
  ushort semzcnt;   /* azon foly. sz�ma, amelyek a semval=0-t v�rj�k */
};

e�r�s: Le�r�s: Le�r�s: Le�r�s: Le�r�s: Le�r�s: Le�r�s: Le�r�s: Le�r�s: D:\!SO2\html\buttons\n_book.gif  Műveletek szemaforokkal

e�r�s: Le�r�s: Le�r�s: Le�r�s: Le�r�s: Le�r�s: Le�r�s: Le�r�s: Le�r�s: D:\!SO2\html\buttons\g_book.gif  L�trehoz�s (semget)

A semget rendszerf�ggv�ny lehetőv� teszi egy szemafork�teg ID-j�nak a meghat�roz�s�t. Ha a szemafork�teg előzőleg nem l�tezett, a f�ggv�ny l�trehozza azt. F�ggetlen�l att�l, hogy a k�teg l�tezett-e vagy sem a folyamatnak ismernie kell a szemaforhoz rendelt kulcsot. A f�ggv�ny alakja:

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>

int semget(key_t key, int nrsem, int flg);

A f�ggv�ny visszat�r�si �rt�ke az �jonnan l�trehozott vagy egy r�gi szemafor azonos�t�ja, illetve -1 hiba eset�n. A key v�ltoz�ban a szemaforhoz rendelt kulcsot kell megadni, m�g az flg-ben a l�trehoz�si tev�kenys�get �s a hozz�f�r�si jogokat. A kulcsot a szemafort haszn�l� �sszes folyamatnak ismernie kell. Az nrsem argumentum a k�tegben tal�lhat� szemaforok sz�m�t jelenti. Ha egy �j k�teget hozunk l�tre meg kell adnunk a v�ltoz� �rt�k�t, ha viszont egy m�r l�tező k�tegre hivatkozunk az nrsem �rt�ke 0 lesz.

Egy �j szemafork�teg l�trehoz�sa eset�n az flg mezőt a k�vetkező form�ban kell megadni:

IPC_CREAT  |  IPC_EXCL  |  hozz�f�r�si_jogok

Ha az IPC_EXCL nincs be�ll�tva, akkor ha m�r l�tezik egy előzőleg l�trehozott k�teg a megadott kulcsra, a program nem jelez hib�t, hanem visszaadja a l�tező k�teg ID-j�t.

P�lda egy szemafork�teg l�trehoz�s�ra:

#define KEY 2003

int semid;
semid = semget((key_t) KEY, 5, IPC_CREAT | 0666);

Ha csak a szemafork�teg azonos�t�j�ra vagyunk k�v�ncsiak, a semget h�v�sakor adjuk meg a kulcsot, a t�bbi param�ternek pedig 0 �rt�ket.

semid = semget((key_t) KEY, 0, 0);

L�trehoz�skor a t�rs�tott adatstrukt�ra (sem_perm) mezői a k�vetkező inform�ci�kkal t�ltődnek fel:

- sem_perm.cuid, sem_perm.uid – a semget f�ggv�nyt megh�v� folyamathoz hozz�rendelt felhaszn�l� ID-ja,
- sem_perm.cgid, sem_perm.uid – a semget f�ggv�nyt megh�v� folyamathoz hozz�rendelt felhaszn�l�csoport ID-ja,
- sem_perm.mode – a semget f�ggv�ny h�v�sakor megadott flg argumentum, amely a hozz�f�r�si jogokat tartalmazza,
- sem_nsems – a semget f�ggv�ny h�v�sakor megadott szemaforok sz�ma,
- sem_ctime – az aktu�lis időt tartalmazza,
- sem_otime – �rt�ke 0.

Előfordulhat, hogy egy szemafork�teghez nincs hozz�rendelt kulcs. Ebben az esetben a k�teg l�trehoz�sakor a semget f�ggv�ny key param�terek�nt az IPC_PRIVATE szimbolikus konstanst kell megadni.

e�r�s: Le�r�s: Le�r�s: Le�r�s: Le�r�s: Le�r�s: Le�r�s: Le�r�s: Le�r�s: D:\!SO2\html\buttons\g_book.gif  Szemafor adatainak lek�rdez�se, m�dos�t�sa �s t�rl�se (semctl)

A semctl f�ggv�ny a szemafork�tegek szintj�n az inform�ci�k lek�rdez�s�re, m�dos�t�s�ra �s t�rl�s�re haszn�lhat�. Szintaxisa:

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>

int semctl(int semid, int nrsem, int cmd, union semun arg);

A f�ggv�ny visszat�r�tett �rt�ke az �sszes GET parancs kimeneti �rt�ke, kiv�telt k�pez a GETALL parancs. Minden m�s esetben a f�ggv�ny �rt�ke 0.

A semid param�ter a semget f�ggv�ny �ltal meghat�rozott szemafork�teg azonos�t�ja, m�g az nrsem annak a szemafornak a sz�ma, amelyen v�gre szeretn�nk hajtani a cmd műveletet.

A cmd argumentum teh�t a k�v�nt műveletet hat�rozza meg �s a k�vetkező �rt�keket veheti fel:

- GETVAL – a f�ggv�ny visszat�r�ti a semval �rt�k�t az nrsem �ltal meghat�rozott szemaforban,

- SETVAL – az nrsem �ltal meghat�rozott szemafor semval param�ter�nek �rt�ke arg.val lesz,

- GETPID – a f�ggv�ny visszat�r�ti a sempid �rt�k�t az nrsem �ltal meghat�rozott szemaforban,

- GETNCNT – a f�ggv�ny visszat�r�ti a semncnt �rt�k�t az nrsem �ltal meghat�rozott szemaforban,

- GETZCNT – a f�ggv�ny visszat�r�ti a semzcnt �rt�k�t az nrsem �ltal meghat�rozott szemaforban,

- GETALL – minden szemafor semval �rt�k�t elhelyezi az arg.array t�mbben,

- SETALL – minden szemafor semval �rt�k�t felt�lti az arg.array t�mbben megadott �rt�kekkel,

- IPC_STAT – a semid_ds strukt�ra elemeit lementi az arg.buf t�mbbe,

- IPC_SET – a sem_perm.uid, a sem_perm.gid �s a sem_perm.mode mezők �rt�keit friss�ti az arg.buf t�mbben megadott �rt�kekkel,

- IPC_RMID – a szemafork�teg t�rl�se; a t�rl�s azonnali, teh�t minden ezt a szemafor haszn�l� folyamat egy EIDRM �zenetet kap, �s hib�val le�ll.

Az arg vari�ns t�pus� v�ltoz�, amely a cmd parancs �ltal felhaszn�lt argumentumokat tartalmazza:

union semun
{
  int val;                /* a SETVAL-hoz */
  struct semid_ds *buf;   /* az IPC_STAT-hoz �s az IPC_SET-hez */
  ushort *array;          /* a GETALL-hoz �s a SETALL-hoz */
}

e�r�s: Le�r�s: Le�r�s: Le�r�s: Le�r�s: Le�r�s: Le�r�s: Le�r�s: Le�r�s: D:\!SO2\html\buttons\g_book.gif  Szemafor �rt�k�nek n�vel�se �s cs�kkent�se (semop)

A semop f�ggv�ny feladata egy szemafork�teg egy elem�nek n�vel�se �s cs�kkent�se. Szintaxisa:

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>

int semop(int semid, struct sembuf op[], size_t nrop);

A f�ggv�ny visszat�r�si �rt�ke 0, ha a művelet sikeres volt, ellenkező esetben -1. A semid a semget �ltal meghat�rozott szemafork�teg azonos�t�ja.

Az op egy mutat� nrop darab sembuf t�pus� strukt�r�hoz, ahol:

struct sembuf
{
  ushort sem_num;  /* a k�tegben levő szemafor sorsz�ma */
  short sem_op;    /* v�grehajtani k�v�nt művelet */
  short sem_flg;   /* v�grehajt�si k�r�lm�nyek */
}

Teh�t minden szemafor eset�n a v�grehajtani k�v�nt műveletet a sem_op mező jelzi. Ha:

- sem_op < 0

a. Ha semval >= |sem_op|, akkor semval = semval - |sem_op|. Ez biztos�tja, hogy a szemafor �ltal visszat�r�tett �rt�k >= 0.

b. Ha (semval < |sem_op|) & (sem_flg & IPC_NOWAIT) = true, akkor a f�ggv�ny egy hibak�dot t�r�t vissza.

c. Ha semval < |sem_op| �s az IPC_NOWAIT nincs megadva, akkor a folyamat le�ll, am�g a k�vetkezők k�z�l valamely felt�tel nem teljes�l:

- semval >= |sem_op| (egy m�sik folyamat felszabad�t p�r erőforr�st),

- a szemafor t�rlődik a rendszerből; a f�ggv�ny ebben az esetben -1 �rt�ket t�r�t vissza �s errno=ERMID,

- ha egy folyamat egy jel lekezel�se ut�n visszat�r, a semncnt �rt�ke a szemaforban cs�kken, �s a f�ggv�ny -1-et ad vissza (errno=EINTR).

- sem_op > 0

Ekkor semval = semval + sem_op.

- sem_op = 0

a. Ha a semval = 0, akkor a f�ggv�ny azonnal befejeződik.

b. Ha a semval 0 �s az IPC_NOWAIT be van �ll�tva, akkor a f�ggv�ny -1-et ad vissza �s az errno=EAGAIN.

c. Ha a semval 0 �s az IPC_NOWAIT nincs be�ll�tva, akkor a folyamat le�ll, ameddig a semval 0 nem lesz, vagy a szemafork�teg megsemmis�l, vagy a folyamat egy jelet kap.

e�r�s: Le�r�s: Le�r�s: Le�r�s: Le�r�s: Le�r�s: Le�r�s: Le�r�s: Le�r�s: D:\!SO2\html\buttons\n_book.gif  P�ld�k(Let�lt�s)

A k�vetkezőkben megn�zz�k, hogyan lehet implement�lni a P �s V elj�r�sokat:

pv.c

static void semcall(int semid, int op)

{

struct sembuf pbuf;

pbuf.sem_num = 0;

pbuf.sem_op = op;

pbuf.sem_flg = 0;

 

if (semop(semid, &pbuf, 1) < 0){

������� perror("In semop()");

������� exit(1);

}

}

 

void P(int semid)

{

semcall(semid, -1);

}

 

void V(int semid)

{

semcall(semid, 1);
}

Az�rt, hogy a P �s a V elj�r�sok műk�d�s�t jobban meg�rts�k tekints�k a k�vetkező p�ld�t.

�rjunk folyamatot, amely h�rom gyereket hoz l�tre. Mindenik gyerek hozz� szeretne f�rni egy k�z�s erőforr�shoz. A kritikus szakasz 10 m�sodpercig tart. (A val�s�gban a kritikus szakasznak sokkal r�videbbnek kell lennie.) A szemafor biztos�tja minden folyamat egy�ni hozz�f�r�s�t a kritikus szakaszban. A tesztprogram a k�vetkező:

#include <stdlib.h>

#include <stdio.h>

#include <sys/types.h>

#include <sys/ipc.h>

#include <sys/sem.h>

#include "pv.c"���� /* a fent defini�lt P �s V elj�r�sok */

 

#define SEMPERM 0600����� /* hozz�f�r�si jogok */

 

void rut_sem(int semid);

int initsem(key_t semkey);

 

void main(void)

{

key_t semkey = 0x200;/* kulcs */

int semid, i;

semid = initsem(semkey);���� /* szemafor l�trehoz�sa */

 

for (i=0; i<3; i++)��� /* 3 darab gyerekfolyamat l�trehoz�sa */

������� if (fork() == 0)

������������� rut_sem(semid);�� /* erőforr�si k�relmek a gyerekfolyamatokt�l */

}

 

void rut_sem(int semid)/* szemaforok megval�s�t�sa */

{

pid_t pid;

pid = getpid();�� /* gyerekfolyamat PID-je */

 

P(semid);�� /* bel�p�s a kritikus szakaszba */

printf("a %d folyamat kritikus szakaszban van\n", pid);

 

sleep(random()%5);���� /* kritikus szakasz; v�rakoz�s */

 

printf("a %d folyamat elhagyja a kritikus szakaszt\n", pid);

V(semid);�� /* kil�p�s a kritikus szakaszb�l */

 

exit(0);��� /* gyerekfolyamat v�ge */

}

 

int initsem(key_t semkey)

{

int semid;/* szemafor l�trehoz�sa */

 

semid = semget(semkey, 1, SEMPERM | IPC_CREAT);

 

if (semctl(semid, 0, SETVAL, 1) < 0){

������� perror("In semctl()"); /* szemaforok sz�ma = 1 */

������� exit(1);

}

 

return semid;���� /* szemafor ID-j�nak visszat�r�t�se */

}

 

Makefile(Fedora disztrib�ci�):

 

shmtool: teszt.c

����� gcc teszt.c -o teszt

A k�vetkező tesztesetek is bizony�tj�k, hogy egy bizonyos időpillanatban csak egyetlen folyamat lehet a kritikus szakaszban.

$ a.out
a 790 folyamat kritikus szakaszban van
a 790 folyamat elhagyja a kritikus szakaszt
a 791 folyamat kritikus szakaszban van
a 791 folyamat elhagyja a kritikus szakaszt
a 792 folyamat kritikus szakaszban van
a 792 folyamat elhagyja a kritikus szakaszt

e�r�s: Le�r�s: Le�r�s: Le�r�s: Le�r�s: Le�r�s: Le�r�s: Le�r�s: Le�r�s: D:\!SO2\html\buttons\n_book.gif  POSIX kieg�sz�t�s

A posixos szemafor tipusa sem_t . A k�vetkezők�ppen jelentj�k be a sem_name nevű szemafort:

#include <semaphore.h>

sem_t sem_name;

e�r�s: Le�r�s: Le�r�s: Le�r�s: Le�r�s: Le�r�s: Le�r�s: Le�r�s: Le�r�s: D:\!SO2\html\buttons\g_book.gif  Szemafor �rt�k�nek inicializ�l�sa (sem_init)

#include <semaphore.h>

int sem_init( sem_t *sem, int pshared, unsigned value );

Argumentumok:���

       sem: Szemaforra mutat� pointer

       pshared: flag, ami mutatja, hogy fork eset�n megosztjuk-e a szemafort vagy nem. A Linux sz�lak egyelőre nem tudj�k kezelni

       value: erre az �rt�kre szeretn�nk be�ll�tani

P�lda sem_init –re:

��� sem_init(&sem_name, 0, 10); //sem_name szemafort be�ll�tja 10-re

e�r�s: Le�r�s: Le�r�s: Le�r�s: Le�r�s: Le�r�s: Le�r�s: Le�r�s: Le�r�s: D:\!SO2\html\buttons\g_book.gif  V�rakoz�s szemaforra (sem_wait)

A sem_wait f�ggv�ny seg�ts�g�vel v�rakozhatunk egy szemaforra.

Műk�d�se:

Ha a szemafor �rt�ke negat�v, akkor blokkolja a h�v� folyamatot, ellenkező esetben cs�kkenti a szemafor �rt�k�t.

Szintaxis:

int sem_wait(sem_t *sem);

P�lda:

sem_wait(&sem_name); //amennyiben a sem_name szemafor �rt�ke pozit�v, akkor cs�kkenti
�� �������������� ���// k�l�nben blokkolja a h�v� folyamatot.

e�r�s: Le�r�s: Le�r�s: Le�r�s: Le�r�s: Le�r�s: Le�r�s: Le�r�s: Le�r�s: D:\!SO2\html\buttons\g_book.gif  Szemafor �rt�k�nek n�vel�se (sem_post)

Műk�d�se:

N�veli a szemafor �rt�k�t (eggyel).

Amennyiben van a szemaforon blok�lt v�rakoz� folyamat, akkor ezek k�z�l egy aktiv�lva lesz.

Ha t�bb folyamat is v�rakozik a szemaforra, akkor az lesz �rtes�tve, amelyiknek a priorit�sa a legnagyobb a rendszerben.

Szintaxis:

#include <semaphore.h>
int sem_post( sem_t *sem );
���

P�ld�ul:

sem_post(&sem_name); //n�veli a sem_name szemafor �rt�k�t 1-el,

e�r�s: Le�r�s: Le�r�s: Le�r�s: Le�r�s: Le�r�s: Le�r�s: Le�r�s: Le�r�s: Le�r�s: D:\!SO2\html\buttons\g_book.gif  Szemafor �rt�k�nek cs�kkent�se blokkol�s n�lk�l (sem_trywait)

V�r egy szemaforra de nem blokkolja.

Ha a szemafor �rteke pozit�v akkor cs�kkenti, k�l�nben egyszerűen visszat�r (return). Ezzel pl. megvizsg�lhatjuk, hogy blok�l�dott-e volna a folyamat a szemafor �rt�k�t cs�kkentő művelet sor�n.

Szintaxis:

#include <semaphore.h>
int sem_trywait( sem_t *sem );

P�ld�ul:

sem_trywait(&sem_name);

e�r�s: Le�r�s: Le�r�s: Le�r�s: Le�r�s: Le�r�s: Le�r�s: Le�r�s: Le�r�s: Le�r�s: D:\!SO2\html\buttons\g_book.gif  Szemafor �rt�k�nek lek�rdez�se (sem_getvalue)

Lek�rdezi a szemafor �rt�k�t.

Szintaxis:

int sem_getvalue(sem_t *sem, int *valp);

Param�terez�s:

��� sem mutat� �ltal mutatott szemafor �rt�k�t lek�ri a valp mutat� �ltal mutatott int t�pus� v�toz�ba.

P�lda:

int value;
sem_t sem_name;
sem_getvalue(&sem_name, &value);
printf("A szemafor erteke %d\n", value);

e�r�s: Le�r�s: Le�r�s: Le�r�s: Le�r�s: Le�r�s: Le�r�s: Le�r�s: Le�r�s: Le�r�s: D:\!SO2\html\buttons\g_book.gif  Szemafor t�rl�se (sem_destroy)

A sem_destroy() t�rli a szemafort. Aj�nlatos csak akkor t�r�lni, ha m�r egyetlen folyamat sem haszn�lja az illető szemafort.

Szintaxis:

int sem_destroy(sem_t *sem); //kit�rli a sem mutat� �ltal mutatott szemafort

P�lda:

sem_destroy(&sem_name)

 

A szemaforok haszn�lat�nak klasszikus p�ld�ja a termelők-fogyaszt�k probl�m�ja,
ami a k�vetkezők�ppen implement�lhat� POSIX szemaforok seg�ts�g�vel: (Let�lt�s)

header.h

#include <stdio.h>

#include <unistd.h>

#include <string.h>

#include <stdlib.h>

#include <semaphore.h>

#include <fcntl.h>

#include <sys/mman.h>

 

#define BUFFER_SIZE 5

#define SHMOBJ_PATH��� "/tmp"

typedef struct

{

����� int buffer[BUFFER_SIZE]; //futoszalag

����� sem_t ures; //�res helyek sz�m�t jelző szemafor. kezdetben: BUFFER_SIZE

����� sem_t tele; //tele helyek sz�m�t jelző szemafor. kezdetben: 0.

����� sem_t pmut; //termelők mutex-e. Biztos�tja, hogy egyszerre csak egy folyamat termeljen.

����� sem_t cmut; //fogyaszt�k mutex-e. Biztos�tja, hogy egyszerre csak egy folyamat fogyasszon.

����� int nextin; //k�vetkező termelt adat helye

����� int nextout;����� //k�vetkező elfogyasztani k�v�nt adat poz�ci�ja

 

} osztottMemoriaTipus;

 

int lekerOsztottMemoriaID()

{

����� int shmfd = shm_open(SHMOBJ_PATH, O_RDWR, S_IRWXU | S_IRWXG);

��� //ha m�r van ilyen key kulcs� osztott mem�riater�let l�trehozva

��� if (shmfd == -1){

��� ������� shmfd = shm_open(SHMOBJ_PATH, O_CREAT | O_EXCL | O_RDWR, S_IRWXU | S_IRWXG);

��� ������� if (shmfd < 0) {

��� ������������� perror("In shm_open()");

������� ��������� exit(1);

��� ������� }

�����������

����������� /* adjusting mapped file size (make room for the whole segment to map) --ftruncate() */

����������� ftruncate(shmfd, sizeof(osztottMemoriaTipus));

����� }

return shmfd;

}

 

void initSzemaforok(osztottMemoriaTipus* p)

{

����� if(sem_init(&(p->ures),1,BUFFER_SIZE) < 0 ){

����������� perror("In sem_init()");

����������� exit(1);���

����� }

����� if(sem_init(&(p->tele),1,0) < 0){

����������� perror("In sem_init()");

����������� exit(1);

����� }

����� if(sem_init(&(p->pmut),1,1) < 0){

����������� perror("In sem_init()");

����������� exit(1);

����� }

����� if(sem_init(&(p->cmut),1,1) < 0){

����������� perror("In sem_init()");

����������� exit(1);

����� }

����� p->nextin = p->nextout = 0;

}

 

termelo.c

#include "header.h"

 

void initOsztottMemoria(osztottMemoriaTipus* p)

{

����� //lenull�zzuk a puffert (le�r�tj�k a fut�szalagot)

����� int i = 0;

 

����� for(i=0; i< BUFFER_SIZE; ++i){

����������� p->buffer[i] = 0;

����� }

}

void termel(osztottMemoriaTipus* p)

{

����� //a termelo elkezdi pakolni a termekeket a futoszalagra

����� int item = -1;

 

����� sem_wait(&(p->ures));

����� sem_wait(&(p->pmut));

 

����� item = rand()%10 + 1;

����� printf("%d\n",item);

����� p->buffer[p->nextin] = item;

����� p->nextin++;

����� p->nextin %= BUFFER_SIZE;

����� sem_post(&(p->pmut));

����� sem_post(&(p->tele));

}

 

int main()

{

����� int shmfd = lekerOsztottMemoriaID();

����� int t;

����� srand(getpid());

����� osztottMemoriaTipus * p;

����� int shared_seg_size = sizeof(osztottMemoriaTipus);

����� /* requesting the shared segment --mmap() */���

����� p = (osztottMemoriaTipus *)mmap(NULL, shared_seg_size, PROT_READ | PROT_WRITE, MAP_SHARED, shmfd, 0);

����� if (p == NULL) {

����������� perror("In mmap()");

����� ������� exit(1);

����� }

����� initOsztottMemoria(p);

����� initSzemaforok(p);

 

����� for(t=0; t<20; t++){

����������� termel(p);

����� }

 

����� return 0;

}

 

 

fogyaszto.c

#include "header.h"

void fogyaszt(osztottMemoriaTipus* p)

{

����� //a fogyaszto elkezdi levenni a termekeket a futoszalagrol

����� int item;

 

���� sem_wait(&(p->tele));

����� sem_wait(&(p->cmut));

 

����� item = p->buffer[p->nextout];

����� printf("%d\n",item);

����� p->nextout++;

����� p->nextout %= BUFFER_SIZE;

 

����� sem_post(&(p->cmut));

����� sem_post(&(p->ures));

}

 

int main()

{

����� int shmfd = lekerOsztottMemoriaID();

����� int t = 0;

����� osztottMemoriaTipus * p;

����� int shared_seg_size = sizeof(osztottMemoriaTipus);

����� /* requesting the shared segment --mmap() */���

����� p = (osztottMemoriaTipus *)mmap(NULL, shared_seg_size, PROT_READ | PROT_WRITE, MAP_SHARED, shmfd, 0);

����� if (p == NULL) {

����� ���� perror("In mmap()");

����� ������� exit(1);

����� }

����� for(t=0;t<20;++t){

����������� fogyaszt(p);��

}

if (shm_unlink(SHMOBJ_PATH) != 0){

������� perror("In shm_unlink(SHMOBJ_PATH)");

������� exit(1);

}

 

return 0;

}

 

Makefile(Fedora disztrib�ci�):

all: termelo fogyaszto
termelo: termelo.c
����� gcc termelo.c –pthread -lrt -o t
fogyaszto: fogyaszto.c
����� gcc fogyaszto.c –pthread -lrt -o f
clean: rm f t
.PHONY: all clean

A szemaforok haszn�lat�nak klasszikus p�ld�ja a termelők-fogyaszt�k probl�m�ja,
ami a k�vetkezők�ppen implement�lhat� n�vvel ell�tott POSIX szemaforok seg�ts�g�vel: (Let�lt�s)

szemaforNevvel.cpp

/*

Szemaforok �s osztott mem�ria -Nevvel ellatott szemafor

A termelő/fogyaszt� probl�m�ja:

A termelő fogyaszt�si cikkeket termel, melyeket elhelyez egy fut�szalagon (v�ges puffer). A fogyaszt� sorban leveszi a szalagr�l a term�keket �s elfogyasztja őket.

Forditani: gcc szemaforNevvel.cpp -pthread -lrt

*/

 

#include <stdlib.h>

#include <stdio.h>

#include <string.h>

#include <unistd.h>

#include <fcntl.h>

#include <sys/mman.h>

#include <semaphore.h>

 

#define SHMOBJ_PATH��� "/tmp"

 

struct msg_s {

����� int t[10];

����� char name_gyVf[10];

����� char name_termekek[10];

����� char name_tele[10];

};

 

int main(int argc, char *argv[]) {

�����

����� sem_t * sem_gyVf; //gyarthatunk-e v fogyaszthatunk-e

����� sem_t * sem_termekek; //varakozo termekek

����� sem_t * sem_tele; //tele van-e

 

����� srandom(getpid());

����� int myIndex;

����� myIndex = 2; //2 ha fogyaszto

�����

����� struct msg_s *shared_msg; /* the shared segment, and head of the messages list */

����� int shmfd;

��� int shared_seg_size = sizeof(struct msg_s);

���

����� shmfd = shm_open(SHMOBJ_PATH, O_RDWR, S_IRWXU | S_IRWXG);

��� if (shmfd < 0) {

�����������

����������� myIndex = 1; //1 ha termelo

������� ��� /* creating the shared memory object��� --shm_open()*/

��� ������� shmfd = shm_open(SHMOBJ_PATH, O_CREAT | O_EXCL | O_RDWR, S_IRWXU | S_IRWXG);

��� ������� if (shmfd < 0) {

������� ��������� perror("In shm_open()");

������� ��������� exit(1);

��� ������� }

�����������

����������� /* adjusting mapped file size (make room for the whole segment to map) --ftruncate() */

��� ������� ftruncate(shmfd, shared_seg_size);

��� }

 

����� /* requesting the shared segment --mmap() */���

��� shared_msg = (struct msg_s *)mmap(NULL, shared_seg_size, PROT_READ | PROT_WRITE, MAP_SHARED, shmfd, 0);

��� if (shared_msg == NULL) {

������� ��� perror("In mmap()");

������� ��� exit(1);

��� }

 

����� if(myIndex == 1){

����� //termelo

����������� printf("Termelo elindult.\n");

����������� //meghatarozza a szemaforok nevet

����������� strcpy(shared_msg->name_gyVf, "gyVf");

����������� strcpy(shared_msg->name_termekek, "termekek");

����������� strcpy(shared_msg->name_tele, "tele");

����������� //letrehozza a szemaforokat a megadott nevvel

����������� sem_gyVf = sem_open(shared_msg->name_gyVf, O_CREAT, S_IRUSR | S_IWUSR, 1);

����������� if(sem_gyVf == SEM_FAILED){

����������������� perror("In sem_open(sem_gyVf)");

������� ��������� exit(1);

����������� }

����������� sem_termekek = sem_open(shared_msg->name_termekek, O_CREAT, S_IRUSR | S_IWUSR, 0);

����������� if(sem_termekek == SEM_FAILED){

����������������� perror("In sem_open(sem_termekek)");

������� ��������� exit(1);

����������� }

����������� sem_tele = sem_open(shared_msg->name_tele, O_CREAT, S_IRUSR | S_IWUSR, 3);

����������� if(sem_tele == SEM_FAILED){

����������������� perror("In sem_open(sem_tele)");

������� ��������� exit(1);

����������� }

 

����������� //"uriti a futoszalagot"

����������� for(int i=0; i < 4; i++){

����������������� shared_msg->t[i] = 0;�������

����������� }����������

�����

����������� //felrakja a termekeket a "futoszalagra"

����������� int x;

����������� for(int i=0; i < 10; i++){

����������������� sem_wait(sem_tele);

����������������� sem_wait(sem_gyVf);

����������������� sem_getvalue(sem_termekek, &x);

����������������� shared_msg->t[x] = i;

����������������� printf("%d. termek legyartva!\n", i);

����������������� sem_post(sem_termekek);

����������������� sem_post(sem_gyVf);���

����������������� //alszik randomra, hogy valtozatosabb legyen a megoldas

����������������� double t = random() % 30 / 10;

����������������� sleep(t);

����������� }����������������

����� }

����� else{

����� //fogyaszto

����������� printf("Fogyaszto elindult.\n");

����������� //megnyitja a szemaforokat

����������� sem_gyVf = sem_open(shared_msg->name_gyVf, 0);

����������� if(sem_gyVf == SEM_FAILED){

����������������� perror("In sem_open(sem_gyVf)");

������� ��������� exit(1);

����������� }

����������� sem_termekek = sem_open(shared_msg->name_termekek, 0);

����������� if(sem_termekek == SEM_FAILED){

����������������� perror("In sem_open(sem_termekek)");

������� ��������� exit(1);

����������� }

����������� sem_tele = sem_open(shared_msg->name_tele, 0);

����������� if(sem_tele == SEM_FAILED){

����������������� perror("In sem_open(sem_tele)");

������� ��������� exit(1);

����������� }

����������� //leszedi a termekeket

����������� int x;

����������� for(int i=0; i < 10; i++){

����������������� sem_wait(sem_termekek);

����������������� sem_wait(sem_gyVf);

����������������� printf("%d. termek elfogyasztva!\n", shared_msg->t[0]);

����������������� for(int j = 0; j < 3; j++)

���������������������� shared_msg->t[j] = shared_msg->t[j+1];

����������������� sem_post(sem_tele);

����������������� sem_post(sem_gyVf);

����������������� //alszik o is randomra, hogy minden futtatasnal kicsit maskepp mukodjon

����������������� double t = random() % 30 / 10;

����������������� sleep(t);

����������� }����

����� }

 

����� if(myIndex == 2)

����� {

����������� //a fogyaszto zarja be a szemaforokat

����������� if (sem_unlink(shared_msg->name_gyVf) != 0)

����������� {

������� ��������� perror("In sem_unlink(shared_msg->sem_gyVf)");

������� ��������� exit(1);

��� ������� }

����������� if (sem_unlink(shared_msg->name_termekek) != 0)

����������� {

������� ��������� perror("In sem_unlink(shared_msg->sem_termekek)");

������� ��������� exit(1);

��� ������� }

����������� if (sem_unlink(shared_msg->name_tele) != 0)

����������� {

������� ��������� perror("In sem_unlink(shared_msg->sem_tele)");

������� ��������� exit(1);

��� ������� }

����������� //es torli az osztott memoriat

��� ������� if (shm_unlink(SHMOBJ_PATH) != 0)

����������� {

������� ��������� perror("In shm_unlink(SHMOBJ_PATH)");

������� ��������� exit(1);

��� ������� }����

����� }

�����

����� return 0;

}

 

Makefile(Fedora disztrib�ci�):

termelo: szemaforNevvel.cpp

����� gcc szemaforNevvel.cpp -pthread -lrt -o sz



e�r�s: Le�r�s: Le�r�s: Le�r�s: Le�r�s: Le�r�s: Le�r�s: Le�r�s: Le�r�s: D:\!SO2\html\buttons\n_link_n.gif  Osztott mem�ria (shared memory)

 

 


 

Copyright (C) Buzog�ny L�szl�, 2002

e�r�s: Le�r�s: Le�r�s: Le�r�s: Le�r�s: Le�r�s: Le�r�s: Le�r�s: Le�r�s: D:\!SO2\html\art\simple.gif

About