Komunikasi Proses Antar - Pipa Bernama

Pipa dimaksudkan untuk komunikasi antara proses terkait. Bisakah kita menggunakan pipa untuk komunikasi proses yang tidak terkait, katakanlah, kita ingin menjalankan program klien dari satu terminal dan program server dari terminal lain? Jawabannya adalah Tidak. Lalu bagaimana kita bisa mencapai proses komunikasi yang tidak terkait, jawaban sederhananya adalah Named Pipes. Meskipun ini berfungsi untuk proses terkait, tidak ada artinya menggunakan pipa bernama untuk komunikasi proses terkait.

Kami menggunakan satu pipa untuk komunikasi satu arah dan dua pipa untuk komunikasi dua arah. Apakah kondisi yang sama berlaku untuk Pipa Bernama. Jawabannya tidak, kita dapat menggunakan pipa bernama tunggal yang dapat digunakan untuk komunikasi dua arah (komunikasi antara server dan klien, ditambah klien dan server pada saat yang sama) karena Named Pipe mendukung komunikasi dua arah.

Nama lain untuk pipa bernama adalah FIFO (First-In-First-Out). Mari kita lihat pemanggilan sistem (mknod ()) untuk membuat pipa bernama, yang merupakan sejenis file khusus.

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

int mknod(const char *pathname, mode_t mode, dev_t dev);

Panggilan sistem ini akan membuat file khusus atau node sistem file seperti file biasa, file perangkat, atau FIFO. Argumen untuk panggilan sistem adalah nama jalur, mode, dan dev. Nama jalur beserta atribut mode dan informasi perangkat. Pathname bersifat relatif, jika direktori tidak ditentukan maka akan dibuat di direktori saat ini. Mode yang ditentukan adalah mode file yang menentukan jenis file seperti jenis file dan mode file seperti yang disebutkan dalam tabel berikut. Bidang dev adalah untuk menentukan informasi perangkat seperti nomor perangkat mayor dan minor.

Jenis File Deskripsi Jenis File Deskripsi
S_IFBLK blok khusus S_IFREG File biasa
S_IFCHR karakter spesial S_IFDIR Direktori
S_IFIFO FIFO khusus S_IFLNK Tautan Simbolik
Mode File Deskripsi Mode File Deskripsi
S_IRWXU Membaca, menulis, mengeksekusi / mencari menurut pemilik S_IWGRP Izin menulis, kelompok
S_IRUSR Izin baca, pemilik S_IXGRP Jalankan / cari izin, kelompok
S_IWUSR Izin menulis, pemilik S_IRWXO Membaca, menulis, mengeksekusi / mencari oleh orang lain
S_IXUSR Jalankan / cari izin, pemilik S_IROTH Izin baca, lainnya
S_IRWXG Membaca, menulis, mengeksekusi / mencari menurut kelompok S_IWOTH Izin menulis, orang lain
S_IRGRP Izin baca, kelompok S_IXOTH Izin eksekusi / pencarian, lainnya

Mode file juga dapat direpresentasikan dalam notasi oktal seperti 0XYZ, di mana X mewakili pemilik, Y mewakili grup, dan Z mewakili orang lain. Nilai X, Y atau Z dapat berkisar dari 0 sampai 7. Nilai untuk baca, tulis dan eksekusi masing-masing adalah 4, 2, 1. Jika diperlukan dalam kombinasi baca, tulis, dan eksekusi, tambahkan nilai yang sesuai.

Katakanlah, jika kita menyebutkan, 0640, maka ini berarti baca dan tulis (4 + 2 = 6) untuk pemilik, baca (4) untuk grup dan tidak ada izin (0) untuk orang lain.

Panggilan ini akan mengembalikan nol jika berhasil dan -1 jika gagal. Untuk mengetahui penyebab kegagalan, periksa dengan variabel errno atau fungsi perror ().

#include <sys/types.h>
#include <sys/stat.h>

int mkfifo(const char *pathname, mode_t mode)

