Komunikasi Proses Antar - Pipa

Pipa adalah media komunikasi antara dua atau lebih proses yang berhubungan atau saling terkait. Ini dapat berupa dalam satu proses atau komunikasi antara anak dan proses induk. Komunikasi juga bisa bertingkat seperti komunikasi antara orang tua, anak dan cucu, dll. Komunikasi dicapai dengan satu proses menulis ke dalam pipa dan membaca lainnya dari pipa. Untuk mencapai panggilan sistem pipa, buat dua file, satu untuk menulis ke dalam file dan satu lagi untuk dibaca dari file.

Mekanisme pipa dapat dilihat dengan skenario real-time seperti mengisi air dengan pipa ke beberapa wadah, misalnya ember, dan seseorang mengambilnya, misalnya dengan cangkir. Proses pengisian tidak lain adalah menulis ke dalam pipa dan proses membaca tidak lain adalah mengambil dari pipa. Ini berarti bahwa satu keluaran (air) adalah masukan untuk yang lainnya (ember).

#include<unistd.h>

int pipe(int pipedes[2]);

Panggilan sistem ini akan membuat pipa untuk komunikasi satu arah, yaitu membuat dua deskriptor, yang pertama dihubungkan untuk membaca dari pipa dan yang lainnya terhubung untuk menulis ke dalam pipa.

Descriptor pipedes [0] untuk membaca dan pipedes [1] untuk menulis. Apa pun yang ditulis ke dalam pipedes [1] dapat dibaca dari pipedes [0].

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>
#include <fcntl.h>

int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode);

Meskipun operasi dasar untuk file adalah membaca dan menulis, sangatlah penting untuk membuka file sebelum melakukan operasi dan menutup file setelah menyelesaikan operasi yang diperlukan. Biasanya, secara default, 3 deskriptor dibuka untuk setiap proses, yang digunakan untuk input (input standar - stdin), output (output standar - stdout) dan kesalahan (kesalahan standar - stderr) yang masing-masing memiliki deskriptor file 0, 1 dan 2.

Panggilan sistem ini akan mengembalikan deskriptor file yang digunakan untuk operasi file lebih lanjut dari read / write / seek (lseek). Biasanya deskriptor file mulai dari 3 dan bertambah satu angka seiring dengan jumlah file yang dibuka.

Argumen yang diteruskan ke panggilan sistem terbuka adalah nama jalur (jalur relatif atau absolut), tanda yang menyebutkan tujuan membuka file (misalnya, membuka untuk dibaca, O_RDONLY, untuk menulis, O_WRONLY, untuk membaca dan menulis, O_RDWR, untuk ditambahkan ke file yang ada O_APPEND, untuk membuat file, jika tidak ada dengan O_CREAT dan sebagainya) dan mode yang diperlukan memberikan izin baca / tulis / eksekusi untuk pengguna atau pemilik / grup / orang lain. Modus bisa disebutkan dengan simbol.

Baca - 4, Tulis - 2 dan Jalankan - 1.

Sebagai contoh: Nilai oktal (dimulai dengan 0), 0764 berarti pemilik memiliki izin baca, tulis, dan eksekusi, grup memiliki izin baca dan tulis, lainnya memiliki izin baca. Ini juga dapat direpresentasikan sebagai S_IRWXU | S_IRGRP | S_IWGRP | S_IROTH, yang menyiratkan atau pengoperasian 0700 | 0040 | 0020 | 0004 → 0764.

Panggilan sistem ini, jika berhasil, mengembalikan id deskriptor file baru dan -1 jika terjadi kesalahan. Penyebab error dapat diidentifikasi dengan variabel errno atau fungsi perror ().

#include<unistd.h>

int close(int fd)

Penutupan panggilan sistem di atas sudah membuka deskriptor file. Ini menyiratkan bahwa file tersebut tidak lagi digunakan dan sumber daya yang terkait dapat digunakan kembali oleh proses lain. Panggilan sistem ini mengembalikan nol saat berhasil dan -1 jika terjadi kesalahan. Penyebab error dapat diidentifikasi dengan variabel errno atau fungsi perror ().

#include<unistd.h>

ssize_t read(int fd, void *buf, size_t count)

Panggilan sistem di atas adalah untuk membaca dari file yang ditentukan dengan argumen deskriptor file fd, buffer yang sesuai dengan memori yang dialokasikan (baik statis atau dinamis) dan ukuran buffer.

Id deskriptor file adalah untuk mengidentifikasi file masing-masing, yang dikembalikan setelah memanggil panggilan sistem open () atau pipe (). File harus dibuka sebelum membaca dari file. Ini secara otomatis terbuka jika memanggil system call pipe ().

