• Nie Znaleziono Wyników

Zaawansowana komunikacja międzyprocesowa

N/A
N/A
Protected

Academic year: 2021

Share "Zaawansowana komunikacja międzyprocesowa"

Copied!
19
0
0

Pełen tekst

(1)

Zaawansowana komunikacja

międzyprocesowa

(2)

IPC

IPC jest zbiorem urządzeń komunikacji międzyprocesowej (ang.

interprocess communication). W skład tego zbioru wchodzą:

Przekazywanie komunikatów (ang. message passing): pozwala

procesowi wysyłać i odbierać komunikaty, będące dowolną sekwencją bajtów lub znaków

Semafory (ang. semaphores) niskopoziomowy sposób

synchronizacji procesów, nieodpowiedni do przesyłania danych. Podstawy teoretyczne E.W. Dijkstra (1968)

Pamięć współdzielona (ang. shared memory) najszybsze

urządzenie IPC pozwalające pewnej liczbie procesów korzystać z danych zawartych w określonych segmentach pamięci.

Urządzenia IPC są powszechnie używane i pochodzą z Systemu V Uniksa.

(3)

Klucze IPC

3 Wszystkie urządzenia IPC posiadają podobny interfejs, odbijając

podobieństwo ich implementacji wewnątrz jądra. Najważniejszą wspólna cechą jest klucz urządzenia IPC. Klucze są liczbami używanymi do

identyfikacji obiektów IPC w Uniksie w podobny sposób jak nazwa

identyfikuje plik. Umożliwia to wspólne użycie zasobów IPC przez kilka (niespokrewnionych) procesów. Klucz jest określany przez zależny od implementacji typ key_t z <sys/types.h>.

Klucze różnych obiektów nie mogą się powtarzać. Do znajdowania unikatowego klucza zależnego od ścieżki pliku służy funkcja:

key_t ftok(const char *path,int id);

Zwraca ona numer klucza w oparciu o path pliku. Parametr id

dostarcza dodatkowy poziom niepowtarzalności – ta sama path dla różnych id daje różne klucze.

(4)

Przekazywanie komunikatów

4 Komunikat jest sekwencją znaków. Komunikaty są przekazywane

między procesami za pomocą kolejek komunikatów tworzonych przez funkcję:

int msgget(key_t key, int permflags);

key identyfikuje kolejkę jako urządzenie IPC, permflags może

przyjmować dwie wartości zdefiniowane w <sys/ipc.h>:

IPC_CREAT utwórz kolejkę, o ile nie istnieje; nie będzie nadpisana,

jeżeli istnieje; bez tego parametru wywołanie dla istniejącej kolejki odda identyfikator istniejącej kolejki

IPC_EXCL jeżeli użyte z IPC_CREATE, to tworzy kolejkę; jeżeli kolejka

istnieje zwraca -1 a errno zwraca EEXIST.

9 mniej znaczących bitów jest permflags używane do nadawania uprawnień:

(5)

Wysyłanie i odbieranie

5 Do operowania na istniejącej kolejce komunikatów służą funkcje:

int msgsnd(int mqid, const void *msg, size_t size, int flags); int msgrcv(int mqid, void *msg,

size_t size, long msg_type);

mqid to identyfikator kolejki zwrócony przez msgget, komunikat jest

zawarty w strukturze o następującym wzorcu:

struct mymsg{

long mtype; /* typ komunikatu */

char mtext[SOMEVALUE]; /* tekst komunikatu */ }

Składowa mtype może być używana do klasyfikacji komunikatów.

size to dla wysyłania liczba wysłanych bajtów < SOMEVALUE lub

(6)

Wysyłanie i odbieranie

II

6 Parametr flags dla msgsnd może przybierać tylko jedną wartość:

IPC_NOWAIT. Bez niej proces wywołujący będzie wstrzymany, jeżeli