Fungsi pustaka ini membuat file khusus FIFO, yang digunakan untuk pipa bernama. Argumen untuk fungsi ini adalah nama file dan mode. Nama file dapat berupa jalur absolut atau jalur relatif. Jika nama path lengkap (atau path absolut) tidak diberikan, file akan dibuat di folder saat ini dari proses eksekusi. Informasi mode file seperti yang dijelaskan dalam panggilan sistem mknod ().

Panggilan ini akan mengembalikan nol jika berhasil dan -1 jika gagal. Untuk mengetahui penyebab kegagalan, periksa dengan variabel errno atau fungsi perror ().

Mari kita pertimbangkan program menjalankan server di satu terminal dan menjalankan klien di terminal lain. Program hanya akan melakukan komunikasi satu arah. Klien menerima input pengguna dan mengirim pesan ke server, server mencetak pesan pada output. Proses dilanjutkan hingga pengguna memasukkan string “end”.

Mari kita pahami ini dengan sebuah contoh -

Step 1 - Buat dua proses, satu adalah fifoserver dan yang lainnya adalah fifoclient.

Step 2 - Proses server melakukan hal berikut -

  • Membuat pipa bernama (menggunakan system call mknod ()) dengan nama "MYFIFO", jika tidak dibuat.

  • Membuka pipa bernama untuk tujuan hanya baca.

  • Di sini, dibuat FIFO dengan izin baca dan tulis untuk Pemilik. Baca untuk Grup dan tidak ada izin untuk Orang Lain.

  • Menunggu pesan dari Klien tanpa batas.

  • Jika pesan yang diterima dari klien tidak "berakhir", cetak pesan tersebut. Jika pesannya adalah "end", tutup fifo tersebut dan akhiri prosesnya.

Step 3 - Proses klien melakukan hal berikut -

  • Membuka pipa bernama untuk tujuan menulis saja.

  • Menerima string dari pengguna.

  • Memeriksa, apakah pengguna memasukkan "akhir" atau selain "akhir". Either way, itu mengirim pesan ke server. Namun, jika stringnya adalah "end", ini menutup FIFO dan juga mengakhiri prosesnya.

  • Berulang tanpa batas sampai pengguna memasukkan string "akhir".

Sekarang mari kita lihat file server FIFO.

/* Filename: fifoserver.c */
#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>

#define FIFO_FILE "MYFIFO"
int main() {
   int fd;
   char readbuf[80];
   char end[10];
   int to_end;
   int read_bytes;
   
   /* Create the FIFO if it does not exist */
   mknod(FIFO_FILE, S_IFIFO|0640, 0);
   strcpy(end, "end");
   while(1) {
      fd = open(FIFO_FILE, O_RDONLY);
      read_bytes = read(fd, readbuf, sizeof(readbuf));
      readbuf[read_bytes] = '\0';
      printf("Received string: \"%s\" and length is %d\n", readbuf, (int)strlen(readbuf));
      to_end = strcmp(readbuf, end);
      if (to_end == 0) {
         close(fd);
         break;
      }
   }
   return 0;
}

Langkah Kompilasi dan Eksekusi

Received string: "this is string 1" and length is 16
Received string: "fifo test" and length is 9
Received string: "fifo client and server" and length is 22
Received string: "end" and length is 3

Sekarang, mari kita lihat kode contoh klien FIFO.

/* Filename: fifoclient.c */
#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>

#define FIFO_FILE "MYFIFO"
int main() {
   int fd;
   int end_process;
   int stringlen;
   char readbuf[80];
   char end_str[5];
   printf("FIFO_CLIENT: Send messages, infinitely, to end enter \"end\"\n");
   fd = open(FIFO_FILE, O_CREAT|O_WRONLY);
   strcpy(end_str, "end");
   
   while (1) {
      printf("Enter string: ");
      fgets(readbuf, sizeof(readbuf), stdin);
      stringlen = strlen(readbuf);
      readbuf[stringlen - 1] = '\0';
      end_process = strcmp(readbuf, end_str);
      
      //printf("end_process is %d\n", end_process);
      if (end_process != 0) {
         write(fd, readbuf, strlen(readbuf));
         printf("Sent string: \"%s\" and string length is %d\n", readbuf, (int)strlen(readbuf));
      } else {
         write(fd, readbuf, strlen(readbuf));
         printf("Sent string: \"%s\" and string length is %d\n", readbuf, (int)strlen(readbuf));
         close(fd);
         break;
      }
   }
   return 0;
}