Panggilan ini akan mengembalikan jumlah byte yang dibaca (atau nol jika menemui akhir file) saat berhasil dan -1 jika gagal. Byte yang dikembalikan bisa lebih kecil dari jumlah byte yang diminta, jika tidak ada data yang tersedia atau file ditutup. Nomor kesalahan yang benar diatur jika terjadi kegagalan.

Untuk mengetahui penyebab kegagalan, periksa dengan variabel errno atau fungsi perror ().

#include<unistd.h>

ssize_t write(int fd, void *buf, size_t count)

Panggilan sistem di atas adalah untuk menulis ke file yang ditentukan dengan argumen dari deskriptor file fd, buffer yang tepat dengan memori yang dialokasikan (baik statis atau dinamis) dan ukuran buffer.

Id deskriptor file adalah untuk mengidentifikasi file masing-masing, yang dikembalikan setelah memanggil panggilan sistem open () atau pipe ().

File harus dibuka sebelum menulis ke file. Ini secara otomatis terbuka jika memanggil system call pipe ().

Panggilan ini akan mengembalikan jumlah byte yang ditulis (atau nol jika tidak ada yang ditulis) saat berhasil dan -1 jika gagal. Nomor kesalahan yang benar diatur jika terjadi kegagalan.

Untuk mengetahui penyebab kegagalan, periksa dengan variabel errno atau fungsi perror ().

Program Contoh

Berikut adalah beberapa contoh program.

Example program 1 - Program untuk menulis dan membaca dua pesan menggunakan pipa.

Algoritma

Step 1 - Buat pipa.

Step 2 - Kirim pesan ke pipa.

Step 3 - Ambil pesan dari pipa dan tulis ke output standar.

Step 4 - Kirim pesan lain ke pipa.

Step 5 - Ambil pesan dari pipa dan tulis ke output standar.

Note - Pengambilan pesan juga bisa dilakukan setelah mengirim semua pesan.

Source Code: simplepipe.c

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

int main() {
   int pipefds[2];
   int returnstatus;
   char writemessages[2][20]={"Hi", "Hello"};
   char readmessage[20];
   returnstatus = pipe(pipefds);
   
   if (returnstatus == -1) {
      printf("Unable to create pipe\n");
      return 1;
   }
   
   printf("Writing to pipe - Message 1 is %s\n", writemessages[0]);
   write(pipefds[1], writemessages[0], sizeof(writemessages[0]));
   read(pipefds[0], readmessage, sizeof(readmessage));
   printf("Reading from pipe – Message 1 is %s\n", readmessage);
   printf("Writing to pipe - Message 2 is %s\n", writemessages[0]);
   write(pipefds[1], writemessages[1], sizeof(writemessages[0]));
   read(pipefds[0], readmessage, sizeof(readmessage));
   printf("Reading from pipe – Message 2 is %s\n", readmessage);
   return 0;
}

Note- Idealnya, status pengembalian perlu diperiksa untuk setiap panggilan sistem. Untuk menyederhanakan proses, pemeriksaan tidak dilakukan untuk semua panggilan.

Langkah Eksekusi

Kompilasi

gcc -o simplepipe simplepipe.c

Eksekusi / Output

Writing to pipe - Message 1 is Hi
Reading from pipe – Message 1 is Hi
Writing to pipe - Message 2 is Hi
Reading from pipe – Message 2 is Hell

Example program 2 - Program untuk menulis dan membaca dua pesan melalui pipa menggunakan proses induk dan anak.

Algoritma

Step 1 - Buat pipa.

Step 2 - Buat proses anak.

Step 3 - Proses induk menulis ke pipa.

Step 4 - Proses anak mengambil pesan dari pipa dan menulisnya ke output standar.

Step 5 - Ulangi langkah 3 dan 4 sekali lagi.

Source Code: pipewithprocesses.c

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

int main() {
   int pipefds[2];
   int returnstatus;
   int pid;
   char writemessages[2][20]={"Hi", "Hello"};
   char readmessage[20];
   returnstatus = pipe(pipefds);
   if (returnstatus == -1) {
      printf("Unable to create pipe\n");
      return 1;
   }
   pid = fork();
   
   // Child process
   if (pid == 0) {
      read(pipefds[0], readmessage, sizeof(readmessage));
      printf("Child Process - Reading from pipe – Message 1 is %s\n", readmessage);
      read(pipefds[0], readmessage, sizeof(readmessage));
      printf("Child Process - Reading from pipe – Message 2 is %s\n", readmessage);
   } else { //Parent process
      printf("Parent Process - Writing to pipe - Message 1 is %s\n", writemessages[0]);
      write(pipefds[1], writemessages[0], sizeof(writemessages[0]));
      printf("Parent Process - Writing to pipe - Message 2 is %s\n", writemessages[1]);
      write(pipefds[1], writemessages[1], sizeof(writemessages[1]));
   }
   return 0;
}

