Pobieranie prezentacji. Proszę czekać

Pobieranie prezentacji. Proszę czekać

Zaawansowana obsługa sygnałów

Podobne prezentacje


Prezentacja na temat: "Zaawansowana obsługa sygnałów"— Zapis prezentacji:

1 Zaawansowana obsługa sygnałów
#include <signal.h> int sigaction(...) Podstawowy efekt działania tej funkcji jest podobny jak funkcji signal() – definiuje jak przychodzący sygnał powinien zostać obsłużony; sigaction oferuje jednak znacznie wiecej możliwości poprzez możliwość wyspecyfikowania dodatkowych flag (znaczników) kontrolnych. Użycie sigaction jest znacznie bardziej skomplikowane.

2 Tworzenie zbioru sygnałów ”signal set”
Wszystkie blokujące sygnały funkcje używają struktury danych nazwanej signal set w celu wyspecyfikowania o które sygnały chodzi. Używanie tych funkcji jest dwustopniowe: najpierw tworzy się ”signal set”, następnie przesyła się go jako argument do odpowiedniej funkcji (bibliotecznej). #include <signal.h> sigset_t Ten powyższy typ danych reprezentuje ”signal set”. W danej wersji języka C może być zaimplementowany jako typ int lub jako struktura. Dla celów przenaszalności (”portability of code”) należy inicjalizować, zmieniać, odzyskiwać informację ze zmiennych typu sigset_t wyłącznie przy użyciu przedstawionych poniżej funkcji.

3 ”signal set” Są dwa sposoby zainicjalizowania zbioru sygnałów. Można rozpocząć od sigemptyset(), to określa pusty zbiór sygnałów, a następnie dodawać poszczególne sygnały przez sigaddset() . Inny sposób to zainicjowanie zbioru sygnałów pełnym zbiorem istniejących możliwych sygnałów przez sigfillset() a następnie usuwanie poszczególnych sygnałow przez sigdelset() . Wysoce zalecane jest wybranie jednej z tych dwóch możliwości!

4 ”signal set” int sigemptyset (sigset_t *set)
Incjalizuje zbiór sygnałów (pusty). Zawsze zwraca zero. int sigfillset (sigset_t *set) Inicjalizuje zbiór sygnałów (pełny). Zawsze zwraca zero. int sigaddset (sigset_t *set, int signum) Dodaje sygnał signum do zbioru sygnałów. Zwraca zero w przypadku sukcesu oraz –1 w przypadku niepowodzenia. int sigdelset (sigset_t *set, int signum) Usuwa sygnał signum ze zbioru sygnałów. Zwraca zero w przypadku sukcesu oraz –1 w przypadku niepowodzenia. int sigismember (const sigset_t *set, int signum) Sprawdza czy sygnał signum jest zawarty w zbiorze sygnałów. Zwraca 1 jeżęli sygnał jest w zbiorze sygnałow, 0 jeśli go nie ma, -1 jeśli był błąd.

5 ”signal set” int sigemptyset (sigset_t *set)
Incjalizuje zbiór sygnałów (pusty). Zawsze zwraca zero. int sigfillset (sigset_t *set) Inicjalizuje zbiór sygnałów (pełny). Zawsze zwraca zero. int sigaddset (sigset_t *set, int signum) Dodaje sygnał signum do zbioru sygnałów. Zwraca zero w przypadku sukcesu oraz –1 w przypadku niepowodzenia. int sigdelset (sigset_t *set, int signum) Usuwa sygnał signum ze zbioru sygnałów. Zwraca zero w przypadku sukcesu oraz –1 w przypadku niepowodzenia. int sigismember (const sigset_t *set, int signum) Sprawdza czy sygnał signum jest zawarty w zbiorze sygnałów. Zwraca 1 jeżęli sygnał jest w zbiorze sygnałow, 0 jeśli go nie ma, -1 jeśli był błąd.

