상대방의 의사 단말 마스터와 슬레이브를 어떻게 알 수 있나요?

상대방의 의사 단말 마스터와 슬레이브를 어떻게 알 수 있나요?

의사 터미널에는 한 쌍의 마스터 장치와 슬레이브 장치가 있습니다.

슬레이브 장치 파일에서 마스터 장치 파일(예:)을 어떻게 찾나요 /etc/pts/3? 나는 찾았 /dev/ptmx지만 /dev/pts/ptmx여러 노예가 공유할 수는 없습니다.

마스터와 슬레이브에서 실행되는 프로세스 중 하나가 주어지면 다른 프로세스를 어떻게 찾을 수 있습니까? 예를 들어, ps각 프로세스의 제어 tty에 대한 정보를 제공합니다. 도움이 되었나요?

감사해요.

답변1

이것은 해야 할 일보다 하기가 더 어려운 일입니다.

tty-index최신 Linux 커널의 경우 마스터와 쌍을 이루는 슬레이브 pty의 인덱스는 다음 항목에서 수집할 수 있습니다 /proc/PID/fdinfo/FD. 이것 좀 봐범죄.

이전 커널에서 이를 달성하는 유일한 방법은 마스터 pty를 보유하는 프로세스에 디버거를 연결하고 파일 설명자를 호출 ptsname(3)(또는 직접 호출)하는 것입니다.ioctl(TIOCGPTN)

[그러나 여러 devpt 마운트를 사용하는 시스템에서는 두 방법 모두 문제가 발생합니다. 아래를 참조하세요.]

이 정보를 사용하여 마스터-슬레이브 페어링 목록을 구축할 수 있으며 이를 통해 슬레이브 장치에서 마스터 검색을 시작할 수도 있습니다.

다음은 해당 tty-index방법을 먼저 시도한 다음 작동하지 않는 경우 gdb. 후자의 경우,피복재 gdb(대부분의 배포판은 그렇지 않거나 gdb-minimal절반 정도 깨졌습니다 gdb) 사용으로 gdb인해아주 느린.

각 pty 쌍에 대해 다음과 같이 인쇄됩니다.

/dev/pts/1
    1227  3     t/ct_test
        1228  +*      t/ct_test
        1230  +      t/ct_test
/dev/pts/3
    975   9     'sshd: root [priv]' '' '' '' '' '' '' '' ''
    978   14,18,19   'sshd: root@pts/3' '' '' '' '' '' '' ''
        979   -*0,1,2,255   -bash
        1222  1     tiocsti
        1393  -0,1,2   sleep 3600
        1231  +0,2   perl ptys.pl
        1232  +1,2   cut -b1-60

sshd프로세스(pid 975 및 978)가 마스터에 대한 핸들을 열었습니다(하나는 9 fd용이고 다른 하나는 14, 18 및 19 fd용). 표준(0,1 및 2) fd로 슬레이브 측에 열린 핸들이 있습니다 sleep. -bash세션 리더( bash)도 로 표시되고 *, 포그라운드 프로세스( perlcut)도 로 표시되며 +, 백그라운드 프로세스( less-bash)도 로 표시됩니다 -.

이러한 t/ct_test프로세스는 fd가 열리지 않은 상태에서 pty를 제어 터미널로 사용합니다. tiocsti열린 손잡이가 있지만 제어 터미널은 아닙니다.

Debian 9 및 Fedora 28에서 테스트되었습니다. 사용되는 매직 넘버에 대한 정보는 다음에서 찾을 수 있습니다.procfs(5)그리고Documentation/admin-guide/devices.txt리눅스 커널 소스 코드에서.


이는 chroot 또는 네임스페이스 컨테이너를 사용하는 모든 시스템에서 실패합니다. 필드를 pty에 일치시키고 fd를 tty적절한 mount로 여는 안정적인 방법이 없기 때문에 커널을 일부 변경하지 않으면 수정할 수 없습니다 . /proc/PID/stat바라보다/dev/ptmx/dev/pts여기이것에 대해 호언 장담합니다.

