Zaawansowana obsługa sygnałów

Slides:



Advertisements
Podobne prezentacje
C++ wykład 2 ( ) Klasy i obiekty.
Advertisements

C++ wykład 4 ( ) Przeciążanie operatorów.
Język C/C++ Funkcje.
Wzorce.
Programowanie współbieżne i rozproszone
Wprowadzenie do języka skryptowego PHP
Systemy rozproszone W. Bartkiewicz
Języki programowania C++
PROGRAMOWANIE STRUKTURALNE
dynamiczny przydział pamięci
używanie komend UNIXa z wnętrza programu napisanego w C
Uzupełnienie dot. przekazywania argumentów #include struct nowa { int f; char line[20000]; int k; } reprezentant; int main() { void funkcja7( struct nowa.
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.
SIECI KOMPUTEROWE (SieKom) PIOTR MAJCHER WYŻSZA SZKOŁA ZARZĄDZANIA I MARKETINGU W SOCHACZEWIE Zarządzanie.
ODE Zapytania. Pętla for (1) Do obiektów będących instancjami klas możemy uzyskać dostęp za pomocą pętli for Zakres tej pętli to wszystkie obiekty klasy.
Struktury.
Tablice.
Programowanie w C Wykład 3
Wykład 1: Wskaźniki Podstawy programowania Programowanie w C
15. MECHANIZMY SYNCHRONIZACJI WĄTKÓW Większość koncepcji stworzonych na potrzeby synchronizacji procesów ciężkich została zastosowana też do synchronizacji.
Muteksy Muteksy (mutex – MUTual EXclusion) są prostymi obiektami synchronizacyjnymi pełniącymi rolę semaforów binarnych dla wątków (chroniącymi sekcje.
11. PAKIET IPC Narzędzia z pakietu IPC (InterProcess Communication) służą do koordynacji procesów wykonywa- nych na jednym komputerze (nie są przeznaczone.
Semafory według normy POSIX
10. PROSTE MECHANIZMY KOORDYNACJI DOSTĘPNE W JĘZYKU C W systemie Unix użytkownikowi (nie będącemu administratorem) nie wolno wykonywać bezpośrednio żadnych.
9. KOORDYNACJA PROCESÓW WSPÓŁBIEŻNYCH PRZY UŻYCIU INTERPRETATORA
ipcrm [ shm | msq | sem ] id
Procesy odrębne –Unikatowy PID ( ) –Zmienne –Zbiory deskryptorów plików –Przestrzeń stosu (lokalne zmienne, wywołania funkcji) –Środowisko –Licznik.
Wątki.
Pamięć wspólna Opis własnego rozwiązania Marcin Kamiński, Michał Kotra Wydział EAIiE Katedra Automatyki Kraków, 2008.
Pamięć wspólna Przegląd stosowanych rozwiązań Marcin Kamiński, Michał Kotra Wydział EAIiE Katedra Automatyki Kraków, 2008.
nowe operatory & . (kropka) * operator rzutowy -> , (przecinek)
Schemat Hornera Mgr inż. Michał Szucki.
Podstawy programowania
Podstawy programowania II
Podstawy informatyki 2013/2014
Linux - polecenia.
Programowanie strukturalne i obiektowe
Automatyka i Robotyka Systemy czasu rzeczywistego Wykład 4.
Złożone typy danych Listy Tworzenie elastycznych baz danych
Jerzy F. Kotowski1 Informatyka I Wykład 14 DEKLARATORY.
Inicjalizacja i sprzątanie
Programowanie obiektowe Wykład 3 dr Dariusz Wardowski, Katedra Analizy Nieliniowej, WMiI UŁ 1/21 Dariusz Wardowski.
Wykład 4 Programowanie systemowe w Linux: System plików i procesy
Programowanie systemowe w Linux:
Operacje edycyjne w bazie danych - kwerendy funkcjonalne Marzena Nowakowska Katedra Informatyki Stosowanej, WZiMK, PŚk.
Programowanie obiektowe 2013/2014
Komendy SQL do pracy z tabelami i bazami
Wykład 7 Synchronizacja procesów i wątków
Kurs języka C++ – wykład 9 ( )
Systemy operacyjne (wiosna 2014)
Kurs języka C++ – wykład 4 ( )
1 dynamiczny przydział pamięci malloc() free() realloc() calloc() memset() memcpy( ) mempcpy( ) memmove() (wskaźniki!! )
1 Uzupełnienie dot. przekazywania argumentów #include struct nowa { int f; char line[20000]; int k; } reprezentant; int main() { void funkcja7( struct.
Komendy SQL do pracy z danymi
Paweł Starzyk Obiektowe metody projektowania systemów
Programowanie Zaawansowane
Seminarium Dyplomowe: Metodyka i Techniki Programowania Autor: Bartłomiej Fornal.
Podstawy informatyki Tablice Łukasz Sztangret Katedra Informatyki Stosowanej i Modelowania Prezentacja przygotowana w oparciu o materiały Danuty Szeligi.
1 Architektury Komputerów i Systemy Operacyjne Prowadzący przedmiot: dr inż. Rafał Stankiewicz Data:
1 Opisy funkcji Adres strony WWW : html (należy odszukać hyperlink Function Index) (
Łukasz Sztangret Katedra Informatyki Stosowanej i Modelowania Prezentacja przygotowana w oparciu o materiały Danuty Szeligi i Pawła Jerzego Matuszyka Podstawy.
Jeszcze dygresja o macierzach... #include /* przyklad pokazuje, jak dla macierzy wielowymiarowych dziala operator dereferencji * ; otoz jesli macierz jest.
ALGORYTMY I STRUKTURY DANYCH
Kurs języka C++ – wykład 3 ( )
jeszcze dygresja o macierzach...
Opisy funkcji Adres strony WWW :
Uzupełnienie dot. przekazywania argumentów
nowe operatory & . (kropka) * operator rzutowy -> , (przecinek)
Język C++ Typy Łukasz Sztangret Katedra Informatyki Stosowanej i Modelowania Prezentacja przygotowana w oparciu o materiały Danuty Szeligi i Pawła Jerzego.
dynamiczny przydział pamięci
Zapis prezentacji:

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.

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.

”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!

”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.

”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.

”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.

”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); }

”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); }

”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 */

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

”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

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”)

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);

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.

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”

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> */

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 */

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); } ...

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)

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>

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);

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;

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 */ }

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);

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 = '*';

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);

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 */

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

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”

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 */

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 ()

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);

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;

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 */

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;

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");

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 */

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

”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.

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 | 0666 ) ; (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()

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

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 1...2....3...) msgflg to znacznik, np. IPC_NOWAIT

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 128

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

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;

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;

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); }

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

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

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); }

Message Queues – przykład odebrania /* Odbierz wiadomość typu 1 */ 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” ? */

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ę

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() */

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;

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);

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);

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 */

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.

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: 0666 | IPC_CREAT | IPC_EXCL )

#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() */

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

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;

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.

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.

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 */ };

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

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”)

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)

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.