brak zasobów systemowych do wysłania komunikatu, np. całkowita długośc komunikatów przekracza max. systemowe lub max. kolejki. Zmienna errno będzie ustawiona na EAGAIN.

Wysyłanie komunikatu może zawieść z powodu oprawnień. W zmiennej

errno będzie wówczas EACCES.

Odczyt komunikatu, o ile mamy uprawnienia, powoduje usuniecie go z kolejki. Parametr msg_type określa jaki typ komunikatu został

odczytamy, jeżeli był ustawiony na 0. Jeżeli msg_type ma wartość >0, to zostanie odczytany komunikat o tym typie. Jeżeli ma wartość ujemną, to zostanie odczytany pierwszy komunikat z najniższą liczbą mtype,

mniejszą niż albo równą wartości bezwzględnej msg_type.

flags przyjmuje wartości IPC_NOWAIT (działa jak dla wysyłania) i/lub MSG_NOERROR – komunikat obcięty, jeżeli przekracza size.

(7)

Funkcja msgctl

7 Funkcja msgctl służy trzem celom:

 uzyskanie informacji o stanie kolejki komunikatów

 zmiana niektórych ograniczeń zwiazanych z kolejką

 usuwanie kolejki z systemu Postać funkcji:

int msgctl(int mqid, int command,

struct msqid_ds *msq_stat);

Parametr mqid jest identyfikatorem kolejki komunikatów. Trzeci

parametr msq_stat zawiera adres struktury msqid_ds zdefiniowanej w <bits/msg.h>. Opis w pliku msg/msqid_ds.

(8)

Funkcja msgctl

II

8 Parametr command opisuje operację wykonywaną przez msgctl. Istnieją trzy dostępne wartości wspólne dla wszystkich urządzeń IPC:

IPC_STAT umieść w msq_stat informacje o stanie struktury IPC_SET zmiana parametrów urządzenia IPC; dla kolejek

komunikatów można zmieniać:

msg_stat.msg_perm.uid, msg_stat.msg_perm.gid, msg_stat.msg_perm.mode,

msg_stat.msg_qbytes; operacja zakończy się

pomyślnie, jeżeli jest wykonywana przez SU lub właściciela kolejki; tylko SU może powiększyć msg_qbytes (max.

liczba znaków w kolejce)

IPC_RMID usuwa kolejkę komunikatów z systemu; operacja

dostępna tylko dla SU lub właściciela kolejki; po wykonaniu

msq_stat ustawiony na NULL. Zobacz: msg/show_msg.c

(9)

Semafory

9 Pojęcie semafora zostało po raz pierwszy wprowadzone przez

E.W.Dijkstrę, jako rozwiazanie problemów synchronizacji procesów. Semafor jest zmienną całkowitą, na której dozwolone są następujące operacje:

p(sem):

if (sem != 0) zmniejsz sem o 1 else czekaj aż sem stanie się

różne od zera, wtedy zmniejsz

v(sem):

zwiększ sem o 1

if(kolejka czekających procesów nie jest pusta)

uruchom pierwszy proces z kolejki oczekujących

Część testująca i ustawiająca obu operacji musi być niepodzielna. Niezmiennik semafora:

(początkowa wartość sem + liczba operacji v – liczba zakończonych operacji p) >= 0

(10)

Semafory:

get

10 Funkcja semget jest analogiczna do funkcji msgget.

int semget(key_t key, int nsems, int permflags);

Operacje semaforowe Unixa są nastawione na pracę z zestawami semaforów, a nie z pojedynczymi obiektami. Parametr nsems podaje liczbę semaforów w tworzonym zestawie. Wartością zwracaną przez pomyślne wywołanie semget jest identyfikator zestawu semaforów.

semval = 2 semval = 4 semval = 1 semval = 3 nsems = 4 semid

(11)

Semafory:

wartości

11 Z każdym semaforem w zestawie związane są następujące wartości:

semval wartość semafora, zawsze dodatnia liczba całkowita. Musi być

