我编写并维护了一个程序rlwrap,该程序使用伪终端与子进程进行通信。 Pseudo-terminals(ptys)在所有类似Unix(-like)的系统中都可以找到,但是它们在不同平台上的行为略有不同。
例子:在rlwrap
中,父进程保持从属pty打开,以保持子级终端设置上的标签(例如,在Linux和FreeBSD上,可以使用主控,但在Solaris中则不能使用主控)。
在FreeBSD(8.2)(而不是Linux)上,这会导致 child 的最终输出丢失。例如:
#include <stdio.h>
/* save as test.c and compile with gcc -o test test.c -lutil */
#define BUFSIZE 255
int main(void) {
int master, slave;
char buf[BUFSIZE];
int nread;
openpty(&master, &slave, NULL, NULL, NULL);
if (fork()) { /* parent: */
close(slave); /* leave this out and lose slave's final words ... WHY? */
do {
nread = read(master, buf, BUFSIZE);
write(STDOUT_FILENO, buf, nread); /* echo child's output to stdout */
} while (nread > 0);
} else { /* child: */
login_tty(slave); /* this makes child a session leader and slave a controlling */
/* terminal for it, then dup()s std{in,out,err} to slave */
printf("Feeling OK :-)\n");
sleep(1);
printf("Feeling unwell ... Arghhh!\n"); /* this line may get lost */
}
return 0;
}
父进程将按预期方式回显子级的输出,但是当我省略
close(slave)
(使其像rlwrap
一样保持打开状态)时:FreeBSD上的
此行为记录在某处吗?有理由吗?我可以在不关闭父进程的情况下绕过它吗?
我发现不将从属设备作为控制终端-用一些简单的
login_tty
调用替换dup()
调用-将解决此问题。但是,这不是rlwrap
的解决方案:相当多的命令需要控制终端(/dev/tty
)进行通信,因此rlwrap
必须为其提供一个。 最佳答案
我认为Pty有独特的独立行为。
该代码依赖于存在时间足够长的管道来发送数据,但是退出子进程可能会导致虚拟通道在接收到数据之前被删除。
这对于Pty而言将是唯一的,而对于真正的终端机则不存在。
关于c - 如果未在父级上关闭,则从属pty的最终输出将丢失。为什么?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/23458160/