現在の制御端末と `/dev/tty`の関係は何ですか?

現在の制御端末と `/dev/tty`の関係は何ですか?

Lubuntu 18.04では、lxterminalでシェルを実行します。制御端子は現在擬似端子スレーブです。

$ tty
/dev/pts/2

現在の制御端末/dev/pts/2/dev/tty

  1. /dev/tty現在の制御端末と同じです/dev/pts/2

    $ echo hello > /dev/tty
    hello
    
    $ cat < /dev/tty
    world
    world
    ^C
    
  2. しかし、これらのファイルは、互いにシンボリックリンクやハードリンクというよりは関係のないファイルのようです。

    $ 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のマンページ主張は次のとおりです。

文書/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(望むよりMosviの答えまた、)の属性についてより合理的な説明を提供します/dev/tty

/dev/ttyリンクを実装するドライバは、呼び出しプロセスの制御端末が何であるかを決定するので、リンクとは異なる制御端末を表すことができる。

これを制御端末と考えることができるので、制御/dev/tty端末だけに意味のある機能を提供する一方、等は/dev/pts/2一般端末であり、その一つは与えられたプロセスの制御端末になることができます。

答え2

/dev/tty開いたときに現在の端末のハンドルを返す「魔法の」文字デバイス。

制御端末が仮定すると、/dev/pts/1via経由で開かれたファイル記述子/dev/pts/1とvia経由で開かれたファイル記述子は/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/ttyttyとしてリストされなくなることです/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/ pairをフォアグラウンドプロセスグループに送信します。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=> /dev/fd/0=> =>/proc/self/fd/0などのシンボリックリンクではありません/dev/pts/0。これは、procfsなどの仮想動的ファイルシステムの前に作成されたためです(通常はシンボリックリンクの前に作成されます)。多くのプログラムが特定の意味に依存するようになりました(例えば、制御端末にアクセスできないと失敗します/dev/tty)。ENODEV

関連情報