ustawiana za pomocą funkcji systemowej semafora; oznacza to, że semafor nie jest dostępny dla programu jako obiekt

danych.

sempid identyfikator procesu, który ostatnio miał do czynienia z

semaforem.

semncnt liczba procesów, które czekają, aż semafor osiagnie wartość

większą niż jego aktualna wartość.

semzcnt liczba procesów, które czekają, aż semafor osiągnie wartość

(12)

Semafory:

semctl

12

int semctl(int semid, int sem_num, int command, union semun ctl_arg);

Parametr semid musi być ważnym identyfikatorem semafora (wynik

semget). Parametry command są podzielone na trzy grupy:

standardowe funkcje IPC (jak IPC_STAT),

 funkcje działające tylko na pojedynczy semafor,  funkcje dotyczące całego zestawu semaforów.

Parametr sem_num jest używany z drugą grupą funkcji do identyfikacji konkretnego semafora. Ostatni parametr jest unią:

union semun{ int val;

struct semid_ds *buf; unsigned short *array; }

Używana do przekazywania wartości – wykorzystanie poszczególnych pól zależne od operacji.

(13)

Kody funkcji

semctl

13

Standardowe

IPC_STAT umieszcza informację o stanie w ctl_arg.stat IPC_SET ustawia informację o prawach własności i dostępu z

ctl_arg.stat

IPC_RMID usuwa zestaw semaforów z systemu Operacje na pojedynczym semaforze

GETVAT zwraca wartość semafora (tj. semval)

SETVAL ustawia wartość semafora z ctl_arg.val GETPID zwraca wartość sempid

GETNCNT zwraca semncnt GETZCNT zwraca semzcnt

Operacje na wszystkich semaforach

GETALL umieszcza wszystkie semvals w ctl_arg.array

(14)

Semafory

semop

14

int semop(int semid, struct sembuf *op_array, size_t num_ops);

Parametr semid musi być ważnym identyfikatorem semafora (wynik

semget). Parametr op_array to tablica struktur sembuf,

zdefiniowane w <sys/sem.h>. Parametr num_ops jest liczbą struktur

sembuf w tablicy. Każda struktura sembuf zawiera specyfikację

operacji do wykonania na semaforze.

semop wykonuje się niepodzielnie na zestawach semaforów. Tj., jeśli

jedna z operacji nie może być wykonana, to żadna operacja nie będzie wykonana. Jeżeli nie określono inaczej, proces powinien się zablokować do czasu, póki nie może wykonać wszystkich operacji naraz.

Sembuf zawiera następujące składowe:

unsigned short sem_num;/* indeks semaf w zestawie */ short sem_op; /* określa co zrobić */

(15)

Operacje

sem_op

15

sem_op < 0

Jest to ogólna forma polecenia p(); realizuje następujący algorytm:

if(semval >=ABS(sem_op)) {

ustaw semval na (semval – ABS(sem_op)) } else {

if(sem_flg & IPC_NOWAIT) )

natychmiast zwróć -1

else {

czekaj, aż semval osiągnie lub przekroczy ABS(sem_op) następnie odejmij ABS(sem_op), jak powyżej

} }

Funkcja testuje czy semval jest jest wystarczająco duża. Jeżeli jest, to zostaje zmniejszona. Jeżeli nie, to proces czeka, aż semval stanie się wystarczająco duża. Jeżeli jednak w sem_flg ustawiono IPC_NOWAIT

(16)

Operacje

sem_op cd

16

sem_op > 0

Jest zgodna z operacją v(); wartość sem_op zostaje dodana do odpowiedniej wartości semval. Jeżeli jakiś proces czeka na nową wartość semafora, to zostanie obudzony.

sem_op = 0

W tym przypadku funkcja będzie czekać, aż wartość semafora stanie się zerem, a wartość semval nie jest zmieniana. Jeśli w sem_flg jest

