
Lubuntu 18.04 では、lxterminal でシェルを実行します。その制御端末は、現在の疑似端末スレーブです。
$ tty
/dev/pts/2
/dev/pts/2
現在の制御端末と との間にどのような関係があるのかを知りたいです/dev/tty
。
/dev/tty
現在の制御端末のように動作します/dev/pts/2
:$ echo hello > /dev/tty hello $ cat < /dev/tty world world ^C
しかし、これらは、一方が他方へのシンボリックリンクまたはハードリンクではなく、無関係なファイルであるようです。
$ ls -lai /dev/tty /dev/pts/2 5 crw--w---- 1 t tty 136, 2 May 31 16:38 /dev/pts/2 13 crw-rw-rw- 1 root tty 5, 0 May 31 16:36 /dev/tty
異なる制御端末を持つ異なるセッションの場合、 は
/dev/tty
それらの制御端末であることが保証されます。 シンボリックリンクやハードリンクにせずに、異なる制御端末にするにはどうすればよいでしょうか。
では、それらの関係と違いは何でしょうか? どのような助言でも大歓迎です!
この投稿は以前の投稿から派生したものですコマンド `tty` の出力とファイル `/dev/tty` はどちらも、現在の bash プロセスの制御端末を参照していますか?
答え1
tty
セクション4のmanページ次のように主張している。
ファイル/dev/ttyメジャー番号 5、マイナー番号 0 の文字ファイルで、通常はモード 0666、所有者.グループ root.tty です。プロセスの制御端末 (存在する場合) の同義語です。
に加えて
ioctl(2)
ttyが参照するデバイスがサポートする要求、ioctl(2)
リクエストTIOCNOTTY
はサポートされています。
TIOCNOTTY
呼び出しプロセスを制御端末から切り離します。
プロセスがセッション リーダーである場合、シグナル
SIGHUP
がSIGCONT
フォアグラウンド プロセス グループに送信され、現在のセッション内のすべてのプロセスは制御 tty を失います。これ
ioctl(2)
呼び出しは、接続されたファイル記述子に対してのみ機能します。 /dev/ttyデーモンプロセスは、端末でユーザーによって呼び出されたときに使用されます。プロセスは、/dev/ttyオープンが成功した場合は、 を使用してターミナルからデタッチされますTIOCNOTTY
が、オープンが失敗した場合は、明らかにターミナルに接続されていないため、デタッチする必要はありません。
/dev/tty
これは、 が制御端末へのシンボリックリンクではない理由を部分的に説明します。 は追加の をサポートしioctl
、制御端末がない可能性があります(ただし、プロセスは常に にアクセスしようとすることができます)/dev/tty
。ただし、ドキュメントは間違っています。追加の は、ioctl
経由 /dev/tty
(見るmosvyの回答、これは の性質についてもより合理的な説明を与えます/dev/tty
。
/dev/tty
リンクにならずに、異なる制御端末を表すことができます。これは、それを実装するドライバが、呼び出しプロセスの制御端末 (存在する場合) を決定するためです。
/dev/tty
これは制御端末であると考えることができます。したがって、制御端末にのみ意味のある機能を提供しますが、/dev/pts/2
などは単純な端末であり、そのうちの 1 つが特定のプロセスの制御端末になる場合があります。
答え2
/dev/tty
は、「魔法の」文字デバイスであり、開くと現在の端末へのハンドルを返します。
制御端末が であると仮定すると/dev/pts/1
、 を介して開かれたファイル記述子/dev/pts/1
と を介して開かれたファイル/dev/tty
記述子は同じデバイスを参照します。書き込み、読み取り、またはその他のファイル操作はどちらに対しても同じように動作します。
特に、それらは同じioctlのセットを受け入れ、そしてTIOCNOTTY
経由でのみ利用可能な追加のioctlではありません。/dev/tty
。
ioctl(fd, TIOCNOTTY)
呼び出し元のプロセスの制御端末であれば、端末を参照する任意のファイル記述子に対して同じように動作します。
/dev/tty
記述子が、/dev/pts/1
、を開いて取得されたかどうかは関係ありません/dev/ptmx
(その場合、ioctlは対応する奴隷)、または最近では の呼び出しによっても行われますioctl(master, TIOCGPTPEER, flags)
。
例:
$ cat <<'EOT' >tiocnotty.c
#include <sys/ioctl.h>
#include <unistd.h>
#include <err.h>
int main(int ac, char **av){
if(ioctl(0, TIOCNOTTY)) err(1, "io(TIOCNOTTY)");
if(ac < 2) return 0;
execvp(av[1], av + 1);
err(1, "execvp %s", av[1]);
}
EOT
$ cc -W -Wall tiocnotty.c -o tiocnotty
$ ./tiocnotty
$ ./tiocnotty </dev/tty
$ tty
/dev/pts/0
$ ./tiocnotty </dev/pts/0
また、これは実際には現在のプロセスを tty から「切り離す」わけではありません。プロセスは引き続きそこから読み取ることができ、^C
端末上で を実行するとプロセスが強制終了されるなどです。セッション リーダーではないプロセスに対する唯一の影響は、 経由で tty にアクセスできなくなることと/dev/tty
、 で制御 tty としてリストされなくなることです/proc/PID/stat
。
$ ./tiocnotty cat
^C
$ ./tiocnotty cat
^Z
[2]+ Stopped ./tiocnotty cat
$ ./tiocnotty cat
foo
foo
^D
$ ./tiocnotty cat /dev/tty
cat: /dev/tty: No such device or address
$ ./tiocnotty awk '{print$7}' /proc/self/stat
0
[の7番目のフィールドは/proc/<pid>/stat
制御ttyのデバイスIDです。 を参照してくださいproc(5)
。]
呼び出したプロセスがセッションリーダーである場合、セッションは実際にttyから切り離され、セッションからフォアグラウンドプロセスグループにSIGHUP
/SIGCONT
ペアが送信されます。しかし、それでもターミナルはない閉じられ、プロセスは、次の状態を生き延びれば、引き続きそこから読み取ることができますSIGHUP
。
$ script /dev/null -c 'trap "" HUP; exec ./tiocnotty cat'
Script started, file is /dev/null
lol
lol
^C^C^C^C^C # no controlling tty anymore
wtf
wtf
^D # but still reading fine from it
Script done, file is /dev/null
/dev/tty
/dev/stdin
は、procfs のような仮想動的ファイルシステムよりずっと前に (そして一般的なシンボリックリンクよりずっと前に) 発明されたため、 => /dev/fd/0
=> /proc/self/fd/0
=>のようなシンボリックリンクではありません/dev/pts/0
。そして、多くのプログラムがその特定のセマンティクスに依存するようになりました (例:制御端末にアクセスできない場合/dev/tty
に失敗するENODEV
)。