以下程序(64 位 YASM)从标准输入读取 4 个字节并退出:
section .data
buf db " " ; Just allocate 16 bytes for string
section .text
global _start
_start:
mov rax, 0 ; READ syscall
mov rdi, 0 ; STDIN
mov rsi, buf ; Address of the string
mov rdx, 4 ; How many bytes to read
syscall
; Exit:
mov rax, 60
mov rdi, 0
syscall
一次编译
yasm -f elf64 -l hello.lst -o input.o input.asm
ld -o input input.o
如果像这样运行
./input
例如,123456\n
作为用户输入,它将消耗 1234
,但发送结束位 56\n
bash 。因此,bash 将尝试运行命令 56
...谢天谢地没有成功。但想象一下,如果输入是 1234rm -f *
。但是,如果我使用重定向或管道提供输入,例如,
echo "123456" | ./input
56
不会发送到 bash。
那么,如何防止将未使用的输入发送到 bash?在遇到某种形式的 EOF 之前,我是否需要继续使用它?这甚至是预期的行为吗?
同样的事情发生在 C 程序中:
#include <unistd.h>
int main()
{
char buf[16];
read(0, buf, 4);
return 0;
}
(我只是想知道 C 运行时是否以某种方式清除了 STDIN,但没有,它没有)
最佳答案
是的,这是正常行为。您不消耗的任何东西都可用于下一个过程。你知道当你做一些慢的事情时你可以提前输入,当慢的事情完成时 shell 将运行你输入的内容吗?这里也是一样。
没有万能的解决方案。这实际上与用户期望有关。他们希望您的程序消耗多少输入?这就是您应该阅读的内容。
您的程序是否像
read
这样的单行提示?然后,您应该通过下一个\n
字符读取整行输入。在不过度阅读的情况下做到这一点的最简单方法是一次阅读 1 个字符。如果您进行批量读取,您可能会错误地使用下一行的一部分。您的程序是否像
cat
或sed
或grep
这样的过滤器?然后你应该一直读到 EOF。您的程序是否完全不像
echo
或gcc
从 stdin 读取?然后你应该不理会 stdin 并且不消耗任何东西,将输入留给下一个程序。
正好消耗 4 个字节是不寻常的,但对于提示输入 4 位 PIN 且不需要用户按 Enter 的交互式程序来说可能是合理的行为。
关于c - 在 Linux : unconsumed input is sent to bash 中使用系统调用 READ 读取 STDIN,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62325098/