سؤال

وهذا الرمز أدناه هو للتنفيذ ليرة سورية -l | مرحاض -l. في رمز، إذا أعلق على مقربة (ص [1]) في الأصل ثم برنامج معلقة فقط، والانتظار لبعض المدخلات. لماذا كان الأمر كذلك؟ يكتب الطفل إخراج ليرة سورية على P1 والأم يجب أن تؤخذ أن الإخراج من P0.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>

main ()
{
  int i;
  int p[2];
  pid_t ret;
  pipe (p);
  ret = fork ();

  if (ret == 0)
    {
      close (1);
      dup (p[1]);
      close (p[0]);
      execlp ("ls", "ls", "-l", (char *) 0);
    }

  if (ret > 0)
    {
      close (0);
      dup (p[0]);
      //Doubt, Commenting the line below does not work WHy?
      close (p[1]);
      wait (NULL);
      execlp ("wc", "wc", "-l", (char *) 0);
    }
}
هل كانت مفيدة؟

المحلول

pipe + fork يخلق 4 واصفات الملف، هما مدخلات

وقبل شوكة لديك أنبوب واحد مع واحد المدخلات والمخرجات واحد.

وبعد شوكة سيكون لديك أنبوب واحد مع اثنين من المدخلات واثنين من النواتج.

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

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

وهكذا المآزق الأم، والانتظار إلى الأبد لأنه في الكتابة نفسها.

نصائح أخرى

لاحظ أن "dup(p[1])" يعني أن لديك اثنين من واصفات الملفات لافتا إلى نفس الملف. وهو يفعل p[1] ليست قريبة. يجب عليك أن تفعل ذلك صراحة. وبالمثل مع "dup(p[0]). لاحظ أن واصف ملف القراءة من الأنابيب يعود فقط بايت صفر (EOF) عندما لا يكون هناك واصفات ملف الكتابة مفتوحة للأنبوب. حتى يتم إغلاق آخر يكتب واصف، فإن عملية القراءة تعليق إلى أجل غير مسمى. إذا كنت dup() نهاية الكتابة، وهناك نوعان من واصفات الملف المفتوح إلى نهاية الكتابة، وكلاهما يجب أن تكون مغلقة قبل يحصل على عملية القراءة EOF.

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

عند تجريد المواد الزائدة عن الحاجة بها، يصبح رمز العمل:

#include <unistd.h>

int main(void)
{
    int p[2];
    pid_t ret;
    pipe(p);
    ret = fork();

    if (ret == 0)
    {
        close(1);
        dup(p[1]);
        close(p[0]);
        close(p[1]);
        execlp("ls", "ls", "-l", (char *) 0);
    } 
    else if (ret > 0)
    {
        close(0);
        dup(p[0]);
        close(p[0]);
        close(p[1]);
        execlp("wc", "wc", "-l", (char *) 0);
    }
    return(-1);
}

و، وهذا يجمع على سولاريس 10 دون سابق إنذار مع:

Black JL: gcc -Wall -Werror -Wmissing-prototypes -Wstrict-prototypes -o x x.c
Black JL: ./x
      77
Black JL:

إذا يفعل الطفل لا p[1] قريب، فإن ذلك FD مفتوح في عمليتين - الأم والطفل. الوالد في نهاية المطاف تنتهي، ولكن الطفل لم يفعل - حتى FD يبقى مفتوحة. لذا فإن أي قارئ أن FD (الطفل في هذه الحالة) سوف ننتظر إلى الأبد فقط في حالة المزيد من الكتابة ستعمل أن يتم ذلك على ذلك ... لم يكن، ولكن القارئ فقط لا يعرف! -)

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top