J. Ułasiewicz Programowanie aplikacji współbieżnych 1

Podobne dokumenty
Rys. 9-1 Procesy P1 i P2 komunikuję się poprzez wspólny obszar. pamięci.

J. Ułasiewicz Programowanie aplikacji współbieżnych 1

10. Synchronizacja użycia zasobów, Semafory Problem producenta i konsumenta

10. Synchronizacja użycia zasobów, Semafory

J. Ułasiewicz Programowanie aplikacji współbieżnych 1

10. Synchronizacja użycia zasobów, Semafory

10. Synchronizacja użycia zasobów, Semafory

Laboratorium Systemów Operacyjnych. Ćwiczenie 4. Operacje na plikach

Obsługa plików. Systemy Operacyjne 2 laboratorium. Mateusz Hołenko. 25 września 2011

Pliki. Funkcje tworzące pliki i operujące na nich opisane są w części 2 pomocy systemowej. Tworzenie i otwieranie plików:

1. Kolejki komunikatów POSIX

Co to jest sterta? Sterta (ang. heap) to obszar pamięci udostępniany przez system operacyjny wszystkim działającym programom (procesom).

Obsługa plików Procesy

Kolejki komunikatów POSIX

Łącza nienazwane(potoki) Łącza nienazwane mogą być używane tylko pomiędzy procesami ze sobą powiązanymi.

13. Kolejki komunikatów POSIX

Temat: Dynamiczne przydzielanie i zwalnianie pamięci. Struktura listy operacje wstawiania, wyszukiwania oraz usuwania danych.

Problem producentakonsumenta

Podstawy programowania. Wykład 6 Wskaźniki. Krzysztof Banaś Podstawy programowania 1

Podstawy programowania komputerów

Przedmowa Wstęp Wprowadzenie podstawowe pojęcia... 15

Semafory, pamięć dzielona i kolejki komunikatów

4. Komunikacja pomiędzy procesami przez łącza nienazwane i nazwane

Wskaźniki. Przemysław Gawroński D-10, p marca Wykład 2. (Wykład 2) Wskaźniki 8 marca / 17

J. Ułasiewicz Łącza nienazwane, nazwane, select 1

Pamięć współdzielona

eć dzielona standardu POSIX

4. Tablica dwuwymiarowa to jednowymiarowa tablica wskaźników do jednowymiarowych tablic danego typu.

Pamięć dzielona i kolejki komunikatów

Podstawy programowania w języku C++

Uzupełnienie dot. przekazywania argumentów

Procesy. Systemy Operacyjne 2 laboratorium. Mateusz Hołenko. 9 października 2011

Wskaźniki. Informatyka

Tablice, funkcje - wprowadzenie

Struktury czyli rekordy w C/C++

Temat zajęć: Obsługa systemu plików.

// Liczy srednie w wierszach i kolumnach tablicy "dwuwymiarowej" // Elementy tablicy są generowane losowo #include <stdio.h> #include <stdlib.

Model pamięci w systemie Linux

KURS C/C++ WYKŁAD 6. Wskaźniki

Stałe, tablice dynamiczne i wielowymiarowe

Język ANSI C. część 11. Jarosław Gramacki Instytut Informatyki i Elektroniki

dynamiczny przydział pamięci calloc() memset() memcpy( ) (wskaźniki!! )

Wskaźniki. Programowanie Proceduralne 1

Wykład Tryby adresowania i modele pamięci adres_logiczny = segment : offset Tryb adresowania rzeczywistego

Laboratorium z systemów operacyjnych. System plików - funkcje systemowe. Anna Wojak

DYNAMICZNE PRZYDZIELANIE PAMIECI

1. Utwórz blok pamięci współdzielonej korzystając z poniższego kodu:

J. Ułasiewicz Łącza nienazwane, nazwane, select 1

Poniższe funkcje opisane są w 2 i 3 części pomocy systemowej.

Semafor ustaw_semafor(key_t nazwa, int start); Semafor usun_semafor(semafor sem); void signal(semafor sem); void wait(semafor sem);

wykład III uzupełnienie notatek: dr Jerzy Białkowski Programowanie C/C++ Język C - zarządzanie pamięcią, struktury,