/dev/tty이는 또한 다음을 통해 열린 fd 와 연결되지 않습니다 .진짜tty는 프로세스에 연결하고 호출하여 해결할 수 있지만 ioctl(fd, TIOCGDEV, &dev)이는 gdb를 또 다시 더럽게 많이 사용한다는 의미이며 위와 동일한 문제, 즉 의사 tty 슬레이브가 모호한 주 번호와 부 번호를 갖는 문제로 어려움을 겪게 됩니다.

ptys.pl:

my (%pty, %ctty);
for(</proc/*[0-9]*/{fd/*,stat}>){
    if(my ($pid, $fd) = m{/proc/(\d+)/fd/(\d+)}){
        next unless -c $_;
        my $rdev = (stat)[6]; my $maj = $rdev >> 8 & 0xfff;
        if($rdev == 0x502){ # /dev/ptmx or /dev/pts/ptmx
            $pty{ptsname($pid, $fd, readlink $_)}{m}{$pid}{$fd} = 1;
        }elsif($maj >= 136 && $maj <= 143){ # /dev/pts/N
            $pty{readlink $_}{s}{$pid}{$fd} = 1;
        }
    }else{
        my @s = readfile($_) =~ /(?<=\().*(?=\))|[^\s()]+/gs;
        $ctty{$s[6]}{$s[0]} =       # ctty{tty}{pid} =
            ($s[4] == $s[7] ? '+' : '-').   # pgrp == tpgid
            ($s[0] == $s[5] ? '*' : '');    # pid == sid
    }
}
for(sort {length($a)<=>length($b) or $a cmp $b} keys %pty){
    print "$_\n";
    pproc(4, $pty{$_}{m}); pproc(8, $pty{$_}{s}, $ctty{(stat)[6]});
}

sub readfile { local $/; my $h; open $h, '<', shift and <$h> }
sub cmdline {
    join ' ', map { s/'/'\\''/g, $_ = "'$_'" if m{^$|[^\w./+=-]}; $_ }
        readfile("/proc/$_[0]/cmdline") =~ /([^\0]*)\0/g;
}
sub pproc {
    my ($px, $h, $sinfo) = @_;
    exists $$h{$_} or $$h{$_} = {''} for keys %$sinfo;
    return printf "%*s???\n", $px, "" unless $h;
    for my $pid (sort {$a<=>$b} keys %$h){
        printf "%*s%-5d %s%-3s   %s\n", $px, "", $pid, $$sinfo{$pid},
            join(',', sort {$a<=>$b} keys %{$$h{$pid}}),
            cmdline $pid;
    }
}
sub ptsname {
    my ($pid, $fd, $ptmx) = @_;
    return '???' unless defined(my $ptn = getptn($pid, $fd));
    $ptmx =~ m{(.*)(?:/pts)?/ptmx$} ? "$1/pts/$ptn" : "$ptmx ..?? pts/$ptn"
}
sub getptn {
    my ($pid, $fd) = @_;
    return $1 if
        readfile("/proc/$pid/fdinfo/$fd") =~ /^tty-index:\s*(\d+)$/m;
    return gdb_ioctl($pid, $fd, 0x80045430);    # TIOCGPTN
}
sub gdb_ioctl {
    my ($pid, $fd, $ioctl) = @_;
    my $cmd = qq{p (int)ioctl($fd, $ioctl, &errno) ? -1 : errno};
    qx{exec 3>&1; gdb -batch -p $pid -ex '$cmd' 2>&1 >&3 |
            grep -v '/sysdeps/.*No such file or directory' >&2}
        =~ /^\$1 *= *(\d+)$/m ? $1 : undef;
}

답변2

Linux에서는 를 사용하세요 devpts. 마스터 장치 파일이 없습니다. 마스터 측 프로세스는 open 을 통해 얻은 파일 설명자를 사용 ptmx하지만 해당 장치 노드가 없습니다.

바라보다ptmx맨페이지더 알아보기.

(Linux의 BSD 버전의 경우 pty마스터 측과 슬레이브 측 모두 /dev/ptyp1및 와 같은 일치하는 장치 쌍을 갖습니다 /dev/ttyp1.)

답변3

lsof +Eptm/pts를 포함하여 FD의 양쪽 끝에 대한 정보를 제공하는 것 같습니다 .

관련 정보