الخميس، 1 أكتوبر 2020

الاتصال بين العمليات - الأنابيب المحددة

 

الاتصال بين العمليات - الأنابيب المحددة


الاتصال بين العمليات - الأنابيب المحددة


الإعلانات
Ad by Valueimpression

كانت الأنابيب مخصصة للتواصل بين العمليات ذات الصلة. هل يمكننا استخدام الأنابيب لاتصالات العمليات غير ذات الصلة ، على سبيل المثال ، نريد تنفيذ برنامج العميل من محطة طرفية وبرنامج الخادم من محطة طرفية أخرى؟ الجواب هو لا. فكيف يمكننا تحقيق اتصال غير ذي صلة بالعمليات ، والإجابة البسيطة هي الأنابيب المسماة. على الرغم من أن هذا يعمل مع العمليات ذات الصلة ، فإنه لا يعطي أي معنى لاستخدام الأنابيب المسماة لاتصالات العملية ذات الصلة.

استخدمنا أنبوبًا واحدًا للاتصال أحادي الاتجاه وأنبوبين للاتصال ثنائي الاتجاه. هل ينطبق نفس الشرط على الأنابيب المسماة. الإجابة هي لا ، يمكننا استخدام أنبوب واحد مسمى يمكن استخدامه للاتصال ثنائي الاتجاه (الاتصال بين الخادم والعميل ، بالإضافة إلى العميل والخادم في نفس الوقت) حيث يدعم Named Pipe الاتصال ثنائي الاتجاه.

اسم آخر للأنبوب المسمى FIFO (أول ما يدخل أولاً يخرج) . دعونا نرى استدعاء النظام (mknod ()) لإنشاء أنبوب مسمى ، وهو نوع من الملفات الخاصة.

#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);

سيؤدي استدعاء النظام هذا إلى إنشاء ملف خاص أو عقدة نظام ملفات مثل ملف عادي أو ملف جهاز أو FIFO. وسيطات استدعاء النظام هي اسم المسار والوضع و dev. اسم المسار مع سمات الوضع ومعلومات الجهاز. اسم المسار نسبي ، إذا لم يتم تحديد الدليل سيتم إنشاؤه في الدليل الحالي. الوضع المحدد هو وضع الملف الذي يحدد نوع الملف مثل نوع الملف ووضع الملف كما هو مذكور في الجداول التالية. مجال التطوير هو تحديد معلومات الجهاز مثل أرقام الأجهزة الرئيسية والثانوية.

نوع الملفوصفنوع الملفوصف
S_IFBLKكتلة خاصةS_IFREGملف عادي
S_IFCHRشخصية خاصةS_IFDIRالدليل
S_IFOFIFO خاصS_IFLNKارتباط رمزي
وضع الملفوصفوضع الملفوصف
S_IRWXUالقراءة والكتابة والتنفيذ / البحث من قبل المالكS_IWGRPإذن الكتابة ، المجموعة
S_IRUSRقراءة إذن المالكS_IXGRPتنفيذ / إذن بحث ، مجموعة
S_IWUSRإذن الكتابة ، المالكS_IRWXOالقراءة والكتابة والتنفيذ / البحث من قبل الآخرين
S_IXUSRتنفيذ / إذن البحث ، المالكS_IROTHقراءة إذن الآخرين
S_IRWXGالقراءة والكتابة والتنفيذ / البحث حسب المجموعةS_IWOTHإذن كتابة ، آخرون
S_IRGRPإذن قراءة ، مجموعةS_IXOTHتنفيذ / إذن بحث ، آخرون

يمكن أيضًا تمثيل وضع الملف بترميز ثماني مثل 0XYZ ، حيث يمثل X المالك ، ويمثل Y المجموعة ، ويمثل Z الآخرين. يمكن أن تتراوح قيمة X أو Y أو Z من 0 إلى 7. قيم القراءة والكتابة والتنفيذ هي 4 ، 2 ، 1 على التوالي. إذا لزم الأمر مع مجموعة القراءة والكتابة والتنفيذ ، فقم بإضافة القيم وفقًا لذلك.

لنفترض ، إذا ذكرنا ، 0640 ، فهذا يعني القراءة والكتابة (4 + 2 = 6) للمالك ، اقرأ (4) للمجموعة ولا توجد أذونات (0) للآخرين.

هذه المكالمة سترجع صفرًا عند النجاح و -1 في حالة الفشل. لمعرفة سبب الفشل ، تحقق من متغير errno أو وظيفة perror ().

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

int mkfifo(const char *pathname, mode_t mode)

تنشئ وظيفة المكتبة هذه ملفًا خاصًا يرد أولاً يصدر أولاً (FIFO) ، والذي يستخدم لأنبوب الإخراج المسمى. وسيطات هذه الوظيفة هي اسم الملف والوضع. يمكن أن يكون اسم الملف إما مسار مطلق أو مسار نسبي. إذا لم يتم إعطاء اسم المسار الكامل (أو المسار المطلق) ، فسيتم إنشاء الملف في المجلد الحالي لعملية التنفيذ. معلومات وضع الملف كما هو موضح في استدعاء نظام mknod ().

هذه المكالمة سترجع صفرًا عند النجاح و -1 في حالة الفشل. لمعرفة سبب الفشل ، تحقق من متغير errno أو وظيفة perror ().

دعونا نفكر في برنامج لتشغيل الخادم على محطة واحدة وتشغيل العميل على محطة أخرى. سيقوم البرنامج بإجراء اتصال أحادي الاتجاه فقط. يقبل العميل إدخال المستخدم ويرسل الرسالة إلى الخادم ، ويطبع الخادم الرسالة على الإخراج. تستمر العملية حتى يقوم المستخدم بإدخال السلسلة "end".

