擬似端末には、一対のマスター装置とスレーブ装置があります。
スレーブデバイスファイルでマスターデバイスファイル(例)をどのように検索しますか/etc/pts/3
?私は見つけ/dev/ptmx
ましたが、/dev/pts/ptmx
いくつかの奴隷が共有することはできません。
マスターとスレーブで実行されているプロセスの1つが与えられたら、他のプロセスをどのように見つけることができますか?たとえば、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
2つsshd
のプロセス(pid 975と978)がマスターへのハンドルを開きました(1つは9 fd用、もう1つは14、18、19 fd用)。標準(0、1、2)fdでスレーブ側に開いたハンドルがありますsleep
。-bash
セッションリーダー(bash
)も*
、前景プロセス(および)も表示され、バックグラウンドプロセス(およびperl
)も表示されます。cut
+
less
-bash
-
これらのt/ct_test
プロセスは、 fd が開かれていない状態で pty を制御端末として使用します。tiocsti
開いたハンドルがありますが、制御端末ではありません。
Debian 9とFedora 28でテストされました。使用されるマジックナンバーに関する情報は以下にあります。procfs(5)
そしてDocumentation/admin-guide/devices.txt
Linuxカーネルのソースコードから。
これは、chrootまたは名前空間コンテナを使用するすべてのシステムで失敗します。フィールドをptyに一致させ、fdをtty
適切なマウントで開く安定した方法がないため、カーネルを一部変更しないと変更できません。/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 +E
ptm / ptsを含むFDの両端に関する情報を提供しているようです。