Mari kita lihat keluaran yang akan datang.

Langkah Kompilasi dan Eksekusi

FIFO_CLIENT: Send messages, infinitely, to end enter "end"
Enter string: this is string 1
Sent string: "this is string 1" and string length is 16
Enter string: fifo test
Sent string: "fifo test" and string length is 9
Enter string: fifo client and server
Sent string: "fifo client and server" and string length is 22
Enter string: end
Sent string: "end" and string length is 3

Komunikasi Dua Arah Menggunakan Pipa Bernama

Komunikasi antar pipa dimaksudkan searah. Pipa dibatasi untuk komunikasi satu arah secara umum dan membutuhkan setidaknya dua pipa untuk komunikasi dua arah. Pipa dimaksudkan hanya untuk proses yang saling terkait. Pipa tidak dapat digunakan untuk komunikasi proses yang tidak terkait, katakanlah, jika kita ingin mengeksekusi satu proses dari satu terminal dan proses lain dari terminal lain, tidak mungkin dengan pipa. Apakah kita memiliki cara sederhana untuk berkomunikasi antara dua proses, katakanlah proses yang tidak terkait dengan cara yang sederhana? Jawabannya iya. Pipa bernama dimaksudkan untuk komunikasi antara dua atau lebih proses yang tidak terkait dan juga dapat memiliki komunikasi dua arah.

Kita telah melihat komunikasi satu arah antara pipa bernama, yaitu pesan dari klien ke server. Sekarang, mari kita lihat komunikasi dua arah yaitu, klien mengirim pesan ke server dan server menerima pesan dan mengirim kembali pesan lain ke klien menggunakan pipa bernama yang sama.

Berikut adalah contohnya -

Step 1 - Buat dua proses, satu adalah fifoserver_twoway dan satu lagi adalah fifoclient_twoway.

Step 2 - Proses server melakukan hal berikut -

  • Membuat pipa bernama (menggunakan fungsi perpustakaan mkfifo ()) dengan nama "fifo_twoway" di direktori / tmp, jika tidak dibuat.

  • Membuka pipa bernama untuk tujuan baca dan tulis.

  • Di sini, dibuat FIFO dengan izin baca dan tulis untuk Pemilik. Baca untuk Grup dan tidak ada izin untuk Orang Lain.

  • Menunggu pesan dari klien tanpa batas.

  • Jika pesan yang diterima dari klien tidak "berakhir", mencetak pesan dan membalikkan string. String yang dibalik dikirim kembali ke klien. Jika pesannya adalah "end", tutup fifo dan akhiri prosesnya.

Step 3 - Proses klien melakukan hal berikut -

  • Membuka pipa bernama untuk tujuan baca dan tulis.

  • Menerima string dari pengguna.

  • Memeriksa, apakah pengguna memasukkan "akhir" atau selain "akhir". Either way, itu mengirim pesan ke server. Namun, jika stringnya adalah "end", ini menutup FIFO dan juga mengakhiri prosesnya.

  • Jika pesan dikirim sebagai bukan "akhir", itu menunggu pesan (string terbalik) dari klien dan mencetak string terbalik.

  • Berulang tanpa batas sampai pengguna memasukkan string "akhir".

Sekarang, mari kita lihat kode sampel server FIFO.

/* Filename: fifoserver_twoway.c */
#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>