دعونا نفهم هذا بمثال -

الخطوة 1 - قم بإنشاء عمليتين ، إحداهما فيفوسيرفير والأخرى هي فيفو كلينت.

الخطوة 2 - تقوم عملية الخادم بما يلي -

  • ينشئ أنبوبًا مسمىًا (باستخدام استدعاء النظام mknod ()) باسم "MYFIFO" ، إذا لم يتم إنشاؤه.

  • يفتح الأنبوب المحدد لأغراض القراءة فقط.

  • هنا ، تم إنشاء FIFO مع أذونات القراءة والكتابة للمالك. اقرأ للمجموعة ولا توجد أذونات للآخرين.

  • ينتظر بلا حدود لرسالة من العميل.

  • إذا كانت الرسالة المستلمة من العميل ليست "إنهاء" ، فسيتم طباعة الرسالة. إذا كانت الرسالة "end" ، يغلق FIFA وينهي العملية.

الخطوة 3 - عملية العميل تؤدي ما يلي -

  • يفتح الأنبوب المحدد لأغراض الكتابة فقط.

  • يقبل السلسلة من المستخدم.

  • الشيكات ، إذا أدخل المستخدم "نهاية" أو غير "نهاية". في كلتا الحالتين ، فإنه يرسل رسالة إلى الخادم. ومع ذلك ، إذا كانت السلسلة "end" ، فهذا يؤدي إلى إغلاق FIFO وأيضًا إنهاء العملية.

  • يتكرر بلا حدود حتى يدخل المستخدم السلسلة "end".

الآن دعونا نلقي نظرة على ملف خادم 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;
}

خطوات التجميع والتنفيذ

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

الآن ، دعنا نلقي نظرة على نموذج كود العميل 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;
}

لنأخذ a عند وصول الناتج.

خطوات التجميع والتنفيذ

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

اتصال ثنائي الاتجاه باستخدام الأنابيب المحددة

من المفترض أن يكون الاتصال بين الأنابيب أحادي الاتجاه. كانت الأنابيب مقيدة بالاتصال أحادي الاتجاه بشكل عام وتحتاج إلى أنبوبين على الأقل للاتصال ثنائي الاتجاه. الأنابيب مخصصة للعمليات المترابطة فقط. لا يمكن استخدام الأنابيب في اتصالات العمليات غير ذات الصلة ، على سبيل المثال ، إذا أردنا تنفيذ عملية واحدة من محطة واحدة وعملية أخرى من محطة أخرى ، فهذا غير ممكن مع الأنابيب. هل لدينا أي طريقة بسيطة للتواصل بين عمليتين ، لنقل عمليات غير مرتبطة بطريقة بسيطة؟ الجواب نعم. الأنبوب المسمى مخصص للتواصل بين عمليتين أو أكثر غير مرتبطين ويمكن أن يكون له أيضًا اتصال ثنائي الاتجاه.

بالفعل ، لقد رأينا الاتصال أحادي الاتجاه بين الأنابيب المسماة ، أي الرسائل من العميل إلى الخادم. الآن ، دعونا نلقي نظرة على الاتصال ثنائي الاتجاه ، أي إرسال العميل رسالة إلى الخادم والخادم يتلقى الرسالة ويعيد إرسال رسالة أخرى إلى العميل باستخدام نفس الأنبوب المسمى.

فيما يلي مثال -

الخطوة 1 - قم بإنشاء عمليتين ، واحدة هي fifoserver_twoway والأخرى هي fifoclient_twoway.

الخطوة 2 - تقوم عملية الخادم بما يلي -

  • يقوم بإنشاء أنبوب مسمى (باستخدام وظيفة المكتبة mkfifo ()) بالاسم "fifo_twoway" في الدليل / tmp ، إذا لم يتم إنشاؤه.

  • يفتح الأنبوب المحدد لأغراض القراءة والكتابة.

  • هنا ، تم إنشاء FIFO مع أذونات القراءة والكتابة للمالك. اقرأ للمجموعة ولا توجد أذونات للآخرين.

  • ينتظر بلا حدود لرسالة من العميل.

  • إذا كانت الرسالة المستلمة من العميل ليست "end" ، يطبع الرسالة ويعكس السلسلة. يتم إرسال السلسلة المعكوسة مرة أخرى إلى العميل. إذا كانت الرسالة هي "end" ، يغلق FIFA وينهي العملية.

الخطوة 3 - عملية العميل تؤدي ما يلي -

  • يفتح الأنبوب المحدد لأغراض القراءة والكتابة.

  • يقبل سلسلة من المستخدم.

  • الشيكات ، إذا أدخل المستخدم "نهاية" أو غير "نهاية". في كلتا الحالتين ، فإنه يرسل رسالة إلى الخادم. ومع ذلك ، إذا كانت السلسلة "end" ، فهذا يؤدي إلى إغلاق FIFO وأيضًا إنهاء العملية.

  • إذا تم إرسال الرسالة على أنها ليست "end" ، فإنها تنتظر الرسالة (السلسلة المعكوسة) من العميل وتطبع السلسلة المعكوسة.

  • يتكرر بلا حدود حتى يدخل المستخدم السلسلة "end".

الآن ، دعنا نلقي نظرة على نموذج كود خادم 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;
}

خطوات التجميع والتنفيذ

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

الآن ، دعنا نلقي نظرة على نموذج كود العميل 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;
}

خطوات التجميع والتنفيذ

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 

التسميات: