현재 제어 터미널과 `/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
    

서로 다른 제어 터미널을 사용하는 서로 다른 세션의 경우 if 가 /dev/tty해당 터미널을 제어하는 ​​것으로 보장됩니다. 심볼릭 링크나 하드링크가 아닌 다른 제어 터미널이 어떻게 가능합니까?

그렇다면 그들의 관계와 차이점은 무엇입니까? 어떤 도움이라도 대단히 감사하겠습니다!

이 게시물은 이전 게시물에서 유래되었습니다`tty` 명령의 출력과 `/dev/tty` 파일이 모두 현재 bash 프로세스의 제어 터미널을 참조합니까?

답변1

tty섹션 4의 맨 페이지다음과 같이 주장합니다.

파일/dev/tty메이저 번호가 5이고 마이너 번호가 0인 문자 파일이며 일반적으로 모드는 0666이고 owner.group root.tty입니다. 프로세스의 제어 터미널(있는 경우)과 동의어입니다.

여기에 덧붙여ioctl(2)tty가 참조하는 장치에서 지원되는 요청ioctl(2)요청 TIOCNOTTY이 지원됩니다.

TIOCNOTTY

제어 터미널에서 호출 프로세스를 분리합니다.

프로세스가 세션 리더인 경우 신호 SIGHUPSIGCONT포그라운드 프로세스 그룹으로 전송되고 현재 세션의 모든 프로세스는 제어 tty를 잃습니다.

이것ioctl(2)호출은 다음에 연결된 파일 설명자에서만 작동합니다. /dev/tty. 이는 터미널에서 사용자가 호출할 때 데몬 프로세스에 의해 사용됩니다. 프로세스가 열려고 시도합니다./dev/tty. 열기에 성공하면 를 사용하여 터미널에서 자체적으로 분리되고 TIOCNOTTY, 열기에 실패하면 분명히 터미널에 연결되지 않으며 자체적으로 분리할 필요가 없습니다.

이는 제어 터미널에 대한 심볼릭 링크가 아닌 이유를 부분적으로 설명합니다 /dev/tty. 추가를 지원하고 ioctl제어 터미널이 없을 수도 있습니다(그러나 프로세스는 항상 액세스를 시도할 수 있습니다 /dev/tty). 그러나 문서가 올바르지 않습니다. 추가 항목에 ioctl액세스할 수 있을 뿐만 아니라~을 통해 /dev/tty(보다모스비의 대답, 이는 또한 의 성격에 대해 보다 합리적인 설명을 제공합니다 /dev/tty.

/dev/tty링크가 아닌 다른 제어 터미널을 나타낼 수 있습니다. 왜냐하면 이를 구현하는 드라이버가 호출 프로세스의 제어 터미널이 무엇인지 결정하기 때문입니다.

이것을 제어 터미널이라고 생각할 수 있으므로 /dev/tty제어 터미널에만 의미가 있는 기능을 제공하는 반면 /dev/pts/2기타는 일반 터미널이며 그 중 하나는 주어진 프로세스에 대한 제어 터미널이 될 수 있습니다.

답변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터미널의 a는 이를 종료합니다. 세션 리더가 아닌 프로세스에 대한 유일한 영향은 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/ttyprocfs와 같은 가상 동적 파일 시스템보다 오래 전에 (그리고 일반적으로 심볼릭 링크보다 오래 전에) 발명되었기 때문에 /dev/stdin=> /dev/fd/0=> /proc/self/fd/0=> 와 같은 심볼릭 링크가 아닙니다 . /dev/pts/0그리고 많은 프로그램이 특정 의미에 의존하게 되었습니다(예: 제어 터미널에 액세스할 수 없을 때 /dev/tty실패함 ).ENODEV

관련 정보