Podział programu na moduły

1. Kolejki komunikatów POSIX

Programowanie w języku C++

Komunikacja mi edzyprocesowa (IPC)

Zaawansowane operacje wejścia/wyjścia

3. Identyfikacja. SKŁADNIA #include <sys/socket.h> int getpeername(int socket, struct sockaddr *addr, int *addrlen);

Spis treści WSKAŹNIKI. DYNAMICZNY PRZYDZIAŁ PAMIĘCI W JĘZYKU C. Informatyka 2. Instrukcja do pracowni specjalistycznej z przedmiotu

Wstęp do Programowania, laboratorium 02

Instytut Teleinformatyki

Zaawansowane operacje wejścia/wyjścia

Zarządzanie pamięcią w systemie operacyjnym

Wskaźniki i dynamiczna alokacja pamięci. Spotkanie 4. Wskaźniki. Dynamiczna alokacja pamięci. Przykłady

Typy złożone. Struktury, pola bitowe i unie. Programowanie Proceduralne 1

Zaawansowane operacje wejścia/wyjścia

PROGRAMOWANIE SYSTEMÓW CZASU RZECZYWISTEGO

Temat zajęć: Tworzenie i obsługa wątków.

1. Procesy i współbieżność

Podstawy programowania w języku C++

Wskaźniki w C. Anna Gogolińska

Wykład VI. Programowanie. dr inż. Janusz Słupik. Gliwice, Wydział Matematyki Stosowanej Politechniki Śląskiej. c Copyright 2014 Janusz Słupik

Języki i metody programowania I

1.1 Przykład znajdowanie liczb pierwszych leżących w zadanym zakresie, tryb bezpołączeniowy

Temat zajęć: Obsługa łączy komunikacyjnych

Pomoc dla użytkowników systemu asix 6 i 7. Drajwer Bufor. Dok. Nr PLP6021 Wersja:

Futex (Fast Userspace Mutex) Łukasz Białek

Gniazda BSD. komunikacja bezpołączeniowa

Krótkie wprowadzenie do korzystania z OpenSSL

ZASADY PROGRAMOWANIA KOMPUTERÓW

Zaawansowane operacje wejścia/wyjścia

1. Timery i zdarzenia

Wskaźniki. nie są konieczne, ale dają językowi siłę i elastyczność są języki w których nie używa się wskaźników typ wskaźnikowy typ pochodny:

Łącza nienazwane(potoki)

Spis treści WSKAŹNIKI. DYNAMICZNY PRZYDZIAŁ PAMIĘCI W JĘZYKU C. Informatyka 2. Instrukcja do pracowni specjalistycznej z przedmiotu

9. Problem wzajemnego wykluczania i sekcji krytycznej

SUMA KONTROLNA (icmp_cksum) NUMER KOLEJNY (icmp_seq)

Spis treści JĘZYK C - WSKAŹNIKI, DYNAMICZNY PRZYDZIAŁ PAMIĘCI. Informatyka 2. Instrukcja do pracowni specjalistycznej z przedmiotu

Wątki. S. Samolej: Wątki, producent - konsument 1

Pobieranie argumentów wiersza polecenia

4.2 Sposób korzystania z l acza

Tablice w argumentach funkcji. Tablicy nie są przekazywane po wartości Tablicy są przekazywane przez referencje lub po wskaźniku

Materiał uzupełniający do ćwiczen z przedmiotu: Programowanie w C ++ - ćwiczenia na wskaźnikach

Programowanie na poziomie sprzętu. Tryb chroniony cz. 1

Język ANSI C tablice wielowymiarowe

Wykład 3. Procesy i wątki. Wojciech Kwedlo, Wykład z Systemów Operacyjnych -1- Wydział Informatyki PB

Schematy zarzadzania pamięcia

Funkcje zawarte w bibliotece < io.h >

Pliki w C/C++ Przykłady na podstawie materiałów dr T. Jeleniewskiego

Ćwiczenie 4. Obsługa plików. Laboratorium Podstaw Informatyki. Kierunek Elektrotechnika. Laboratorium Podstaw Informatyki Strona 1.

Tablice, funkcje, wskaźniki - wprowadzenie

Transkrypt:

