_exit(), fork() และ waitpid() การเรียกระบบ

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

printf("\n****Child process.****\n\nSquence: ");

 do{
        //Print the integer in the sequence.
        printf("%d\t",inputInteger);
        if((inputInteger%2) == 0){
            //printf("inputInteger = %d\n", inputInteger);
            inputInteger = inputInteger / 2;
        }else{
            inputInteger = 3*inputInteger +1;
            //printf("%d\t",inputInteger);
        }

    }while(inputInteger != 1);

    //Makes sure we print off 1!
    printf("%d\n\n", inputInteger);

    //Properly exit
    _exit(status);

ฉันใช้สถานะเนื่องจากในเธรดหลักของฉันฉันใช้มันในการเรียกระบบ waitpid() นี่คือโค้ดสำหรับกระบวนการหลักที่ดำเนินการหลังจากที่รายการย่อยเสร็จสิ้น

waitpid_check = waitpid(processID, &status, 0);
        printf("\n****Parent process.****\n");

        if(waitpid_check == -1){
            printf("Error in waitpid.\n");
            exit(EXIT_FAILURE);
        }

        if(WIFEXITED(status)){
            printf("Child process terminated normally!\n");
        }

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

แล้วฉันก็สงสัยว่าฉันตรวจสอบการออกจากเด็กในผู้ปกครองอย่างถูกต้องหรือไม่

ขอบคุณสำหรับความช่วยเหลือของคุณ!


person pmac89    schedule 18.02.2014    source แหล่งที่มา
comment
เรากำลังพูดถึงเธรดที่นี่หรือกระบวนการ? จากการโทร ดูเหมือนว่าคุณกำลังจัดการกับกระบวนการย่อย ไม่ใช่เธรดย่อย   -  person jia103    schedule 18.02.2014
comment
ใช่ ฉันกำลังจัดการกับกระบวนการต่างๆ   -  person pmac89    schedule 18.02.2014


คำตอบ (2)


จากคู่มือ waitpid linux

"หากสถานะไม่เป็น NULL ให้ wait() และ waitpid() เก็บข้อมูลสถานะไว้ใน int ที่ชี้ไป"

คุณไม่จำเป็นต้องคืนค่าการรอที่จ่ายเพื่อตรวจสอบว่ารายการย่อยล้มเหลวหรือไม่ คุณต้องตรวจสอบค่าสถานะ มีมาโครจำนวนหนึ่งให้ตรวจสอบสถานะ

WIFEXITED(status)
returns true if the child terminated normally, that is, by calling exit(3) or _exit(2), or by returning from main().
WEXITSTATUS(status)
returns the exit status of the child. This consists of the least significant 8 bits of the status argument that the child specified in a call to exit(3) or _exit(2) or as the argument for a return statement in main(). This macro should only be employed if WIFEXITED returned true.
WIFSIGNALED(status)
returns true if the child process was terminated by a signal.
WTERMSIG(status)
returns the number of the signal that caused the child process to terminate. This macro should only be employed if WIFSIGNALED returned true.
WCOREDUMP(status)
returns true if the child produced a core dump. This macro should only be employed if WIFSIGNALED returned true. This macro is not specified in POSIX.1-2001 and is not available on some UNIX implementations (e.g., AIX, SunOS). Only use this enclosed in #ifdef WCOREDUMP ... #endif.
WIFSTOPPED(status)
returns true if the child process was stopped by delivery of a signal; this is only possible if the call was done using WUNTRACED or when the child is being traced (see ptrace(2)).
WSTOPSIG(status)
returns the number of the signal which caused the child to stop. This macro should only be employed if WIFSTOPPED returned true.
WIFCONTINUED(status)
(since Linux 2.6.10) returns true if the child process was resumed by delivery of SIGCONT.

ไม่ว่าคุณจะออกจากกระบวนการย่อยหรือไม่นั้นขึ้นอยู่กับมันจริงๆ คุณจะออกเหมือนที่คุณทำในโปรแกรมอื่น ๆ เนื่องจากเมื่อคุณแยกกระบวนการ คุณเพียงแค่ทำซ้ำพื้นที่ที่อยู่และลูกเมื่อทำงานเป็นโปรแกรมอิสระของตัวเอง (แน่นอนว่าด้วย FD แบบเปิดเดียวกัน ค่าที่ประกาศไว้แล้ว ฯลฯ ในฐานะพาเรนต์) . ด้านล่างนี้เป็นการใช้งานทั่วไปสำหรับปัญหานี้ (แม้ว่า NULL จะถูกส่งผ่านไปยังการรอแทนที่จะเป็นสถานะ ดังนั้นฉันคิดว่าคุณทำถูกแล้ว)

/* fork a child process */
pid = fork();

if (pid < 0) { /* error occurred */
    fprintf(stderr, "Fork Failed\n");
    return 1;
}
else if (pid == 0) { /* child process */
    printf("I am the child %d\n",pid);
    execlp("/bin/ls","ls",NULL);
}
else { /* parent process */
    /* parent will wait for the child to complete */
    printf("I am the parent %d\n",pid);
    wait(NULL);

    printf("Child Complete\n");
}

return 0;
person PandaRaid    schedule 18.02.2014
comment
ขอบคุณ ฉันพลาดส่วน _exit(2) ในหน้า man นั่นคือคำถามหลักของฉัน ฉันไม่ต้องการแสดงรหัสทั้งหมดของฉันเนื่องจากเป็นงานที่ได้รับมอบหมาย - person pmac89; 19.02.2014

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

ความคิดดูดีในระดับสูง

สิ่งหนึ่งที่ควรจำไว้คือคุณอาจต้องการล้อมรอบเนื้อของวิธีการของลูกคุณในแบบ try/catch เมื่อใช้เธรด คุณมักไม่ต้องการให้มีข้อยกเว้นมารบกวนโฟลว์หลักของคุณ

คุณจะไม่มีปัญหานั้นกับหลายกระบวนการ แต่ลองคิดดูว่าคุณต้องการให้ _exit ถูกเรียกเมื่อมีข้อยกเว้นหรือไม่ และจะสื่อสารอย่างไร (กับผู้ปกครองหรือผู้ใช้) เมื่อมีข้อยกเว้นเกิดขึ้น

person jia103    schedule 18.02.2014