หลังจาก fork () เด็กจะเริ่มต้นการดำเนินการที่ใด


22

ฉันพยายามเรียนรู้การเขียนโปรแกรม UNIX และพบคำถามเกี่ยวกับ fork () ฉันเข้าใจว่า fork () สร้างกระบวนการที่เหมือนกันของกระบวนการที่กำลังทำงานอยู่ แต่มันเริ่มต้นที่ไหน ตัวอย่างเช่นถ้าฉันมีรหัส

int main (int argc, char **argv)
{
    int retval;
    printf ("This is most definitely the parent process\n");
    fflush (stdout);
    retval = fork ();
    printf ("Which process printed this?\n");

    return (EXIT_SUCCESS);
}

ผลลัพธ์คือ:

นี่เป็นกระบวนการสำหรับผู้ปกครองแน่นอนที่สุดกระบวนการ
ใดที่พิมพ์ออกมานี้
กระบวนการใดพิมพ์

ฉันคิดว่ามันfork()สร้างกระบวนการเดียวกันดังนั้นตอนแรกฉันก็เลยว่าในโปรแกรมนั้นการfork()โทรจะถูกเรียกซ้ำตลอดไป ฉันเดาว่ากระบวนการใหม่ที่สร้างขึ้นจากการfork()เริ่มต้นหลังจากการfork()โทร?

ถ้าฉันเพิ่มรหัสต่อไปนี้เพื่อแยกความแตกต่างระหว่างกระบวนการหลักและลูก

if (child_pid = fork ()) printf ("This is the parent, child pid is %d\n", child_pid);
else printf ("This is the child, pid is %d\n",getpid ());

หลังจากการเรียก fork () กระบวนการลูกจะเริ่มการประมวลผลที่ไหน


5
man forkก็พอที่จะตอบคำถามของคุณ btw
alex

คำตอบ:


23

กระบวนการใหม่จะถูกสร้างขึ้นภายในการfork()โทรและจะเริ่มต้นด้วยการส่งคืนจากมันเช่นเดียวกับผู้ปกครอง ค่าตอบแทน (ซึ่งคุณเก็บไว้ในretval) จากfork()จะเป็น:

  • 0 ในกระบวนการลูก
  • PID ของเด็กในกระบวนการหลัก
  • -1 ในผู้ปกครองหากมีความล้มเหลว (ไม่มีลูกตามธรรมชาติ)

รหัสทดสอบของคุณทำงานอย่างถูกต้อง มันเก็บค่าตอบแทนจากfork()ในchild_pidและใช้ifในการตรวจสอบว่าเป็น 0 หรือไม่ (แม้ว่าจะไม่ตรวจสอบข้อผิดพลาด)


13

ฉันคิดว่า fork () สร้างกระบวนการเดียวกันดังนั้นฉันเริ่มแรกว่าในโปรแกรมนั้นการเรียก fork () จะถูกเรียกซ้ำตลอดไป ฉันเดาว่ากระบวนการใหม่ที่สร้างจาก fork () เริ่มต้นหลังจากการเรียก fork () หรือไม่

ใช่. ลองนับจำนวน:

int main (int argc, char **argv)
{
    int retval;                                               /* 1 */
    printf ("This is most definitely the parent process\n");  /* 2 */
    fflush (stdout);                                          /* 3 */
    retval = fork ();                                         /* 4 */
    printf ("Which process printed this?\n");                 /* 5 */
    return (EXIT_SUCCESS);                                    /* 6 */
}

การไหลของการดำเนินการคือ:

caller process     fork()  ...
                          
original program            exec()  2  3  4  5  6
                                               
forked program                                   5  6

... ซึ่งอธิบายผลลัพธ์ที่คุณได้รับอย่างแน่นอน

หากคุณต้องการทราบว่าโปรแกรมดั้งเดิมและโปรแกรมแยกสามารถทำงานแตกต่างกันอย่างไรเนื่องจากพวกเขาจำเป็นต้องใช้รหัสเดียวกันให้ดูคำตอบของ Michael Mrozek


โปรดทราบว่า 1 ไม่ใช่คำสั่งจริง นอกจากนี้โปรดทราบว่าโปรแกรมดั้งเดิมและโปรแกรมแยกทางแยกไม่ได้ทำงานในเวลาเดียวกัน - โปรแกรมใดโปรแกรมหนึ่งจะต้องรอให้โปรแกรมอื่น ๆ ให้ผลตอบแทน / ถูกครอบครอง
badp

1
บนระบบมัลติคอร์ / มัลติซีพียูทั้งสองโปรแกรมสามารถทำงานได้ในเวลาเดียวกัน
jlliagre

@jilliagre Multicore เป็นเรื่องเกี่ยวกับระบบมัลติเธรดจริงๆ ในฐานะที่เป็นสำหรับระบบที่มีซีพียูหลายฉันไม่ทราบว่าถ้าเป็นกรณีนี้หรือไม่ในทางปฏิบัติ ฉันไม่มีความเชี่ยวชาญในสาขานี้ - และดูเหมือนว่าจะเป็นไปได้ยาก หากเราเห็นว่าระบบปฏิบัติการสามารถทำงานหลาย ๆ กระบวนการได้ในเวลาเดียวกัน (จากนั้นจะจัดการกับการทำงานพร้อมกันได้อย่างไร) ตามเวลาที่โปรแกรมดั้งเดิมรันคำสั่งที่ 4 บน CPU, CPU อื่น ๆ มักจะยุ่งอยู่กับกระบวนการอื่นอยู่แล้ว
badp

ฉันจะบอกว่ามันเป็นสถานการณ์ที่น่าเป็นไปได้มากโดยเฉพาะอย่างยิ่งเนื่องจากมีการเรียกระบบพื้นฐานที่มี I / O บางอย่างเกิดขึ้นในขั้นตอนที่ 5 การมี CPU ไม่ว่างทั้งหมดนั้นจริงๆแล้วไม่ใช่สถานการณ์ทั่วไปเนื่องจาก CPU ไม่ค่อยมีปัญหาคอขวด ดูเหมือนว่าคุณสับสนหลายเธรดและมัลติคอร์
jlliagre

8
ฉันสามารถเพียงความคิดเห็นที่จะบอกว่าผู้ที่ลูกศรแนวทแยงเป็นที่ยอดเยี่ยม
JBirch

0

ทางออกที่แท้จริงของสิ่งนี้คือ

switch (fork()) {
    case -1 :
        fprintf (stderr, "fork failed (%s)\n", strerror(errno));
        break;
    case 0 :  // child process comes here
        break;
    default : // parent process
        break;
}

// all continue here

-1

ไม่ว่ารหัสใดก็ตามหลังจากfork()นั้นจะถูกคัดลอกไปยังกระบวนการลูกและไม่รวมกระบวนการหลักและลูกเข้าด้วยกันพวกเขาเป็นหน่วยงานที่แตกต่างกันสองรายการที่มีสภาพแวดล้อมแบบเดียวกัน

ตอนนี้ดูผลลัพธ์ของคุณ ...

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.