6 ”signal set” int sigprocmask (int how, sigset_t * set, sigset_t * oldset) funkcja ta służy do zmiany maski sygnałów w danym procesie lub uzyskania informacji jaka jast ta maska. Argument how wybiera, jak funkcja działa. Możliwe wartości how : SIG_BLOCK Blokuj sygnały które są w set -- dodaj je do istniejącej maski. In other words, the new mask is the union of the existing mask and set. SIG_UNBLOCK Odblokuj sygnały które są w set – usuń je z istniejącej maski. SIG_SETMASK Sygnały z set tworzą nową maskę; ignore the previous value of the mask. (jeśli set jest NULL, maska procesu nie zostanie zmieniona, jedynie zostanie załadowany oldset informacją o bieżącej masce procesu.

7 ”signal set”: przykład programu
#include <stdio.h> #include <stdlib.h> #include <signal.h> void sigcont(); main() { int pid; int n; if ((pid = fork()) < 0) { perror("fork"); exit(1); }

8 ”signal set”: przykład programu
if (pid == 0) /* potomek */ { sigset_t tempset; sigfillset(&tempset); sigdelset(&tempset,SIGCONT); /* sygnalu SIGCONT nie ma w masce */ signal(SIGCONT, sigcont); for(n=1;;++n) /* wieczna pętla */ { printf("\n child: %d\n",getpid()); sleep(1); if(n==3) sigsuspend(&tempset); }

9 ”signal set”: przykład programu
else /* parent */ { /* pid zawiera ID potomka */ sleep(6); printf("\nPARENT: wysyla sygnal SIGCONT\n\n\n"); kill(pid,SIGCONT); /* uruchomienie */ sleep(7); } }/* koniec main */ void sigcont() { printf("\n potomek: byl sygnal SIGCONT\n"); }/* koniec funkcji sigcont */

10 sygnały: blokowanie a ignorowanie
na czym polega różnica pomiędzy blokowaniem sygnału a ignorowaniem sygnału?

11 ”shared memory” ”Pamięć (współ)dzielona” jest efektywna metodą przesyłania informacji pomiędzy programami/procesami. Jeden proces tworzy porcję takiej pamięci, którą następnie inne procesy (jeśli kod dostępu na to zezwala) mogą dołączać, także w sposób asynchroniczny. Pamięć taka istnieje od momentu utworzenia do jej zlikwidowania, jej zawartość pozostaje niezmieniona aż do (zamierzonej) modyfikacji

12 IPC – Shared Memory /* tworzenie pamięci współdzielonej lub uzyskiwanie identyfikatora do istniejącej pamięci współdzielonej */ #include <sys/shm.h> int shmget(key_t key, size_t size, int shmflg); pamięć ta jest rozpoznawana poprzez nadany jej klucz; size to jej wielkość w bajtach; shmflg specyfikuje kod dostępu i w przypadku tworzenia dodatkowe flagi kontrolne argument size jest wielkością w bajtach pamięci współdzielonej (”shared memory”) argument shmflg określa (w przypadku tworzenia) kod dostępu oraz znaczniki kontrolne (”creation control flags”)

13 IPC – Shared Memory /* tworzenie pamięci współdzielonej lub uzyskiwanie identyfikatora do istniejącej pamięci współdzielonej */ #include <sys/shm.h> int shmget(key_t key, size_t size, int shmflg); argument shmflg określa (w przypadku tworzenia) kod dostępu oraz znaczniki kontrolne (”creation control flags”) przykład: shmget(klucz, 1024 , IPC_CREAT | 0666);

14 IPC – Shared Memory int shmctl(int shmid, int cmd, struct shmid_ds *buf); służy do różnych operacji na pamięci współdzielonej, np.. zmiana użytkownika, grupy, kodu dostępu, odczytanie informacji o ilości procesów dołączonych do danej pamięci współdzielonej itp.

15 IPC – Shared Memory int shmctl(int shmid, int cmd, struct shmid_ds *buf); argument cmd może mieć wartość: SHM_LOCK – wymuszenie zakleszczenia w pamięci operacyjnej (root) SHM_UNLOCK – koniec wymuszenia (”unlock”) (root) IPC_STAT – zwróć informację o danej ”shared memory” i umieść ją w obiekcie wskazywanym przez buf IPC_SET – zmień właściciela, grupę, prawa dostępu do ”shared memory” IPC_RMID – usuń dany ”shared memory segment”

16 IPC – Shared Memory #include <sys/shm.h>
int shmctl(int shmid, int cmd, struct shmid_ds *buf); /* uwaga: struct shmid_ds. jest zdefiniowana w <sys/shm.h> */

17 IPC – Shared Memory struct shmid_ds ma następujące elementy:
size_t shm_segsz; /* długość w bajtach */ time_t shm_atime; /* czas ostatniego shmat() */ unsigned long int __unused1; time_t shm_dtime; /* czas ostatniego shmdt() */ unsigned long int __unused2; time_t shm_ctime; /* czas ostatniej modyfikacji shmctl() */ unsigned long int __unused3; pid_t shm_cpid; /* pid procesu-twórcy*/ pid_t shm_lpid; /* pid ostatniego procesu */ shmatt_t shm_nattch; /* liczba dołączonych procesów */

18 IPC – Shared Memory int shmctl(int shmid, int cmd, struct shmid_ds *buf); /* przykładowe użycie */ #include <sys/types.h> #include <sys/ipc.h> #include <sys/shm.h> ... int cmd; /* command code for shmctl() */ int shmid; /* segment ID */ struct shmid_ds buf; /* shared memory data structure to hold results */ shmid = ... ; cmd = ... ; if (shmctl(shmid, cmd, &buf) == -1) { perror("shmctl: shmctl failed"); exit(1); } ...

19 IPC – Shared Memory shmat() oraz shmdt() są używane do dołączenia i odłączenia danej pamięci współdzielonej (”attach and detach of shared memory segment”) void *shmat(int shmid, const void *shmaddr, int shmflg); int shmdt(const void *shmaddr); shmat() zwraca wskaźnik do początku danego segmentu pamięci współdzielonej shmdt() odłącza dany segment pamięci współdzielonej wskazany przez wskaźnik shmaddr (dany process może dołączyć jednocześnie więcej niż jeden ”shared memory segment”, może je odłączyć przed swoim zakończeniem)

20 IPC – Shared Memory (przykład)
#include <stdio.h> #include <stdlib.h> #include <signal.h> #include <sys/ipc.h> #include <sys/shm.h> #include <sys/wait.h>

21 IPC – Shared Memory (przykład)
int main () { /* dwa procesy korzystają z ”shared memory” */ key_t klucz; int n,l; /* uruchomienie procesu potomnego */ n=fork(); /* od teraz są dwa procesy */ klucz=16*5+2; /* czyli 0x52 */ if(n==0) sleep(6); /* spi proces potomny */ printf("\n getpid()=%d n=%d\n", getpid(), n);

22 IPC – Shared Memory (przykład)
if(n!=0) /* to rodzic */ {int shmid; char * wsk, * wsk2; char c; int status; shmid=shmget(klucz, 1024 , IPC_CREAT | 0666); printf("\n shmid=%d\n",shmid); wsk=shmat(shmid,NULL,0); printf("\n wsk=%p jesli wsk=-1 to nie udalo sie dolaczyc\n",wsk); wsk2=wsk;

23 IPC – Shared Memory (przykład)
for (c = 'a'; c <= 'z'; c++) *(wsk2++) = c; *wsk2 = 0; waitpid(n, &status,0); printf("\nRodzic %d\n", WEXITSTATUS(status) ); /* makro WEXITSTATUS( ) było na poprzednim wykładzie */ }

24 IPC – Shared Memory (przykład)
if(n==0) /* to jest w procesie potomnym */ { struct shmid_ds buf; int shmid; char * shm, *shm2; /* ponizej lokalizowanie segmentu shared memory */ shmid=shmget(klucz,1024 ,0666);/* odzyskanie identyfikatora */ shm=shmat(shmid,NULL,0);

25 IPC – Shared Memory (przykład)
for (shm2 = shm; *shm2 != 0; shm2++) putchar(*shm2); putchar('\n'); /* * teraz zmien poczatkowy znak segmentu * na znak ze przeczytany zostal segment */ *shm = '*';

26 IPC – Shared Memory (przykład)
/* i odczytaj raz jeszcze ten sam segment ”shared memory” */ for (shm2 = shm; *shm2 != 0; shm2++) putchar(*shm2); putchar('\n'); shmctl(shmid, IPC_STAT, &buf); printf("\n liczba attach. %d\n", buf.shm_nattch); printf("\n dlugosc segmentu %d\n", buf.shm_segsz);

27 IPC – Shared Memory (przykład)
//shmctl(shmid, IPC_RMID, &buf); //printf("\n liczba attach. %d\n", buf.shm_nattch); //printf("\n dlugosc segmentu %d\n", buf.shm_segsz); putchar(*shm); putchar('\n'); exit( 10); } /* koniec procesu potomnego */ exit(0); }/* koniec funkcji main */

28 UNIX: komenda ipcs man ipcs – tak można uzyskać opis po wykonaniu ipcs otrzymujemy Shared Memory Segments key shmid owner perms bytes nattch x rudy Semaphore Arrays key semid owner perms nsems status Message Queues key msqid owner perms used-bytes messages

29 UNIX: komenda ipcrm man ipcrm– tak można uzyskać opis (służy do usuwania obiektów o których informacji udziela ipcs) ipcrm shm shmid ipcrm sem semid ipcrm msg msgid ”shared memory”

30 przykład:”shared memory” i sygnały
/* w przedstawionym przykladzie zostanie wykonany fork(), po czym program nadrzedny zapisze cos do utworzonego obszaru pamięci (współ)dzielonej; następnie program nadrzędny sam siebie zatrzyma wysyłając do siebie sygnał SIGSTOP; proces potomny odczyta dane z obszaru pamięci (współ)dzielonej, wypisze je na stdout, wyśle sygnał SIGCONT do procesu nadrzednego */

31 przykład:”shared memory” i sygnały
#include <stdio.h> #include <stdlib.h> #include <signal.h> #include <sys/ipc.h> #include <sys/shm.h> #include <sys/wait.h> # include <sys/types.h> /* takze do ftok */ int main ()

32 przykład:”shared memory” i sygnały
{ key_t klucz; int n,l; /* uruchomienie procesu potomnego */ n=fork(); /* produkcja klucza z użyciem funkcji ftok() */ klucz=ftok(".", 110); printf("\n pid=%d klucz=%d klucz=%x\n\n",getpid(), klucz,klucz); if(n==0) sleep(6); /* spi proces potomny */ printf("\n getpid()=%d n=%d\n", getpid(), n);

33 przykład:”shared memory” i sygnały
if(n!=0) /* to rodzic */ { int i,k,var; char * wsk, * wsk2; int status; k=shmget(klucz, 1024 , IPC_CREAT | 0666); printf("\n rodzic shmget() zwrocilo k=%d\n",k); wsk=shmat(k,NULL,0); printf("\n rodzic wsk=%p jesli wsk=NULL to nie udalo sie dolaczyc\n",wsk); wsk2=wsk;

34 przykład:”shared memory” i sygnały
for (i = 1; i<=100;++i) { var=i; memcpy(wsk2,&var,4); /* kopiowanie danych do ”shared memory” */ wsk2+=4; } *wsk2 = 0; printf("\n zaraz rodzic wykona dla siebie SIGSTOP\n"); raise(SIGSTOP); /* proces sam siebie zatrzymuje, obsługuje ten sygnał system operacyjny */ printf("\nRodzic obudzil sie...\n"); exit(0); } /* proces nadrzedny zakonczony */

35 przykład:”shared memory” i sygnały
if(n==0) /* to jest w procesie potomnym */ { struct shmid_ds buf; /* wykorzysta buf funkcja shmctl() */ int i,k,n; char * shm, *shm2; /* ponizej lokalizowanie segmentu shared memory */ k=shmget(klucz,1024 ,0666); printf("\n potomek shmget() zwrocilo %d\n",k); /* k to shared memory id inaczej shmid */ shm=shmat(k,NULL,0); printf("\n potomek shmat() zwrocilo %p\n",shm); shm2=shm;

36 przykład:”shared memory” i sygnały
for (i=1;i<=100;++i) { memcpy(&n,shm2,4); /* czytanie z ”shared memory” */ printf(" potomek n=%d",n); shm2+=4; } sleep(4); printf("\n zaraz potomek wykona kill(getppid(),SIGCONT)\n"); kill(getppid(),SIGCONT); printf("\n");

37 przykład:”shared memory” i sygnały
/* k to shared memory id inaczej shmid */ shmctl(k, IPC_STAT, &buf); printf("\n liczba attach. %d\n", buf.shm_nattch); printf("\n dlugosc segmentu %d\n", buf.shm_segsz); // shmctl(k, IPC_RMID, &buf); /*może uaktywnić ? */ exit( 10); } /* koniec procesu potomnego */ }/* koniec funkcji main */

38 funkcja ftok() # include <sys/types.h> # include <sys/ipc.h> key_t ftok(const char *pathname, int proj_id); ftok() tworzy klucz, wyliczając go na podstawie podanego adresu jakiegoś pliku (kartoteki) oraz dodatkowej wartości typu int; utworzony klucz jest niepowtarzalny

39 ”Message Queues” czyli kolejki wiadomości
Dwa czy wiecej procesów mogą wymieniać informację poprzez dostęp do wspólnego system. Użytkownik może stworzyć więcej niż jedną kolejkę wiadomości. W ramach jednej kolejki, wiadomości maja dodatkowy atrybut mtype; proces nawiązujący kontakt z istniejącą kolejką wiadomości wybiera, wiadomości o jakim mtype chce przeczytać. Przeczytanie wiadomości usuwa ją z kolejki wiadomości. Kolejka wiadomości pełni rolę skrzynki pocztowej, do której zapisują wiadomości jakieś upoważnione procesy, a z kolei inne procesy mają możliwość odczytania ich. Odczytanie jest asynchroniczne.

40 Message Queues #include <sys/ipc.h>; #include <sys/msg.h>; int msgget(key_t key, int msgflg) funkcja ta inicjalizuje nową kolejkę wiadomości (jeśli kolejka nie istnieje) i zwraca jej identyfikator msqid msqid = msgget(key, IPC_CREAT | ) ; (flaga IPC_EXCL – msgget() padnie jeśli kolejka już istniała) Procesy które zgłaszają zamiar skorzystania z IPC (InterProcessCalls) muszą zlokalizować odpowiedni zasób – lokalizują go poprzez argument key (typu key_t, tożsamy z typem int); klucz ten można wygenerowac uzywając ftok()

41 Message Queues msqid = msgget(ftok("/tmp", key), (IPC_CREAT | IPC_EXCL | 0400)); /* utworzy nową kolejkę, pod warunkiem że ona nie istnieje */

42 Message Queues - przesyłanie i odbieranie
int msgsnd(int msqid, void *msgp, size_t msgsz, int msgflg); int msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg); Argument msqid musi być identyfikatorem (deskryptorem) istniejącej kolejki wiadomości. msgp jest wskaźnikiem do struktury opisującej typ wiadomości i jej tekst. Poniżej jest przykład jak taka struktura może wyglądać: struct mymsg { long mtype; /* typ wiadomości */ char mtext[MSGSZ]; /* MSGSZ to długość wiadomości w bajtach */ } argument msgsz określa długość wiadomości w bajtach msgtyp to typ odbieranej wiadomosci (równy ) msgflg to znacznik, np. IPC_NOWAIT

43 Message Queues – przykład tworzenia, przesyłania
#include <sys/types.h> #include <sys/ipc.h> #include <sys/msg.h> #include <stdio.h> #include <string.h> #define MSGSZ

44 Message Queues – przykład tworzenia, przesyłania
/* * deklaracja struktury wiadomości */ typedef struct msgbuf { long mtype; char mtext[MSGSZ]; } message_buf;

45 Message Queues – przykład tworzenia, przesyłania
main() { int msqid; int msgflg = IPC_CREAT | 0666; key_t key; message_buf sbuf; size_t buf_length; /* klucz wybrany ręcznie, nie użyto ftok() */ key = 1234;

46 Message Queues – przykład tworzenia, przesyłania
if ((msqid = msgget(key, msgflg )) < 0) { perror("msgget"); exit(1); } else fprintf(stderr,"msgget: msgget sukces: msqid = %d\n", msqid); perror("msgget"); exit(1); } else /* typ wiadomości 1 */ sbuf.mtype = 1;

47 Message Queues – przykład tworzenia, przesyłania
strcpy(sbuf.mtext, ”Oto przesylana wiadomosc o typie 1"); buf_length = strlen(sbuf.mtext) + 1 ; /* wysyłanie wiadomości */ if (msgsnd(msqid, &sbuf, buf_length, IPC_NOWAIT) < 0) { printf ("%d, %d, %s, %d\n", msqid, sbuf.mtype, sbuf.mtext, buf_length); perror("msgsnd"); exit(1); }

48 Message Queues – przykład tworzenia, przesyłania
else printf(\nWiadomosc: %s\n wyslana!\n", sbuf.mtext); exit(0); } /* koniec funkcji main */

49 Message Queues – przykład odebrania
#include <sys/types.h> #include <sys/ipc.h> #include <sys/msg.h> #include <stdio.h> #define MSGSZ typedef struct msgbuf { /* deklaracja budowy wiadomości */ long mtype; char mtext[MSGSZ]; } message_buf;

50 Message Queues – przykład odebrania
main() { int msqid; key_t key; message_buf rbuf; key = 1234; /* wybrany klucz identyfikujący kolejke wiadomości /* if ((msqid = msgget(key, 0666)) < 0) { perror("msgget"); exit(1); }

51 Message Queues – przykład odebrania
/* Odbierz wiadomość typu */ if (msgrcv(msqid, &rbuf, MSGSZ, 1, 0) < 0) { perror("msgrcv"); exit(1); } /* wypisz tą wiadomość */ printf("%s\n", rbuf.mtext); exit(0); } /* koniec main */ /* czy można przesyłać ”wiadomości binarne” czy też jedynie ”wiadomości tekstowe” ? */

52 Message Queues – kontrolowanie kolejki
int msgctl(int msqid, int cmd, struct msqid_ds *buf ) funkcja ta służy do zmiany charakterystyk kolejki (także do jej usunięcia) jak również do uzyskania informacji o kolejce Argument cmd może mieć wartość: IPC_STAT -- umieszcza informacje o kolejce w strukturze danych wskazanych przez buf; IPC_SET -- przede wszystkim dla root’a – daje możliwość zmiany właściciela, grupy, praw dostępu do kolejki IPC_RMID – usuwa daną kolejkę

53 Message Queues – kontrolowanie kolejki
struct msqid_ds *buf ta struktura jest opisana w /usr/include/bits/msq.h struct ipc_perm msg_perm; /* structure describing operation permission */ time_t msg_stime; /* time of last msgsnd command */ time_t msg_rtime; /* time of last msgrcv command */ time_t msg_ctime; /* time of last change */ unsigned long int __msg_cbytes; /* current number of bytes on queue */ msgqnum_t msg_qnum; /* number of messages currently on queue */ msglen_t msg_qbytes; /* max number of bytes allowed on queue */ __pid_t msg_lspid; /* pid of last msgsnd() */ __pid_t msg_lrpid; /* pid of last msgrcv() */

54 Message Queues – kontrolowanie kolejki przyklad
#include <sys/types.h> #include <sys/ipc.h> #include <sys/msg.h> #include <stdio.h> #include <string.h> struct msqid_ds buf;

55 Message Queues – kontrolowanie kolejki przyklad
main() { int n; int msqid; int msgflg = 0; key_t key; size_t buf_length; key = 1234; msqid = msgget(key, msgflg ); printf(" msqid=%d\n",msqid);

56 Message Queues – kontrolowanie kolejki przyklad
if ((msqid = msgget(key, msgflg )) < 0) { perror("msgget"); exit(1); } n = msgctl(msqid,IPC_STAT, &buf); printf("\n msgctl zwrocilo %d\n",n);

57 Message Queues – kontrolowanie kolejki przyklad
printf(" buf.msg_qnum =%d\n",buf.msg_qnum); printf(" buf.msg_lspid =%d\n",buf.msg_lspid); printf(" buf.msg_stime =%d\n",buf.msg_stime); printf(" %s \n",ctime( &buf.msg_stime) ); exit(0); } /* koniec main */

58 Semafory Semafor w programowaniu jest abstrakcją o zastosowaniu zaczerpniętym z działalności kolei. Gdy zasobów jest na tyle mało, że trzeba ich użyciem się dzielić (typowych zasobów jest zawsze za mało), naturalne jest wprowadzenie znaczników zajętości. W kolejnictwie semafory informują o zajętości toru, stacji itp.. Np. jeśli dany jest pojedynczy odcinek torów na którym powinien znajdować się najwyżej jeden pociąg, inne pociągi muszą czekać, aż semafor przyjmie stan zezwalający na zajęcie tego odcinka torów. W wersji komputerowej semafor może być przechowywaną zmienną typu int. Dany proces czeka aż zmienna ta przyjmie wartość zero. Gdy proces uzyskuje dostęp do zasobu ”będącego chronionego semaforem”, podwyższa tą wartość o jeden (inkrementuje). Gdy kończy używanie, odejmuje od tej wartości jeden.

59 Semafory semget() Funkcja semget() inicjalizuje lub umożliwia dostęp do semaforu. Oto jej prototyp: #include <sys/sem.h> int semget(key_t key, int nsems, int semflg); w przypadku sukcesu funkcja zwraca semid (”semaphore id”) key – wartość klucza stowarzyszona z semaforem nsems – ile elementów ma dany semafor (jego macierz) semflg – definiuje początkowe prawa dostępu, znaczniki kontrolne ( na przykład: | IPC_CREAT | IPC_EXCL )

60 #include <sys/types.h> #include <sys/ipc.h>
Semafory semget() #include <sys/types.h> #include <sys/ipc.h> #include <sys/sem.h> ... key_t key; int semflg; int nsems; int semid; /* semafor id zwracane przez semget() */

61 key = ... ; nsems = ... ; semflg = ... ;
Semafory semget() key = ... ; nsems = ... ; semflg = ... ; if ((semid = semget(key, nsems, semflg)) == -1) { perror("semget: semget failed"); exit(1); } else ...

62 Semafory semctl() zmienia charakterystyki danego semaforu int semctl(int semid, int semnum, int cmd, union semun arg); semid – semafor id semnum – wybór semaforu (jego indeks, np. 0,1,...) union semun { /* do operacji kontrolnych semctl() */ int val; struct semid_ds *buf; ushort_t *array; } arg;

63 Semafory semctl() cmd jest jedną z następujących wartości:
GETVAL Zwróć wartość pojedynczego semaforu. SETVAL Ustaw wartość pojedynczego semaforu. Użyte jest arg.val . GETPID Zwróć pid procesu który wykonał ostatnią operację na tym semaforze. GETNCNT Zwróć liczbę procesów czekających na to, by wartość semaforu wzrosła. GETZCNT Zwróc liczbę procesów czekających na to, by wartość semaforu osiągnęła zero.

64 Semafory semctl() cmd jest jedną z następujących wartości: GETALL zwróć wartości wszystkich semaforów w danej macierzy; użyta jest arg.array . SETALL ustaw wartości wszystkich semaforów w danej macierzy; użyta jest arg.array . IPC_STAT -- zwrócona jest informacja o semaforze, zostaje umieszczona w strukturze danych arg.buf (czyli użyty jest obiekt typu semid_ds) . IPC_SET Ustawione zostają parametry: uzytkownik, grupa, prawa dostępu. Zostaje użyte arg.buf. IPC_RMID -- Semafor zostanie usunięty.

65 Semafory - semop() #include <sys/sem.h> /* wykonuje operacje na semaforze */ int semop(int semid, struct sembuf *sops, size_t nsops); semid -- semafor id (zwrócone przez semget() ) sops wskaźnik do macierzy struktur (struktura sembuf opisuje operację na semaforze) struct sembuf { ushort_t sem_num; /* numer semaforu */ short sem_op; /* kod operacji */ short sem_flg; /* znacznik operacji */ };

66 Semafory - semop() Argument nsops określa długość tej macierzy struktur; tym samym określa ile operacji wykona pojedyncze zawołanie semop(). Operacje są wykonywane w następujący sposób: dodatnia wartość int powiększa wartość semafora (o wartość) ujemna wartość int obniża wartość semafora (o wartość), próba ustawienia semafora na mniej niż zero powoduje blokowanie (zawieszenie procesu) lub błąd, w zależności od tego czy włączony jest znacznik IPC_NOWAIT wartość zero oznacza żądanie oczekiwanie aż semafor osiągnie zero

67 Semafory - semop() znaczniki kontrolne IPC_NOWAIT – zgłasza zakaz blokowania procesu (gdyby operacja nie mogła być wykonana) SEM_UNDO – poszczególne operacje opisane w macierzy struktur zostaną wycofane gdy semop() się załamie (”uda się wszystko albo nic”)

68 Semafory - semop() po wywołaniu semop() proces (jego dalsze wykonanie) jest blokowany (chyba że użyte jest IPC_NOWAIT); tak długo aż dojdzie do jednej z poniższych sytuacji: semop() się wykona proces otrzyma sygnał semafor zostanie usunięty (np.. komendą ipcrm, lub usunie go inny proces)

69 Semafory Uwagi: tylko jeden proces na raz może modyfikować semafor. Jeśli kilka procesów spróbuje zrobić to jednocześnie, zostaną wykonane w kolejności o której rozstrzygnie system operacyjny. Jeśli proces modyfikujący semafor padnie, może się zdarzyć że stan semaforu został zmodyfikowany tylko częściowo.


Pobierz ppt "Zaawansowana obsługa sygnałów"

Podobne prezentacje


Reklamy Google