J. Ułasiewicz Programowanie aplikacji współbieżnych 1 9. Komunikacja przez pamięć dzieloną Pamięć wirtualna Procesy nie adresują bezpośrednio pamięci fizycznej. Zamiast tego system operacyjny przydziela im wirtualną przestrzeń adresową. Jest ona liniowa, zaczyna się od zera i rośnie aż do wartości maksymalnej. Pamięć składa się z bajtów pogrupowanych w strony. Strony zarządzane są przez MMU (ang. Memory Management Unit). Rozmiar strony zależy od architektury I zwykle wynosi: 4 kb dla maszyn 32 bitowych 8 kb dla maszyn 64 bitowych Strona może być albo obecna w pamięci RAM albo nieobecna, znajduje się w pamięci dyskowej. Odwołanie się do strony nieobecnej powoduje wyjątek błąd strony (ang. Page Fault). Wtedy system operacyjny sprowadza stronę z pamięci dyskowej do pamięci RAM. Jądro rozmieszcza strony w blokach zwanych regionami pamięci. Różnić się one mogą prawami dostępu. W każdym procesie istnieją następujące regiony pamięci: Segment tekstu zawiera kod i dane stałe, literały, tylko do odczytu Segment stosu zawiera zmienne lokalne i dane zwracane z funkcji. Rośnie i maleje w trakcie wykonania programu Segment danych (sterta) zawiera dane dynamiczne przydzielane funkcją malloc. Segment bss zawiera niezainicjowane zmienne globalne Przydzielanie pamięci dynamicznej Pamięć dynamiczna przydzielana jest funkcją malloc void * malloc(size_t size) Funkcja zwraca wskaźnik na przydzielony obszar pamięci lub NULL gdy się nie powiodła.

