Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/70.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/28.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
管道命令./a.out | cat,a.out中的printf(";line\n";)未执行且无输出_C_Linux_Gcc_Pipe_Pipeline - Fatal编程技术网

管道命令./a.out | cat,a.out中的printf(";line\n";)未执行且无输出

管道命令./a.out | cat,a.out中的printf(";line\n";)未执行且无输出,c,linux,gcc,pipe,pipeline,C,Linux,Gcc,Pipe,Pipeline,一件非常奇怪的事情,A.out只是printf()一行然后进入死循环,当A.out单独执行时,我可以在termal中看到该行,但是如果管道A.out使用cat,那么我们什么也看不到 #include <stdio.h> #include <unistd.h> int main(int argc, char **argv) { printf("----------\n"); while (1) { sleep

一件非常奇怪的事情,A.out只是
printf()
一行然后进入死循环,当A.out单独执行时,我可以在termal中看到该行,但是如果管道A.out使用cat,那么我们什么也看不到

#include <stdio.h>
#include <unistd.h>

int main(int argc, char **argv)
{
        printf("----------\n");
        while (1) {
                sleep(1000);
        }
        return 0;
}
如果我选a.out | cat,则不调用write(1)系统调用

$ strace ./a.out | cat
execve("./a.out", ["./a.out"], 0x7ffdaa23b200 /* 65 vars */) = 0
brk(NULL)                               = 0x5567446dd000
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=94391, ...}) = 0
mmap(NULL, 94391, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f977ba22000
close(3)                                = 0
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\200l\2\0\0\0\0\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0755, st_size=2000480, ...}) = 0
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f977ba20000
mmap(NULL, 2008696, PROT_READ, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f977b835000
mmap(0x7f977b85a000, 1519616, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x25000) = 0x7f977b85a000
mmap(0x7f977b9cd000, 299008, PROT_READ, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x198000) = 0x7f977b9cd000
mmap(0x7f977ba16000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1e0000) = 0x7f977ba16000
mmap(0x7f977ba1c000, 13944, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7f977ba1c000
close(3)                                = 0
arch_prctl(ARCH_SET_FS, 0x7f977ba21500) = 0
mprotect(0x7f977ba16000, 12288, PROT_READ) = 0
mprotect(0x556743cd8000, 4096, PROT_READ) = 0
mprotect(0x7f977ba64000, 4096, PROT_READ) = 0
munmap(0x7f977ba22000, 94391)           = 0
fstat(1, {st_mode=S_IFIFO|0600, st_size=0, ...}) = 0
brk(NULL)                               = 0x5567446dd000
brk(0x5567446fe000)                     = 0x5567446fe000
nanosleep({tv_sec=1000, tv_nsec=0}, ^C{tv_sec=994, tv_nsec=769383373}) = ? ERESTART_RESTARTBLOCK (Interrupted by signal)
strace: Process 5050 detached
如果我删掉了一首单曲,那么就必须写出(1)


为什么?

输出流可以处于三种不同模式之一,无缓冲、行缓冲或完全缓冲。在无缓冲模式下,立即写入输出。在行缓冲模式下,首先将输出写入内部流缓冲区,直到缓冲区已满或写入换行,然后将缓冲区刷新到输出。在完全缓冲模式下,首先将输出写入内部流缓冲区,直到缓冲区已满,然后将缓冲区刷新到输出。(某些实现也可能在其他时间刷新输出,例如从交互设备读取输入时。)

输入流也可以处于相同的三种模式,这决定了读取流的函数调用方何时可以使用读取输入

在调用
main
函数之前(或至少在对流的任何访问之前),实现初始化标准输入(
stdin
)、标准输出(
stdout
)和标准错误输出(
stderr
)流的模式。在某些情况下,允许实现将标准输入或标准输出初始化为完全缓冲模式。当且仅当实现可以确定标准输入和输出流未链接到交互设备(例如终端)时,才将其初始化为完全缓冲模式。(标准错误输出流从未初始化为完全缓冲模式。)

通常,POSIX系统的C运行时库将调用标准输入和输出流的底层文件描述符
isatty
,如果
isatty
返回0,则将流设置为完全缓冲模式。这发生在调用
main
函数之前

当您运行“/a.out”并将输出发送到终端时,C运行时库确定输出将发送到交互设备,并且不会将
stdout
设置为完全缓冲模式。它将被设置为其他模式之一,通常为线路缓冲模式。但是,当运行“/a.out”并将输出发送到管道时,C运行时库确定输出不会发送到交互设备,并将
stdout
设置为完全缓冲模式。这就是为什么输出不会立即写入管道

有两种方法可以解决你的问题。第一个是在第一次调用
printf
之前,将标准输出流更改为行缓冲模式或非缓冲模式:

setvbuf(stdout, NULL, _IOLBF, 0); // set standard output to line buffered mode

setvbuf(stdout, NULL, _IONBF, 0); // set standard output to unbuffered mode
另一种方法是根据需要刷新标准输出:

fflush(stdout); // write buffered standard output contents

stdout流可能处于完全缓冲模式,因为输出将发送到管道而不是终端。您可以在printf之后使用
fflush(stdout)刷新stdout流
强制将缓冲输出写入管道。或者,您可以通过调用
setvbuf(stdout,NULL,_IOLBF,0)将stdout流设置为行缓冲模式在程序的开头。@IanAbbott您应该写一个答案。@IanAbbott是的,当标准输出是终端时,它是行缓冲的,其他的是块缓冲的。当我设置setlinebuf(stdout)时;然后,管道和终端的作用相同。
setvbuf(stdout, NULL, _IOLBF, 0); // set standard output to line buffered mode

setvbuf(stdout, NULL, _IONBF, 0); // set standard output to unbuffered mode
fflush(stdout); // write buffered standard output contents