سؤال

أنا نوع من المبتدئين على C ++ ، وأعمل على برنامج بسيط على Linux والذي من المفترض أن يستدعي برنامجًا آخر في نفس الدليل والحصول على إخراج البرنامج الذي تم استدعاؤه دون عرض إخراج البرنامج المحتج على وحدة التحكم. هذا هو مقتطف الكود الذي أعمل عليه:

    pid_t pid;
    cout<<"General sentance:"<<endl<<sentence<<endl;
    cout<<"==============================="<<endl;
    //int i=system("./Satzoo");
    if(pid=fork()<0)
        cout<<"Process could not be created..."<<endl;
    else
    {
        cout<<pid<<endl;
        execv("./Satzoo",NULL);
    }
    cout<<"General sentance:"<<endl<<sentence<<endl;
    cout<<"==============================="<<endl;

إحدى المشكلات التي أواجهها هي أنني قادر على طباعة الخطين الأولين على وحدة التحكم ولكن لا يمكنني طباعة الخطين الأخيرين. أعتقد أن البرنامج يتوقف عن العمل عندما أدعو برنامج Satzoo. شيء آخر هو أن هذا الرمز يستدعي برنامج Satzoo مرتين ، لا أعرف لماذا؟ أستطيع أن أرى الإخراج على الشاشة مرتين. من ناحية أخرى ، إذا استخدمت System () بدلاً من Execv () ، فإن Satzoo يعمل مرة واحدة فقط.

لم أحسب كيفية قراءة إخراج Satzoo في برنامجي.

أي مساعدة موضع تقدير.

شكرًا

هل كانت مفيدة؟

المحلول

أنت لست مميزًا بين الطفل وعملية الوالدين بعد الدعوة إلى fork(). لذلك يركض كل من الطفل والوالد execv() وبالتالي يتم استبدال صور العملية الخاصة بهم.

تريد شيئًا أكثر مثل:

pid_t pid;
printf("before fork\n");

if((pid = fork()) < 0)
{
  printf("an error occurred while forking\n");
}
else if(pid == 0)
{
  /* this is the child */
  printf("the child's pid is: %d\n", getpid());
  execv("./Satzoo",NULL);
  printf("if this line is printed then execv failed\n");
}
else
{
  /* this is the parent */
  printf("parent continues execution\n");
}

نصائح أخرى

ال fork() وظيفة استنساخ العملية الحالية والعودة مختلف القيم في كل عملية. في عملية "الوالد" ، فإنه يعيد حوض الطفل. في عملية الطفل ، يعود الصفر. لذلك عادة ما تستحضرها باستخدام نموذج مثل هذا:

if (fork() > 0) {
    cout << "in parent" << endl;
} else {
    cout << "in child" << endl;
    exit(0);
}

لقد حذفت معالجة الأخطاء في ما سبق.

في مثالك ، يقع كل من مسارات الكود أعلاه (الوالد والطفل) في else بند مكالمتك إلى fork(), ، مما يسبب كلاهما execv("./Satzoo"). هذا هو السبب في أن برنامجك يعمل مرتين ، ولماذا لا تصل إلى العبارات التي تتجاوز ذلك.

بدلا من استخدام fork() والقيام بكل شيء يدويًا (إدارة العملية بشكل صحيح هو قدر لا بأس به من العمل) ، فقد تكون مهتمًا باستخدام popen() الوظيفة بدلاً من ذلك:

FILE *in = popen("./Satzoo", "r");
// use "in" like a normal stdio FILE to read the output of Satzoo
pclose(in);

من fork() manpage:

قيمة الإرجاع
عند الانتهاء بنجاح ، تعود Fork () إلى 0 إلى عملية الطفل وتعيد معرف العملية لعملية الطفل إلى عملية الوالدين. يجب أن تستمر كلتا العمليتين في التنفيذ من وظيفة Fork (). خلاف ذلك ، يجب إرجاع -1 إلى عملية الوالدين ، ولا يجوز إنشاء أي عملية طفل ، ويجب ضبط Errno للإشارة إلى الخطأ.

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

EXEC - تحل عائلة الوظائف exec () محل صورة العملية الحالية مع صورة عملية جديدة.

النظام - كتل على تنفيذ الأمر. يستمر تنفيذ برنامج الاتصال بعد إرجاع أمر النظام

هناك ثلاثة اختبارات قيمة الإرجاع التي تريدها مع الشوكة

  1. 0: أنت الطفل
  2. -1: خطأ
  3. آخر: أنت الوالد

قمت بتشغيل البرنامج الآخر من كل من الطفل والوالد ...

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