พื้นหลังที่สำคัญในที่นี้stdoutคือต้องมีการบัฟเฟอร์บรรทัดโดยมาตรฐานเป็นการตั้งค่าเริ่มต้น
สิ่งนี้ทำให้ a \nเพื่อล้างเอาต์พุต
เนื่องจากตัวอย่างที่สองไม่มีการขึ้นบรรทัดใหม่เอาต์พุตจะไม่ถูกลบทิ้งและfork()คัดลอกกระบวนการทั้งหมดจึงคัดลอกสถานะของstdoutบัฟเฟอร์
ในตอนนี้การfork()เรียกเหล่านี้ในตัวอย่างของคุณสร้างกระบวนการทั้งหมด 8 กระบวนการ - ทั้งหมดนั้นมีการคัดลอกสถานะของstdoutบัฟเฟอร์
ตามคำนิยามกระบวนการเหล่านี้จะเรียกใช้exit()เมื่อส่งคืนจากmain()และexit()เรียกfflush()ตามด้วยสตรีมstdio ที่fclose()ใช้งานอยู่ทั้งหมด ซึ่งรวมถึงและเป็นผลให้คุณเห็นเนื้อหาเดียวกันแปดครั้งstdout
เป็นวิธีปฏิบัติที่ดีในการเรียกfflush()ใช้สตรีมทั้งหมดที่มีเอาต์พุตที่ค้างอยู่ก่อนการโทรfork()หรือเพื่อให้เด็กที่ถูกแยกออกมาเรียกอย่างชัดเจน_exit()ว่าจะออกจากกระบวนการโดยไม่ล้างข้อมูลสตรีม stdio
หมายเหตุโทรที่exec()ไม่ได้ล้างบัฟเฟอร์ stdio ดังนั้นจึงมีการตกลงที่จะไม่สนใจเกี่ยวกับบัฟเฟอร์ stdio ถ้าคุณ (หลังจากเรียกfork()) โทรexec()และ (ถ้าที่ล้มเหลว) _exit()โทร
BTW: เพื่อให้เข้าใจว่าการบัฟเฟอร์ผิดอาจทำให้เกิดนี่เป็นข้อผิดพลาดเดิมใน Linux ที่ได้รับการแก้ไขเร็ว ๆ นี้:
มาตรฐานจะต้องไม่มีstderrการstderrบัฟเฟอร์ตามค่าเริ่มต้น แต่ Linux เพิกเฉยต่อสิ่งนี้และทำบัฟเฟอร์บรรทัดและ (ยิ่งแย่กว่า) บัฟเฟอร์เต็มในกรณีที่ stderr ถูกเปลี่ยนเส้นทางผ่านไพพ์ ดังนั้นโปรแกรมที่เขียนสำหรับ UNIX ก็ทำสิ่งที่เอาต์พุตโดยไม่ขึ้นบรรทัดใหม่บน Linux
ดูความคิดเห็นด้านล่างดูเหมือนว่าจะได้รับการแก้ไขในขณะนี้
นี่คือสิ่งที่ฉันทำเพื่อแก้ไขปัญหา Linux นี้:
    /* 
     * Linux comes with a broken libc that makes "stderr" buffered even 
     * though POSIX requires "stderr" to be never "fully buffered". 
     * As a result, we would get garbled output once our fork()d child 
     * calls exit(). We work around the Linux bug by calling fflush() 
     * before fork()ing. 
     */ 
    fflush(stderr); 
รหัสนี้ไม่เป็นอันตรายต่อแพลตฟอร์มอื่น ๆ เนื่องจากการเรียกfflush()สตรีมที่เพิ่งถูกฟลัชคือ noop
               
              
./prog1 > prog1.out) หรือไพพ์ (./prog1 | cat) เตรียมที่จะมีความคิดของคุณเป่า. :-)