J. Ułasiewicz Programowanie aplikacji współbieżnych 2 typedef struct { int pocz; int kon; int ile; msg_t;... msg_t * buf;... buf = (msg_t *) malloc(sizeof(msg_t)); buf->pocz = 1; Pamięć dynamiczna do tablic przydzielana jest funkcją calloc void * calloc(size_t nr, size_t size) nr size liczba elementów wielkośc elementu Funkcja zwraca wskaźnik na przydzielony obszar pamięci lub NULL gdy się nie powiodła. Zmiana wielkości obszaru void * realloc(void * ptr, size_t size) ptr size wskaźnik na obszar nowa wielkość obszaru Zwalnianie obszaru pamięci void free(void * ptr)

J. Ułasiewicz Programowanie aplikacji współbieżnych 3 Blokowanie pamięci int mlock(const void * adr, size_t len); Wykonanie funkcji spowoduje że wskazany obszar pamięci poczynając od adr, wielkości len nie zostanie usunięty z pamięci RAM na dysk. Blokowanie całej pamięci procesu: int mlockall(int flags); Odblokowanie pamięci int munlock(const void * adr, size_t len); int munlockall(void);

J. Ułasiewicz Programowanie aplikacji współbieżnych 4 Komunikacja przez pamięć dzieloną Metoda komunikacji przez wspólną pamięć może być użyta gdy procesy wykonywane są na maszynie jednoprocesorowej lub wieloprocesorowej ze wspólną pamięcią. Procesy mają rozdzielone segmenty danych - modyfikacje wykonane na danych w jednym procesie w żaden sposób nie przenoszą się do procesu drugiego. Aby procesy mogły mieć wspólny dostęp do tych samych danych należy: 1. Utworzyć oddzielny segment pamięci. 2. Udostępnić dostęp do segmentu zainteresowanym procesom. Prywatny P2 Segment danych procesu P1 Proces 1 Wspólny Proces 2 Segment danych procesu P1 Prywatny P1 Segment pamięci dzielonej Rys. 9-1 Procesy P1 i P2 komunikuję się poprzez wspólny obszar pamięci Wątki Wątki z natury dzielą obszar danych. Zmienne zadeklarowane jako zmienne globalne będą dostępne dla wątków. Komunikacja poprzez pamięć dzieloną Gdy procesy komunikują się przez wspólną pamięć, należy zadbać o zachowania spójności danych zawartych w dzielonym obszarze pamięci.

J. Ułasiewicz Programowanie aplikacji współbieżnych 5 9.1 Funkcje operujące na wspólnej pamięci standard Posix Standard Posix 1003.4 - funkcje pozwalające na tworzenie i udostępnianie segmentów pamięci: Działanie Utworzenie wspólnego segmentu pamięci Ustalenie rozmiaru segmentu Ustalenie odwzorowanie segmentu Cofnięcie odwzorowania segmentu Zmiana trybu dostępu Skasowanie segmentu pamięci Funkcja shm_open() ftruncate() mmap() munmap() mprotect() shm_unlink() Tabela 9-1 Funkcje POSIX operujące na pamięci wspólnej Tworzenie segmentu pamięci Tworzenie segmentu pamięci podobne jest do tworzenia pliku segment jest plikiem specjalnym. int shm_open(char *name, int oflag, mode_t mode ) name oflag mode Nazwa segmentu pamięci Flaga specyfikująca tryb utworzenia (jak dla plików), np. O_RDONLY, O_RDWR, O_CREAT Specyfikacja trybu dostępu (jak dla plików). Gdy funkcja zwraca liczbę nieujemną jest to uchwyt identyfikujący segment w procesie. Segment widziany jest jako plik specjalny w katalogu /dev/shmem. Ustalanie rozmiaru segmentu pamięci off_t ftruncate(int fdes, off_t offset) fdes offset Uchwyt segmentu zwracany przez poprzednią funkcję shm_open. Wielkość segmentu w bajtach. Funkcja zwraca wielkość segmentu lub 1 gdy błąd.

J. Ułasiewicz Programowanie aplikacji współbieżnych 6 Odwzorowanie segmentu pamięci wspólnej w obszar procesu, void *mmap(void * addr, size_t len, int prot, int flags, int fdes, off_t off) addr len prot flags fdes off Zmienna wskaźnikowa w procesie której wartość będzie przez funkcję zainicjowana. Może być 0. Wielkość odwzorowywanego obszaru. Specyfikacja dostępu do obszaru opisana w <sys/mman.h>. Może być PROT_READ PROT_WRITE Specyfikacja użycia segmentu, np. MAP_SHARED. Uchwyt segmentu wspólnej pamięci. Początek obszaru we wspólnej pamięci (musi to być wielokrotność strony 4K) Funkcja zwraca adres odwzorowanego obszaru lub 1 gdy błąd. typedef struct { int typ; char text[size]; buf_t;... buf_t *buf; buf = malloc(sizeof(buf_t)); buf->typ = 1;... Przykład 1 Pamięć zawierająca strukturę znajduje się na stercie buf typ text sterta Rys. 9-2 Struktura buf na stercie

J. Ułasiewicz Programowanie aplikacji współbieżnych 7 buf proces 1 typ text bufor buf proces 2 pamięć dzielona Rys. 9-3 Struktura buf w pamięci dzielonej typedef struct { int typ; char text[size]; buf_t;... buf_t *buf;... fd=shm_open("bufor",o_rdwr O_CREAT,0664);... buf = (buf_t *)mmap(0,sizeof(buf_t),prot_read PROT_WRITE, MAP_SHARED, fd, 0); buf->typ = 1;... Przykład 2 Pamięć zawierająca strukturę znajduje się w pamięci dzielonej Odłączenie się od segmentu pamięci shm_unlink(char *name) name Nazwa segmentu pamięci. Każde wywołanie tej funkcji zmniejsza licznik udostępnień segmentu. Gdy osiągnie on wartość 0 czyli segment nie jest używany już przez żaden proces, segment jest kasowany. Schemat utworzenia i udostępnienia segmentu podano na poniższym rysunku.

J. Ułasiewicz Programowanie aplikacji współbieżnych 8 // Kompilacja gcc pam-dziel.c -o pam-dziel -lrt #include <sys/mman.h> #include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <string.h> #define SIZE 60 // Rozmiar bufora typedef struct { int typ; char text[size]; buf_t; main(int argc,char *argv[]) { int i,stat,pid,k,res; buf_t *buf; char name[16]; int fd; // Deskryptor segmentu strcpy(name,"bufor"); shm_unlink(name); // Utworzenie segmentu pamieci --------------------- if((fd=shm_open(name,o_rdwr O_CREAT,0664))==-1) { perror("shm_open"); exit(-1); printf("fh = %d\n",fd); // Okreslenie rozmiaru obszaru pamieci --------------- res = ftruncate(fd,sizeof(buf_t)); if(res < 0) { perror("ftrunc"); return 0; // Odwzorowanie segmentu fd w obszar pamieci procesow buf = (buf_t *) mmap(0,sizeof(buf_t), PROT_READ PROT_WRITE,MAP_SHARED, fd, 0); if(buf == NULL) { perror("mmap"); exit(-1); printf("start\n"); // Proces potomny P2 - pisze do pamieci wspolnej ----- if(fork() == 0) { buf-> typ = 1; for(k=0;k<10;k++) { // Zapis do bufora printf("zapis - Komunikat %d\n",k); sprintf(buf->text,"komunikat %d",k); sleep(1); exit(0); // Proces macierzysty P1 czyta z pamięci wspólnej -

J. Ułasiewicz Programowanie aplikacji współbieżnych 9 for(i=0;i<10;i++) { printf("odczyt %s\n",buf->text); sleep(1); // Czekam na potomny -- pid = wait(&stat); return 0; Przykład 9-1 Procesy P1 i P2 komunikują się przez wspólny obszar pamięci Deklaracja zmiennej wskaźnikowej buf_t * buf Nazwa segmentu - "Bufor" Utworzenie segmentu fd = shm_open("bufor",...) Ustalenie wielkości segmentu ftruncate(fd,...) Odwzorowanie segmentu fd w przestrzeń adresową procesu buf = (buf_t *) mmap(...,fd,...) Zapis / odczyt bufora buf Rys. 9-4 Schemat użycia segmentu pamięci dzielonej

J. Ułasiewicz Programowanie aplikacji współbieżnych 10 Sposób wykorzystania wspólnej pamięci do komunikacji pomiędzy procesami. Proces macierzysty P1: 1. Deklaruje zmienną wskaźnikową buf do struktury buf_t. 2. Tworzy segment pamięci o nazwie Bufor - funkcja shm_open. 3. Ustala jego wielkość na sizeof(buf_t) - funkcją ftrunc. 4. Udostępnia segment w przestrzeni adresowej inicjując zmienną buf funkcja mmap. 5. Tworzy proces potomny P2 funkcja fork. 6. Czyta znaki z bufora buf. Proces potomny P2: 1. Korzysta z utworzonego, udostępnionego i odwzorowanego jako buf segmentu pamięci. 2. Pisze komunikaty do bufora buf.

J. Ułasiewicz Programowanie aplikacji współbieżnych 11 9.2 Rozwiązanie problemu producenta i konsumenta semafory nienazwane Producenci buf[bsize] Konsumenci P1 BSIZE-1 K1 P2 Pk full head x x x 3 2 1 0 empty tail K2 Km cnt mutex segment pamieci dzielonej #include <sys/mman.h> #include <fcntl.h> #include <semaphore.h> #define BSIZE 4 // Rozmiar bufora #define LSIZE 80 // Dlugosc linii typedef struct { char buf[bsize][lsize]; int head; int tail; int cnt; sem_t mutex; sem_t empty; sem_t full; bufor_t; main(int argc,char *argv[]) { int i,stat,k, pid, size, fd,res; bufor_t *wbuf ; char c; // Utworzenie segmentu --------------------------- shm_unlink("bufor"); if((fd=shm_open("bufor", O_RDWR O_CREAT, 0774)) == -1){ perror("open"); exit(-1); printf("fd: %d\n",fd); size = ftruncate(fd, BSIZE); if(size < 0) {perror("trunc"); exit(-1); // Odwzorowanie segmentu fd w obszar pamieci procesow

J. Ułasiewicz Programowanie aplikacji współbieżnych 12 wbuf = (bufor_t *)mmap(0,bsize,prot_read PROT_WRITE, MAP_SHARED, fd, 0); if(wbuf == NULL) {perror("map"); exit(-1); // Inicjacja obszaru -------------------------------- wbuf-> cnt = 0; wbuf->head = 0; wbuf->tail = 0; if(sem_init(&(wbuf->mutex),1,1)){ perror("mutex");exit(0); if(sem_init(&(wbuf->empty),1,bsize)) { perror("empty"); exit(0); if(sem_init(&(wbuf->full),1,0)) { perror("full"); exit(0); // Tworzenie procesow ------------- if(fork() == 0) { // Producent for(i=0;i<10;i++) { // printf("producent: %i\n",i); printf("producent - cnt:%d head: %d tail: %d\n", wbuf-> cnt,wbuf->head,wbuf->tail); sem_wait(&(wbuf->empty)); sem_wait(&(wbuf->mutex)); sprintf(wbuf->buf[wbuf->head],"komunikat %d",i); wbuf-> cnt ++; wbuf->head = (wbuf->head +1) % BSIZE; sem_post(&(wbuf->mutex)); sem_post(&(wbuf->full)); sleep(1); shm_unlink("bufor"); exit(i); // Konsument ------------------ for(i=0;i<10;i++) { printf("konsument - cnt: %d odebrano %s\n",wbuf->cnt,wbuf->buf[wbuf->tail]); sem_wait(&(wbuf->full)); sem_wait(&(wbuf->mutex)); wbuf-> cnt --; wbuf->tail = (wbuf->tail +1) % BSIZE; sem_post(&(wbuf->mutex)); sem_post(&(wbuf->empty)); sleep(1);

J. Ułasiewicz Programowanie aplikacji współbieżnych 13 pid = wait(&stat); shm_unlink("bufor"); sem_close(&(wbuf->mutex)); sem_close(&(wbuf->empty)); sem_close(&(wbuf->full)); return 0; Przykład 9-2 Rozwiązanie problemu producenta i konsumenta za pomocą semaforów nienazwanych

J. Ułasiewicz Programowanie aplikacji współbieżnych 14 9.3 Rozwiązanie problemu producenta i konsumenta semafory nazwane Producenci P1 buf[bsize] BSIZE-1 Konsumenci K1 P2 Pk head x x x 3 2 1 0 tail K2 Km cnt segment pamieci dzielonej full mutex empty #include <sys/mman.h> #include <fcntl.h> #include <semaphore.h> #define BSIZE 4 // Rozmiar bufora #define LSIZE 80 // Dlugosc linii typedef struct { // Obszar wspólny char buf[bsize][lsize]; int head; int tail; int cnt; bufor_t; main(int argc,char *argv[]) { int i,stat,k, pid, size, fd,res; bufor_t *wbuf ; char c; sem_t *mutex; sem_t *empty; sem_t *full; // Utworzenie segmentu --------------------------- shm_unlink("bufor"); if((fd=shm_open("bufor", O_RDWR O_CREAT, 0774)) == -1){ perror("open"); exit(-1); printf("fd: %d\n",fd);

J. Ułasiewicz Programowanie aplikacji współbieżnych 15 size = ftruncate(fd, BSIZE); if(size < 0) {perror("trunc"); exit(-1); // Odwzorowanie segmentu fd w obszar pamieci procesow wbuf = ( bufor_t *)mmap(0,bsize, PROT_READ PROT_WRITE, MAP_SHARED, fd, 0); if(wbuf == NULL) {perror("map"); exit(-1); // Inicjacja obszaru -------------------------------- wbuf-> cnt = 0; wbuf->head = 0; wbuf->tail = 0; // Utworzenie semaforw ------------------------- mutex = sem_open("mutex",o_creat,s_irwxu,1); empty = sem_open("empty",o_creat,s_irwxu,bsize); full = sem_open("full",o_creat,s_irwxu,0); // Utworzenie procesow ------------------------- if(fork() == 0) { // Producent for(i=0;i<10;i++) { // printf("producent: %i\n",i); sem_wait(empty); sem_wait(mutex); printf("producent - cnt:%d head: %d tail: %d\n", wbuf-> cnt,wbuf->head,wbuf->tail); sprintf(wbuf->buf[wbuf->head],"komunikat %d",i); wbuf-> cnt ++; wbuf->head = (wbuf->head +1) % BSIZE; sem_post(mutex); sem_post(full); sleep(1); shm_unlink("bufor"); exit(i);

J. Ułasiewicz Programowanie aplikacji współbieżnych 16 // Konsument ------------------ for(i=0;i<10;i++) { sem_wait(full); sem_wait(mutex); printf("konsument - cnt: %d odebrano %s\n", wbuf->cnt,wbuf->buf[wbuf->tail]); wbuf-> cnt --; wbuf->tail = (wbuf->tail +1) % BSIZE; sem_post(mutex); sem_post(empty); sleep(1); pid = wait(&stat); shm_unlink("bufor"); sem_close(mutex); sem_close(empty); sem_close(full); sem_unlink("mutex"); sem_unlink("empty"); sem_unlink("full"); return 0; Przykład 9-3 Rozwiązanie problemu producenta i konsumenta za pomocą semaforów nazwanych

J. Ułasiewicz Programowanie aplikacji współbieżnych 17 9.4 Odwzorowanie plików w pamięci operacyjnej Pliki mogą być odwzorowane w pamięci. Wykonywane jest to za pomocą funkcji mmap. void *mmap(void * addr, size_t len, int prot, int flags, int fdes, off_t offset) addr Zmienna wskaźnikowa która sugeruje odkąd zacząć odwzorowanie w pamięci. Może być 0. len Wielkość odwzorowywanego obszaru. prot Specyfikacja dostępu do obszaru opisana w <sys/mman.h>. Może być PROT_READ, PROT_WRITE, PROT_EXEC flags Specyfikacja użycia segmentu, np. MAP_SHARED, MAP_PRIVATE fdes Uchwyt pliku. offset Początek pliku który ma być odwzorowany we wspólnej pamięci (musi to być wielokrotność strony 4K) Funkcja zwraca adres odwzorowanego obszaru lub 1 gdy błąd. stos bufor sterta BSS tekst obszar odwzorowany przestrzeń adresowa procesu offset plik Rys. 9-1 Odwzorowanie pliku w przestrzeni adresowej procesu len PROT_READ PROT_WRITE PROT_EXEC Strony mogą być czytane Strony mogą być pisane Strony mogą być wykonywane Zmienne addr i offset muszą być wyrównane do wielokrotności rozmiaru strony. Bajty znajdujące się pomiędzy ostatnią pozycją pliku a końcem strony będą ustawione na zero.

J. Ułasiewicz Programowanie aplikacji współbieżnych 18 Rozmiar strony może być uzyskany za pomocą funkcji sysconf #include <unistd.h> long sysconf(int name); name nazwa testowanego parametru Gdy name _SC_PAGESIZE podawana jest wielkość strony. Usunięcie odwzorowania następuje za pomocą funkcji: void *munmap(void * addr, size_t len) addr len Początek odwzorowania w pamięci. Wielkość odwzorowywanego obszaru. Zalety odwzorowania pliku w pamięci: Uniknięcie podwójnego buforowania Operacja szukania nie wymaga funkcji lseek a jedynie modyfikacji wskaźnika Wady: Dla małych plików następuje strata pamięci mremap mprotect msync Zmiana wielkości odwzorowania Zmiana typu dostepu Zapisanie na dysku zmian wykonanych w pamięci

J. Ułasiewicz Programowanie aplikacji współbieżnych 19 #include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> #include <fcntl.h> #include <sys/mman.h> #define FILEPATH "/tmp/mmapped.bin" #define NUMINTS (1000) #define FILESIZE (NUMINTS * sizeof(int)) int main(int argc, char *argv[]) { int i; int fd; int result; int *map; /* mmapped array of int's */ fd = open(filepath, O_RDWR O_CREAT O_TRUNC, (mode_t)0600); if (fd == -1) { perror("error opening file for writing"); exit(exit_failure); map = mmap(0, FILESIZE, PROT_READ PROT_WRITE, MAP_SHARED, fd, 0); if (map == MAP_FAILED) { close(fd); perror("error mmapping the file"); exit(exit_failure); for (i = 1; i <=NUMINTS; ++i) { map[i] = 2 * i; if (munmap(map, FILESIZE) == -1) { perror("error un-mmapping the file"); /* Decide here whether to close(fd) and exit() or not. Depends... */ close(fd); return 0; Przykład 9-4 Odwzorowanie pliku w pamięci operacyjnej