4. Łącza

4.1. Łącza nienazwane

Listing 4.1: Przykład użycia łącza nienazwanego w komunikacji przodek-potomek (str. 26)

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
main() {
   int pdesk[2];

   if (pipe(pdesk) == -1){
      perror("Tworzenie potoku");
      exit(1);
   }

   switch(fork()){
      case -1:    // blad w tworzeniu procesu
         perror("Tworzenie procesu");
         exit(1);
      case 0:     // proces potomny
         if (write(pdesk[1], "Hallo!", 7) == -1){
            perror("Zapis do potoku");
            exit(1);
         }
         exit(0);
      default: {  // proces macierzysty
         char buf[10];
         if (read(pdesk[0], buf, 10) == -1){
            perror("Odczyt z potoku");
            exit(1);
         }
         printf("Odczytano z potoku: %s\n", buf);
      }
   }
}

Listing 4.2: Przykład odczytu z pustego łącza (str. 27)

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
main() {
   int pdesk[2];

   pipe(pdesk);

   if (fork() == 0){ // proces potomny
      write(pdesk[1], "Hallo!", 7); 
      exit(0);
   }
   else { // proces macierzysty
      char buf[10];
      read(pdesk[0], buf, 10);
      read(pdesk[0], buf, 10);
      printf("Odczytano z potoku: %s\n", buf);
   }
}

Listing 4.3: Konwersja wyniku polecenia ls (str. 27)

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#define MAX 512

main(int argc, char* argv[]) {
   int pdesk[2];

   if (pipe(pdesk) == -1){
      perror("Tworzenie potoku");
      exit(1);
   }

   switch(fork()){
      case -1: // blad w tworzeniu procesu
         perror("Tworzenie procesu");
         exit(1);
      case 0: // proces potomny
         dup2(pdesk[1], 1);
         execvp("ls", argv);
         perror("Uruchomienie programu ls");
         exit(1);
      default: { // proces macierzysty
         char buf[MAX];
         int lb, i;

         close(pdesk[1]);
         while ((lb=read(pdesk[0], buf, MAX)) > 0){
            for(i=0; i<lb; i++)
               buf[i] = toupper(buf[i]);
            if (write(1, buf, lb) == -1){
               perror ("Zapis na standardowe wyjscie");
               exit(1);
            }
         }
         if (lb == -1){
            perror("Odczyt z potoku");
            exit(1);
         }
      }
   }
}

Listing 4.4: Programowa realizacja potoku ls | tr a-z A-Z na łączu nienazwanym (str. 28)

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
main(int argc, char* argv[]) {
   int pdesk[2];

   if (pipe(pdesk) == -1){
      perror("Tworzenie potoku");
      exit(1);
   }

   switch(fork()){
      case -1: // blad w tworzeniu procesu
         perror("Tworzenie procesu");
         exit(1);
      case 0: // proces potomny
         dup2(pdesk[1], 1);
         execvp("ls", argv);
         perror("Uruchomienie programu ls");
         exit(1);
      default: { // proces macierzysty
         close(pdesk[1]);
         dup2(pdesk[0], 0);
         execlp("tr", "tr", "a-z", "A-Z", 0);
         perror("Uruchomienie programu tr");
         exit(1);
      }
   }
}

4.2. Łącza nazwane

Listing 4.5: Przykład tworzenie i otwierania łącza nazwanego (str. 29)

#include <fcntl.h>

main(){
   mkfifo("kolFIFO", 0600);
   open("kolFIFO", O_RDONLY);
}

Listing 4.6: Przykład tworzenie i otwierania łącza nazwanego (str. 29)

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>