Langkah Eksekusi

Compilation

gcc pipewithprocesses.c –o pipewithprocesses

Execution

Parent Process - Writing to pipe - Message 1 is Hi
Parent Process - Writing to pipe - Message 2 is Hello
Child Process - Reading from pipe – Message 1 is Hi
Child Process - Reading from pipe – Message 2 is Hello

Komunikasi Dua Arah Menggunakan Pipa

Komunikasi pipa dipandang hanya sebagai komunikasi satu arah yaitu, baik proses induk menulis dan proses anak membaca atau sebaliknya tetapi tidak keduanya. Namun, bagaimana jika orang tua dan anak perlu menulis dan membaca dari pipa secara bersamaan, solusinya adalah komunikasi dua arah menggunakan pipa. Dua pipa diperlukan untuk menjalin komunikasi dua arah.

Berikut adalah langkah-langkah untuk mencapai komunikasi dua arah -

Step 1- Buat dua pipa. Yang pertama adalah untuk orang tua untuk menulis dan anak untuk membaca, katakanlah sebagai pipa1. Yang kedua adalah untuk anak menulis dan orang tua untuk membaca, katakanlah sebagai pipa2.

Step 2 - Buat proses anak.

Step 3 - Tutup ujung yang tidak diinginkan karena hanya satu ujung yang dibutuhkan untuk setiap komunikasi.

Step 4 - Tutup ujung yang tidak diinginkan dalam proses induk, baca ujung pipa1 dan tulis ujung pipa2.

Step 5 - Tutup ujung yang tidak diinginkan pada proses anak, tulis ujung pipa1 dan baca ujung pipa2.

Step 6 - Lakukan komunikasi sesuai kebutuhan.

Program Sampel

Sample program 1 - Mewujudkan komunikasi dua arah dengan menggunakan pipa.

Algoritma

Step 1 - Buat pipa1 untuk proses induk untuk menulis dan proses anak untuk dibaca.

Step 2 - Buat pipa2 untuk proses anak untuk menulis dan proses induk untuk dibaca.

Step 3 - Tutup ujung pipa yang tidak diinginkan dari sisi induk dan anak.

Step 4 - Proses orang tua untuk menulis pesan dan proses anak untuk dibaca dan ditampilkan di layar.

Step 5 - Proses anak untuk menulis pesan dan proses orang tua untuk membaca dan menampilkan di layar.

Source Code: twowayspipe.c

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

int main() {
   int pipefds1[2], pipefds2[2];
   int returnstatus1, returnstatus2;
   int pid;
   char pipe1writemessage[20] = "Hi";
   char pipe2writemessage[20] = "Hello";
   char readmessage[20];
   returnstatus1 = pipe(pipefds1);
   
   if (returnstatus1 == -1) {
      printf("Unable to create pipe 1 \n");
      return 1;
   }
   returnstatus2 = pipe(pipefds2);
   
   if (returnstatus2 == -1) {
      printf("Unable to create pipe 2 \n");
      return 1;
   }
   pid = fork();
   
   if (pid != 0) // Parent process {
      close(pipefds1[0]); // Close the unwanted pipe1 read side
      close(pipefds2[1]); // Close the unwanted pipe2 write side
      printf("In Parent: Writing to pipe 1 – Message is %s\n", pipe1writemessage);
      write(pipefds1[1], pipe1writemessage, sizeof(pipe1writemessage));
      read(pipefds2[0], readmessage, sizeof(readmessage));
      printf("In Parent: Reading from pipe 2 – Message is %s\n", readmessage);
   } else { //child process
      close(pipefds1[1]); // Close the unwanted pipe1 write side
      close(pipefds2[0]); // Close the unwanted pipe2 read side
      read(pipefds1[0], readmessage, sizeof(readmessage));
      printf("In Child: Reading from pipe 1 – Message is %s\n", readmessage);
      printf("In Child: Writing to pipe 2 – Message is %s\n", pipe2writemessage);
      write(pipefds2[1], pipe2writemessage, sizeof(pipe2writemessage));
   }
   return 0;
}

Langkah Eksekusi

Kompilasi

gcc twowayspipe.c –o twowayspipe

Eksekusi

In Parent: Writing to pipe 1 – Message is Hi
In Child: Reading from pipe 1 – Message is Hi
In Child: Writing to pipe 2 – Message is Hello
In Parent: Reading from pipe 2 – Message is Hello