Linux Shell中的管道管理

4
我目前正在研究如何在Shell中管理流水线处理。例如,在我的shell中,如果我输入"ls | wc | less",这个操作的结果将创建三个进程:ls,wc和less。ls的输出将被连接到wc的标准输入,wc的输出将被连接到less的标准输入。
对我来说,这意味着在执行"ls | wc | less"期间,less的标准输入不是键盘,而是wc的输出。但是,less仍然可以响应我的键盘输入。为什么?我不明白,因为对我来说,由于已经进行了管道传递,less不应该对键盘输入敏感。
有人有什么想法吗? 谢谢

1
不要混淆标准输入(stdin)和tty。通常,tty与进程的stdio流相关联,但更频繁地,它们并不相关。这是一个很好的问题,也是区分tty和stdin之间差异的好示例。 - William Pursell
2个回答

2
< p > less的代码< /p >
#if HAVE_DUP
    /*
     * Force standard input to be the user's terminal
     * (the normal standard input), even if less's standard input 
     * is coming from a pipe.
     */
    inp = dup(0);
    close(0);
#if OS2
    /* The __open() system call translates "/dev/tty" to "con". */
    if (__open("/dev/tty", OPEN_READ) < 0)
#else
    if (open("/dev/tty", OPEN_READ) < 0)
#endif
        dup(inp);
#endif

它打开了来自/dev/tty和标准输入(stdin)的直接流。

这是否意味着less仍然从wc输出和/dev/tty读取数据? - toto
{btsdaf} - chepner

1

我猜测可能是使用/dev/console打开交互式会话,我曾经也使用过这个技巧。但我猜错了,使用strace可以帮你找到答案。

echo | strace less

) = 16
read(0, "\n", 8192)                     = 1
write(1, "\n", 1
)                       = 1
read(0, "", 8191)                       = 0
write(1, "\33[7m(END)\33[27m\33[K", 17(END)) = 17
read(3, 

如您所见,less 正在从文件描述符 3 中读取。
/* Standard file descriptors.  */
#define STDIN_FILENO    0   /* Standard input.  */
#define STDOUT_FILENO   1   /* Standard output.  */
#define STDERR_FILENO   2   /* Standard error output.  */

而更仔细地看(在'q'之后):

open("/dev/tty", O_RDONLY)              = 3

这证实了@123的源代码检查 - 它打开了/dev/tty


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接