#define FIFO_FILE "/tmp/fifo_twoway"
void reverse_string(char *);
int main() {
   int fd;
   char readbuf[80];
   char end[10];
   int to_end;
   int read_bytes;
   
   /* Create the FIFO if it does not exist */
   mkfifo(FIFO_FILE, S_IFIFO|0640);
   strcpy(end, "end");
   fd = open(FIFO_FILE, O_RDWR);
   while(1) {
      read_bytes = read(fd, readbuf, sizeof(readbuf));
      readbuf[read_bytes] = '\0';
      printf("FIFOSERVER: Received string: \"%s\" and length is %d\n", readbuf, (int)strlen(readbuf));
      to_end = strcmp(readbuf, end);
      
      if (to_end == 0) {
         close(fd);
         break;
      }
      reverse_string(readbuf);
      printf("FIFOSERVER: Sending Reversed String: \"%s\" and length is %d\n", readbuf, (int) strlen(readbuf));
      write(fd, readbuf, strlen(readbuf));
      /*
      sleep - This is to make sure other process reads this, otherwise this
      process would retrieve the message
      */
      sleep(2);
   }
   return 0;
}

void reverse_string(char *str) {
   int last, limit, first;
   char temp;
   last = strlen(str) - 1;
   limit = last/2;
   first = 0;
   
   while (first < last) {
      temp = str[first];
      str[first] = str[last];
      str[last] = temp;
      first++;
      last--;
   }
   return;
}

Langkah Kompilasi dan Eksekusi

FIFOSERVER: Received string: "LINUX IPCs" and length is 10
FIFOSERVER: Sending Reversed String: "sCPI XUNIL" and length is 10
FIFOSERVER: Received string: "Inter Process Communication" and length is 27
FIFOSERVER: Sending Reversed String: "noitacinummoC ssecorP retnI" and length is 27
FIFOSERVER: Received string: "end" and length is 3

Sekarang, mari kita lihat kode contoh klien FIFO.

/* Filename: fifoclient_twoway.c */
#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>

#define FIFO_FILE "/tmp/fifo_twoway"
int main() {
   int fd;
   int end_process;
   int stringlen;
   int read_bytes;
   char readbuf[80];
   char end_str[5];
   printf("FIFO_CLIENT: Send messages, infinitely, to end enter \"end\"\n");
   fd = open(FIFO_FILE, O_CREAT|O_RDWR);
   strcpy(end_str, "end");
   
   while (1) {
      printf("Enter string: ");
      fgets(readbuf, sizeof(readbuf), stdin);
      stringlen = strlen(readbuf);
      readbuf[stringlen - 1] = '\0';
      end_process = strcmp(readbuf, end_str);
      
      //printf("end_process is %d\n", end_process);
      if (end_process != 0) {
         write(fd, readbuf, strlen(readbuf));
         printf("FIFOCLIENT: Sent string: \"%s\" and string length is %d\n", readbuf, (int)strlen(readbuf));
         read_bytes = read(fd, readbuf, sizeof(readbuf));
         readbuf[read_bytes] = '\0';
         printf("FIFOCLIENT: Received string: \"%s\" and length is %d\n", readbuf, (int)strlen(readbuf));
      } else {
         write(fd, readbuf, strlen(readbuf));
         printf("FIFOCLIENT: Sent string: \"%s\" and string length is %d\n", readbuf, (int)strlen(readbuf));
         close(fd);
         break;
      }
   }
   return 0;
}

Langkah Kompilasi dan Eksekusi

FIFO_CLIENT: Send messages, infinitely, to end enter "end"
Enter string: LINUX IPCs
FIFOCLIENT: Sent string: "LINUX IPCs" and string length is 10
FIFOCLIENT: Received string: "sCPI XUNIL" and length is 10
Enter string: Inter Process Communication
FIFOCLIENT: Sent string: "Inter Process Communication" and string length is 27
FIFOCLIENT: Received string: "noitacinummoC ssecorP retnI" and length is 27
Enter string: end
FIFOCLIENT: Sent string: "end" and string length is 3