Hãy có một cái nhìn tại chương trình này Hello WorldSự khác nhau giữa FILE * "/ dev/stdout" và stdout
#include <stdio.h>
int main(int argc, char ** argv) {
printf("Hello, World!");
const char* sFile = "/dev/stdout"; // or /proc/self/fd/0
const char* sMode = "w";
FILE * output = fopen(sFile, sMode);
//fflush(stdout) /* forces `correct` order */
putc('!', output); // Use output or stdout from stdio.h
return 0;
}
Khi biên soạn bằng cách sử dụng mô tả output
tập tin đầu ra là:
!Hello, World!
khi được biên soạn bằng cách sử dụng mô tả tệp stdout
được cung cấp bởi stdio.h
kết quả như mong đợi:
Hello, World!!
Tôi hình dung khi gọi putc
với sau này, nó sẽ in trực tiếp đến stdout
và khi sử dụng các mô tả tập tin trên /dev/stdout
nó sẽ mở một ống và in vào đó. Tôi không chắc chắn.
Hành vi này thậm chí còn thú vị hơn, vì nó không ghi đè ký tự đầu tiên của 'Hello' nhưng thay vào đó đẩy chính nó vào vị trí đầu tiên của bộ đệm dòng trước chuỗi đã được đẩy.
Từ quan điểm logic, điều này là không mong muốn yên tĩnh.
Có ai có thể giải thích chính xác những gì đang xảy ra ở đây không?
Tôi đang sử dụng cc (Ubuntu 4.8.2-19ubuntu1) 4.8.2
và một hạt nhân 3.13.0-52 linux biên soạn w/gcc 4.8.2
Sửa: Tôi đã thực hiện một strace
của cả hai chương trình, và đây là phần quan trọng:
output
(fopen ("/ dev/stdout", "w")) mà không cần fflush(stdout)
scenar io sản xuất:
...
open("/dev/stdout", O_WRONLY|O_CREAT|O_TRUNC, 0666) = 3
fstat(3, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 1), ...}) = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f62f21e9000
write(3, "!", 1!) = 1
write(1, "Hello, World!", 13Hello, World!) = 13
exit_group(0) = ?
sử dụng fflush(stdout)
sản xuất và thực thi đúng thứ tự:
...
open("/dev/stdout", O_WRONLY|O_CREAT|O_TRUNC, 0666) = 3
write(1, "Hello, World!", 13Hello, World!) = 13
fstat(3, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 1), ...}) = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f5ad4557000
write(3, "!", 1!) = 1
exit_group(0) = ?
Các stdout
(từ stdlib.h) kịch bản sản xuất:
...
write(1, "Hello, World!!", 14Hello, World!!) = 14
exit_group(0) = ?
Vì vậy, có vẻ như các FILE * output = fopen("/dev/stdout")
luồng sử dụng mô tả tệp khác với stdout
Cũng có vẻ như printf
sử dụng stdout
Vì vậy, trong kịch bản thứ ba, chuỗi được lắp ráp trước khi nó được đẩy lên luồng.
'stdout' là một tệp *, không phải là bộ mô tả tệp. Tương tự, 'output' không phải là một bộ mô tả tập tin. Mỗi tệp có một bộ mô tả tệp cơ bản và nếu bạn viết trực tiếp vào nó, bạn sẽ không thấy hành vi này. (Viết trực tiếp vào bộ mô tả tập tin bỏ qua đệm.) –
Sự khác biệt lớn là mỗi 'FILE *' đang sử dụng bộ đệm riêng của nó, không liên quan đến nhau .. –