Uživatelské nástroje

Nástroje pro tento web


inter-process-comm

Toto je starší verze dokumentu!


Mezi-procesová komunikace

  • sdílená paměť
  • nepojmenovaná roura (pipe)
  • pojmenovaná roura
  • unix soket
  • POSIX_Message_Queues
  • DBus

Sdílená paměť

  • POSIX Shared Memory Operations 1 2
    • 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
  • System V Shared Memory Functions 1 2
    • 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 id
  • semop - provádí operace se smaforem
  • semafor prý existuje, i když všechny procesy skončí!!!
    • lze vypsat přes ipcs -s
  • existuje c++ třída mutex

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říkazem read
  • 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 errno nastaví na EAGAIN
  • 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.1463574731.txt.gz · Poslední úprava: (upraveno mimo DokuWiki)

Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki