如何结束向从一个控制台中的标准输入读取另一控制台的进程输入文本? - 通常通过按 Enter 键完成什么操作。
控制台 1:只要用户不按 Enter 键(通常行为),C++ 程序就会从 std::cin 读取数据。
控制台 2:在普通控制台中,我发现可以通过以下方式将任何文本发送到控制台 1 中的进程:
echo "some text" >> /proc/18672/fd/0
(它只是写入我的进程的标准输入,其 PID 为 18672)。
这可行,但缺少一个重要的步骤:
如何结束从控制台 2 输入“某些文本”,或者如何模拟从控制台 2 按下控制台 1 的回车键?
使用换行符(例如“\n”)不起作用。
答案1
毫无疑问,以其他方式设计会更好(OpenBSD 删除了对 TIOCSTI ioctl 的支持)。考虑到这一点,首先我们需要一些希望合适的 C++ 代码,这些代码涉及std::cin
并使其在/dev/pts/0
.
$ cat foo.cpp
#include <iostream>
int main() {
int n;
std::cin >> n;
std::cout << n;
}
$ c++ foo.cpp
$ tty
/dev/pts/0
$ ./a.out
然后,在不同的终端中,我们编译
// ttytickle.c - send characters via TIOCSTI
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <err.h>
#include <fcntl.h>
int main(int argc, char *argv[]) {
int fd = open(*++argv, O_WRONLY);
if (fd < 0) err(1, "open failed '%s'", *argv);
char word[] = "42\n";
char *wp = word;
while(*wp != '\0') ioctl(fd, TIOCSTI, wp++);
return 0;
}
并运行上面的命令:
$ make ttytickle && ./ttytickle /dev/pts/0
cc ttytickle.c -o ttytickle
并且(假设支持 TIOCSTI,字符串不太长等) 在终端./a.out
中运行/dev/pts/0
应该打印 42。
但是,最好以其他方式设计您想要做的任何事情,例如通过管道或套接字......
答案2
进程的标准输入仅链接到其终端 - 做一个列表来查看这一点,例如
> ll /proc/self/fd
total 0
lrwx------ 1 root root 64 Sep 12 11:32 0 -> /dev/pts/1
lrwx------ 1 root root 64 Sep 12 11:32 1 -> /dev/pts/1
lrwx------ 1 root root 64 Sep 12 11:32 2 -> /dev/pts/1
因此,回显“文本”实际上只是输出到该终端,如您所见。如果您想要实现的只是向进程发送输入,也许 FIFO 可以满足您的要求?例如:
on tty1:
$ mkfifo input
$ cat > input <<-eof # send process some input (being careful not to close your output before completely done)
echo Hi
echo World
read ans
42
echo \$ans
eof
第二个进程从“输入”fifo 中读取:
e.g. on tty1, in the same directory with the "input" fifo:
$ bash -x < input
+ echo Hi
Hi
+ echo World
World
+ read ans
+ echo 42
42