main() {
   int pdesk;

   if (mkfifo("/tmp/fifo", 0600) == -1){
      perror("Tworzenie kolejki FIFO");
      exit(1);
   }

   switch(fork()){
      case -1: // blad w tworzeniu procesu
         perror("Tworzenie procesu");
         exit(1);
      case 0:
         pdesk = open("/tmp/fifo", O_WRONLY);
         if (pdesk == -1){
            perror("Otwarcie potoku do zapisu");
            exit(1);
         }
         if (write(pdesk, "Hallo!", 7) == -1){
            perror("Zapis do potoku");
            exit(1);
         }
         exit(0);
      default: {
         char buf[10];

         pdesk = open("/tmp/fifo", O_RDONLY);
         if (pdesk == -1){
            perror("Otwarcie potoku do odczytu");
            exit(1);
         }
         if (read(pdesk, buf, 10) == -1){
            perror("Odczyt z potoku");
            exit(1);
         }
         printf("Odczytano z potoku: %s\n", buf);
      }
   }
}

Listing 4.7: Programowa realizacja potoku ls | tr a-z A-Z na łączu nazwanym (str. 30)

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>

main(int argc, char* argv[]) {
   int pdesk;

   if (mkfifo("/tmp/fifo", 0600) == -1){
      perror("Tworzenie kolejki FIFO");
      exit(1);
   }

   switch(fork()){
      case -1: // blad w tworzeniu procesu
         perror("Tworzenie procesu");
         exit(1);
      case 0: // proces potomny
         close(1);
         pdesk = open("/tmp/fifo", O_WRONLY);
         if (pdesk == -1){
            perror("Otwarcie potoku do zapisu");
            exit(1);
         }
         else if (pdesk != 1){
            fprintf(stderr, "Niewlasciwy deskryptor do zapisu\n");
            exit(1);
         }
         execvp("ls", argv);
         perror("Uruchomienie programu ls");
         exit(1);
      default: { // proces macierzysty
         close(0);
         pdesk = open("/tmp/fifo", O_RDONLY);
         if (pdesk == -1){
            perror("Otwarcie potoku do odczytu");
            exit(1);
         }
         else if (pdesk != 0){
            fprintf(stderr, "Niewlasciwy deskryptor do odczytu\n");
            exit(1);
         }
         execlp("tr", "tr", "a-z", "A-Z", 0);
         perror("Uruchomienie programu tr");
         exit(1);
      }
   }
}

Listing 4.8: Możliwość zakleszczenia w operacji na łączu nienazwanym (str. 32)

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#define MAX 512

main(int argc, char* argv[]) {
   int pdesk[2];

   if (pipe(pdesk) == -1){
      perror("Tworzenie potoku");
      exit(1);
   }

   if (fork() == 0){ // proces potomny
      dup2(pdesk[1], 1);
      execvp("ls", argv);
      perror("Uruchomienie programu ls");
      exit(1);
   }
   else { // proces macierzysty
      char buf[MAX];
      int lb, i;

      close(pdesk[1]);
      wait(0);
      while ((lb=read(pdesk[0], buf, MAX)) > 0){
         for(i=0; i<lb; i++)
            buf[i] = toupper(buf[i]);
         write(1, buf, lb);
      }
   }
}

Listing 4.9: Możliwość zakleszczenia przy otwieraniu łącza nazwanego (str. 32)

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>

#define MAX 512

main(int argc, char* argv[]) {
   int pdesk;

   if (mkfifo("/tmp/fifo", 0600) == -1){
      perror("Tworzenie kolejki FIFO");
      exit(1);
   }

   if (fork() == 0){ // proces potomny
      close(1);
      open("/tmp/fifo", O_WRONLY);
      execvp("ls", argv);
      perror("Uruchomienie programu ls");
      exit(1);
   }
   else { // proces macierzysty
      char buf[MAX];
      int lb, i;

      wait(0);
      pdesk = open("/tmp/fifo", O_RDONLY);
      while ((lb=read(pdesk, buf, MAX)) > 0){
         for(i=0; i<lb; i++)
            buf[i] = toupper(buf[i]);
         write(1, buf, lb);
      }
   }
}

Spis treści

Poprzedni temat

3. Procesy

Następny temat

5. IPC

Ta strona