私はプログラムを書き、保守していますrlラップ擬似端末を使用して子プロセスと通信します。擬似端末(ptys) はすべての Unix 系システムに存在しますが、プラットフォームによって動作が若干異なります。
一例を挙げると、 ではrlwrap
、親プロセスはスレーブ pty を開いたままにして、子の端末設定を監視します (Linux および FreeBSD では、そのためにマスターを使用できますが、Solaris などでは使用できません)。
FreeBSD (8.2) (Linux ではそうではありません) では、これにより子プロセスの最終出力が失われます。例:
#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 では、親は最終出力行を見ることができず、代わりに EOF を読み取ります。(どちらかといえば、その逆、つまりスレーブ側を開いたままにしておくことで出力が失われないようにすることを期待していました)
- 一方、LinuxではEOFは一度もない見られず、後子供が死んだ(スレーブを閉じるかどうかに関係なく)
この動作はどこかに文書化されていますか? それに根拠はありますか? 親プロセスでスレーブを閉じずにこれを回避できますか?
そうだと分かったないスレーブを制御端末にする (login_tty
呼び出しをいくつかの単純なdup()
呼び出しに置き換える) と、問題は解決します。rlwrap
ただし、これは の解決策ではありません。多くのコマンドは/dev/tty
通信するために制御端末 ( ) を必要とするため、 はrlwrap
それらのコマンドに制御端末を提供する必要があります。
ベストアンサー1
Pty には独自の個別の動作があると思います。
- 最後のデータが書き込まれるとシステムは終了します
- 子プロセスが終了するとシステムは終了します (パイプが壊れた?)
このコードは、パイプがデータを送信するのに十分な長さ存在することを前提としていますが、子パイプから出る5月データが受信される前に仮想チャネルが削除されます。
これは Pty に固有のものであり、実際の端末には存在しません。