ustawiony znacznik IPC_NOWAIT, a wartość semval już nie jest zerowa, wtedy funkcja zwraca błąd.

SEM_UNDO

Ustawienie tego znacznika w sem_flg informuje system by

automatycznie cofnął operację gdy proces się zakończy. Proces

utrzymuje wówczas zmienną całkowitą semdj, zmniejszaną o sem_num po każdej operacji semop z flagą SEM_UNDO. Po zakończeniu procesu

semdj jest dodawana do semval.

(17)

Wspólna pamięć

17 Zwykle obszary danych dwóch programów są całkowicie rozłączne. Operacje wspólnej pamięci pozwalaja dwóm lub więcej procesom korzystać wspólnie z fragmentu pamięci fizycznej.

init shmget(key_t key, size_t size, int permflag);

Funkcja ta odpowiada msgget i semget – parametry key i permflag mają takie samo znaczenie. Parametr size podaje wymaganą

minimalną wielkość (w bajtach) segmentu pamięci.

Segment pamięci utworzony przez funkcję shmget jest częścią pamięci fizycznej, a nie przestrzenią danych logicznych procesu. Aby z niego

korzystać, proces musi jawnie przyłączyć segment pamięci do swojej przestrzeni danych logicznych, używając do tego funkcji shmat.

(18)

Wspólna pamięć:

shmat

18

init shmat(int shmid, const void *daddr, int shmflags);

Funkcja przyłącza segment pamięci identyfikowany przez shmid do przestrzeni adresów logicznych wywołującego procesu. Wartością zwracaną jest adres.

Jeżeli daddr = NULL, to dołączony zostaje segment z pierwszego

dostępnego adresu wybranego przez system. Jeżeli daddr != NULL, a

shmflag ma ustawiony znacznik SHM_RND, to zwracany jest segment o

adresie daddr zaokrąglonym do granicy strony w pamięci. Jeżeli znacznik nie jest ustawiony, to zwraca segment o adresie daddr. Jeżeli wystąpi błąd, to otrzymamy wartość (void *) -1.

Znacznik SHM_RDONLY – segment tylko do odczytu.

Funkcja shmdt(memptr) odłącza przydzielony segment pamięci od przestrzeni adresów logicznych procesu.

Wynik: 0 = powodzenie, -1 = błąd.

Zobacz:

(19)

Polecenia ipcs i ipcrm

19 Istnieją dwa polecenia na poziomie powłoki, które umożliwiają użycie urządzeń IPC. Pierwsze z nich, ipcs, drukuje informację o bieżącym stanie urzadzeń IPC. Przykład użycia

$ ipcs

Kolejne polecenie, używane do usuwania urzadzeń IPC z systemu (pod warunkiem, że użytkownik jest właścicielem urządzenia lub SU), to ipcrm. Przykłady:

$ ipcrm -s 0

usuwa np. semafor związany z identyfikatorem 0.

$ ipcrm -S 200

Cytaty

Powiązane dokumenty

Udowodnić, że średnia arytmetyczna tych liczb jest równa n+1 r

Utwórz zapytanie, które wyświetli nazwisko, imię, wiek pracownika i komentarz (osobom poniżej 40 ma się wyświetlić „junior”, osobom od 40 – „senior”).. Ćwiczenie

[r]

 Jeśli wystąpił błąd lub został przeczytany znacznik końca pliku, to funkcja zwraca wartość EOF.. Znakowe

 Jeśli wystąpił błąd albo został przeczytany znacznik końca pliku, to funkcja zwraca wartość EOF.

 Jeśli wystąpił błąd lub przeczytany został znacznik końca pliku, to funkcja zwraca wartość EOF... Znakowe

Jeśli wystąpił błąd lub został przeczytany znacznik końca pliku, to funkcja zwraca wartość EOF.. Znakowe

Jeśli wystąpił błąd lub przeczytany został znacznik końca pliku, to funkcja zwraca wartość EOF..