因为标准输出和标准输入不会创建一个循环。它们可能指向同一个tty,但是tty实际上是两个独立的通道,一个用于输入,一个用于输出,它们不会相互回路。
您可以尝试通过将程序的标准输入连接到
管道的读取端口,并将其标准输出连接到其写入端口来创建循环。这将适用于
cat
:
mkfifo fifo
{ echo text; strace cat; } <>fifo >fifo
...
read(0, "text\n", 131072) = 5
write(1, "text\n", 5) = 5
read(0, "text\n", 131072) = 5
write(1, "text\n", 5) = 5
...
但不是因为你的程序。这是因为你的程序试图读取行,但它的写入没有以换行符结尾。修复这个问题并将读取的行打印到stderr(这样我们就不必使用strace
来证明你的程序中发生了什么),我们得到:
#include <iostream>
#include <string>
int main()
{
std::cout << "text" << std::endl;
for(;;) {
std::string string_object{};
std::getline(std::cin, string_object);
std::cerr << string_object << std::endl;
std::cout << string_object << std::endl;
}
}
g++ foo.cc -o foo
mkfifo fifo; ./foo <>fifo >fifo
text
text
text
...
注意:使用<>fifo
打开命名管道(fifo)的方式,可以同时打开其读端和写端,避免阻塞。而不是从其路径重新打开fifo,stdout可以直接从stdin复制(prog <>fifo >&0
),或者可以先将fifo作为不同的文件描述符打开,然后在不阻塞的情况下分别以只读模式和只写模式打开stdin和stdout(prog 3<>fifo <fifo >fifo 3>&-
)。
它们在手头的示例中都能起到相同的作用。在Linux上,:|prog >/dev/fd/0
(以及echo text | strace cat >/dev/fd/0
)也可以工作--无需使用mkfifo
创建命名管道。
std::stringstream
来完成这样的事情。 - πάντα ῥεῖ>
来重定向它,你应该使用<
。但这是同样的问题。 - Barmar