inter-process-comm
Toto je starší verze dokumentu!
Obsah
Mezi-procesová komunikace
- sdílená paměť
- nepojmenovaná roura (pipe)
- pojmenovaná roura
- unix soket
- POSIX_Message_Queues
- DBus
Sdílená paměť
-
- mmap(2) - Map a file or shared memory object into the address space.
- shm_open(2) - Create, or gain access to, a shared memory object.
- shm_unlink(2) - Destroy a shared memory object when no references to it remain open.
-
- všechny procesy mají přístup do paměti ihned
- začíná se voláním
shm_open - pro přístup do sdílené paměti musí procesy použít stejný name… což je string, například pathname
-
- shmget(2) - Create a shared memory IPC object or return the ID of one.
- shmctl(2) - Get the status of a shared memory segment, change permissions or user IDs, or lock or unlock a segment in memory.
- shmat(2) - Attach a shared memory segment to the address space.
- shmdt(2) - Detach a shared memory segment from the address space.
Zamykaní
- obecně existuje zámek (mutex) nebo semafor (semaphor)
- mutex
- pouze jeden proces/vlakno může vstoupit
- dá se říct, že je to semafor s číslem 1
- slouží k serializaci přístupu
- semafor
- nastaví se počet X, kolik procesů/vláken může max vstoupit
- slouží k omezení paralelního přístupu na max X
- identifikuje se číslem
- oprávnění se nastavuje 9 bitovým číslem (obdoba oprávnění u souboru), tedy například 666
semget- vytvoří, získá semafor s daným idsemop- provádí operace se smaforem- semafor prý existuje, i když všechny procesy skončí!!!
- lze vypsat přes ipcs -s
výborné čtení o meziprocesorové komunikaci, sdílené paměti, semaforech.... o sdílené, pěkné s příklady
Nepojmenovaná roura
- jednosměrná
- dva konce - producent a konzument
- do roury by měl zapisovat nebo z ní číst pouze jeden proces
- čtení je destruktivní (přečtení jedním procesem zruší možnost čtení procesem druhým)
- zápis/čtení do velikosti 'PIPE_BUF' by mělo být atomické (pokud do roury budou zapisovat dva procesy, tak zápisy do uvedené velikosti by se neměli pomíchat dohromady)
- roura se vytváří příkazem
pipe- parametrem je
int[2], kde index 0 je deskriptor pro zápis a index 1 pro čtení
- rouru je potřeba na konci uzavřít příkazem
close - zapisovat lze příkazem
write, číst příkazemread - při čtení z roury, zavřené na druhé straně, se přečte znak EOF
- při zápisu do roury, zavřené na druhé straně, se generuje signál SIGPIPE (ukončí běh aplikace)
#include <unistd.h> int pipefd[2]; pipe(pipefd); .. close(pipefd[0]); close(pipefd[1]);
Spojení s procesem jednosměrně
- poepen
- pclose
Spojení s procesem obousměrně
- vytvořit rouru ipipe pro jeden směr (rodič → potomek)
- vytvořit rouru opipe pro druhý směr (potomek → rodič)
- provést fork
- zavřít nepoužívané deskriptory
- v potomkovi zavřít deskriptor pro zápis do ipipe
- v potomkovi zavřít deskriptor pro čtení do opipe
- v rodiči zavřít deskriptor pro zápis do opipe
- v rodiči zavřít deskriptor pro čtení do ipipe
- ostatní deskriptory použít pro zpracování
- můžeme z nich číst/zapisovat
- můžeme je použít jako náhradu pro stdin (
STDIN_FILENO), stderr (STERR_FILENO) nebo stdout (STDOUT_FILENO)
Neblokující roura
- standardně je čtení a zápis blokující
- pro neblokující je potřeba změnit nastavení přes syscall
fcntl(pro každý konec roury)
// set non-blocking mode if (fcntl(pipe_fd, F_SETFL, fcntl(pipe_fd, F_GETFL) | O_NONBLOCK) == -1) { fprintf(stderr,"Cannot set non-blocking mode to pipe\n"); }
// set blocking mode if (fcntl(pipe_fd, F_SETFL, fcntl(pipe_fd, F_GETFL) & ~O_NONBLOCK) == -1) { fprintf(stderr,"Cannot set blocking mode to pipe\n"); }
- chování funkcí read a write se v non-blocking režimu mění
- pokud nejsou žádná data ke čtení, ale roura je pořád otevřena, vrátí funkce read chybovou návratovou hodnotu (-1) a
errnonastaví naEAGAIN - pro ověření, zda jsou data připravena pro zápis/čtení je vhodné používat nějakou funkci, například
select
struct timeval tv; fd_set rfds; fd_set wfds; int nfds; // set highest pipe FD +1 nfds = (pipefd[0]>pipefd[1])?pipefd[0]+1:pipefd[1]+1; while(...) { FD_ZERO(&rfds); FD_SET(pipefd[0],&rfds); FD_ZERO(&wfds); FD_SET(pipefd[1],&wfds); tv.tv_sec = 5; tv.tv_usec = 0; if (select(nfds, &rfds, &wfds, NULL, &tv) == -1) { fprintf(stderr,"pipe error %d\n", errno); } if (FD_ISSET(pipefd[0], &rfds)) { .. // do reading } .. }
inter-process-comm.1463574471.txt.gz · Poslední úprava: (upraveno mimo DokuWiki)
