Bối cảnh quan trọng ở đây là stdoutbắt buộc phải được đệm theo tiêu chuẩn như thiết lập mặc định.
Điều này gây ra một \nđể tuôn ra đầu ra.
Vì ví dụ thứ hai không chứa dòng mới, đầu ra không bị xóa và khi fork()sao chép toàn bộ quá trình, nó cũng sao chép trạng thái của stdoutbộ đệm.
Bây giờ, các fork()cuộc gọi này trong ví dụ của bạn tạo tổng cộng 8 quy trình - tất cả chúng đều có một bản sao trạng thái của stdoutbộ đệm.
Theo định nghĩa, tất cả các quy trình này gọi exit()khi trở về main()và exit()các cuộc gọi fflush()theo sau fclose()trên tất cả các luồng stdio hoạt động . Điều này bao gồm stdoutvà kết quả là, bạn thấy cùng một nội dung tám lần.
Đó là một cách thực hành tốt để gọi fflush()tất cả các luồng có đầu ra đang chờ xử lý trước khi gọi fork()hoặc để cho đứa trẻ rẽ nhánh gọi một cách rõ ràng _exit()rằng chỉ thoát khỏi quy trình mà không xóa các luồng stdio.
Lưu ý rằng việc gọi exec()không xóa bộ đệm stdio, vì vậy không cần quan tâm đến bộ đệm stdio nếu bạn (sau khi gọi fork()) gọi exec()và (nếu không) gọi _exit().
BTW: Để hiểu rằng bộ đệm sai có thể gây ra, đây là một lỗi cũ trong Linux đã được sửa gần đây:
Tiêu chuẩn này đòi hỏi stderrphải được giải mã theo mặc định, nhưng Linux đã bỏ qua điều này và tạo ra stderrdòng đệm và (thậm chí tệ hơn) được đệm hoàn toàn trong trường hợp stderr được chuyển hướng qua một đường ống. Vì vậy, các chương trình được viết cho UNIX đã thực hiện công cụ đầu ra mà không có dòng mới quá muộn trên Linux.
Xem bình luận dưới đây, nó dường như được sửa chữa ngay bây giờ.
Đây là những gì tôi làm để giải quyết vấn đề Linux này:
/*
* 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);
Mã này không gây hại cho các nền tảng khác vì việc gọi fflush()một luồng vừa bị xóa là không có.
./prog1 > prog1.out) hoặc ống (./prog1 | cat). Chuẩn bị để có tâm trí của bạn thổi. :-)