Системные вызовы не обрабатываются как вызовы регулярной функции. Это берет специальный код для создания перехода от пространства пользователя до пространства ядра, в основном немного кода встроенного ассемблерного кода введенный в программу на сайте вызова. Код стороны ядра, который "ловит" системный вызов, является также материалом низкого уровня, который Вы, вероятно, не должны понимать глубоко по крайней мере сначала.
В include/linux/syscalls.h
в соответствии с Вашим исходным каталогом ядра, Вы находите это:
asmlinkage long sys_mkdir(const char __user *pathname, int mode);
Затем в /usr/include/asm*/unistd.h
, Вы находите это:
#define __NR_mkdir 83
__SYSCALL(__NR_mkdir, sys_mkdir)
В этом коде говорится mkdir(2)
системный вызов № 83. То есть системные вызовы называет число, не адресом как с нормальным вызовом функции в рамках Вашей собственной программы или к функции в библиотеке, связанной с Вашей программой. Связующее звено встроенного ассемблерного кода кодирует, я упомянул выше использования это для создания перехода от пользователя к пространству ядра, беря параметры наряду с ним.
Другой бит доказательства, что вещи являются немного странными здесь, - то, что существует не всегда строгий список параметров для системных вызовов: open(2)
, например, может взять или 2 или 3 параметра. Это означает open(2)
перегружается, функция C++, не C, все же интерфейс syscall является C-compatible. (Это не то же самое как функция C varargs, которая позволяет единственной функции брать переменное количество аргументов.)
Для ответа на первый вопрос нет никакого единственного файла где mkdir()
существует. Linux поддерживает много различных файловых систем, и у каждого есть его собственная реализация "mkdir" операции. Уровень абстракции, который позволяет ядру скрыть все, что позади вызова единой системы называют VFS. Так, Вы, вероятно, хотите начать закапывать fs/namei.c
, с vfs_mkdir()
. Фактическая реализация кода изменения файловой системы низкого уровня в другом месте. Например, ext4 реализацию называют ext4_mkdir()
, определенный в fs/ext4/namei.c
.
Что касается Вашего второго вопроса, да существуют шаблоны ко всему этому, но ни одно правило. То, в чем Вы на самом деле нуждаетесь, является довольно широким пониманием того, как ядро работает для выяснения, где необходимо искать какой-то конкретный системный вызов. Не все системные вызовы включают VFS, таким образом, их цепочки вызовов стороны ядра выполняют не, все запускают fs/namei.c
. mmap(2)
, например, запускается в mm/mmap.c
, потому что это - часть управления памятью ("мм") подсистема ядра.
Я рекомендую получить копию "Понимания Ядра Linux" Bovet и Cesati.
Начиная с ядра 3.3, это - возможное использование ss
или lsof-4.89
или выше — см. ответ Stéphane Chazelas.
В более старых версиях, по словам автора lsof
, было невозможно узнать это: ядро Linux не выставляет эту информацию. Источник: поток 2003 года на comp.unix.admin.
Число, показанное в /proc/$pid/fd/$fd
inode число сокета в виртуальной файловой системе сокета. При создании канала или пары сокета каждый конец последовательно получает inode число. Числа приписываются последовательно, таким образом, существует высокая вероятность, что числа отличаются 1, но это не гарантируется (или потому что первый сокет был N, и N+1 уже использовался из-за обертывания, или потому что некоторый другой поток был запланирован между двумя inode выделениями, и тот поток создал некоторый inodes также).
Я проверил определение socketpair
в ядре 2.6.39 и двух концах сокета не коррелируются кроме определенным для типа socketpair
метод. Для сокетов Unix это unix_socketpair
в net/unix/af_unix.c
.
Erkki Seppala на самом деле имеет инструмент, который получает эту информацию от ядра Linux с gdb.. Это доступно здесь.
ПРИМЕЧАНИЕ : Я сейчас поддерживаю обертку
LSOF
, который сочетает в себе оба подхода, описанные здесь, а также добавляет информацию для сверстников соединений TCP обратной связи в https://github.com/stephane-Chazelas/misc-scripts/blob/master/lsofc
В Linux, поскольку ядра версии 3.3 (и предоставлена функция Unix_diag
, встроена в ядре), сверстник данного домена Unix (включает в себя сокет отправления) можно получить с помощью нового NetLink на основе API.
LSOF
Поскольку версия 4.89 может воспользоваться этим API:
lsof +E -aUc Xorg
будет перечислять все розетки домена UNIX, которые имеют процесс, имя которого начинается с xorg
при любом конце в формате, аналогичном :
Xorg 2777 root 56u unix 0xffff8802419a7c00 0t0 34036 @/tmp/.X11-unix/X0 type=STREAM ->INO=33273 4120,xterm,3u
Если ваша версия LSOF
слишком старая, есть еще несколько вариантов.
Утилита SS
(из IPROUTE2
) использует эту же API для извлечения и отображения информации в списке доменных сокетов Unix в системе, включая информацию о свертчике.
Розетки идентифицируются своим номером INODE . Обратите внимание, что это не связано с inode файловой системы файла сокета.
Например, в:
$ ss -x
[...]
u_str ESTAB 0 0 @/tmp/.X11-unix/X0 3435997 * 3435996
написано, что разъем 3435997 (который был связан с абстрактным розеткой /tmp/.x11-unix/x0
)) подключен с разъемом 3435996. - P
Опция может сказать вам, какой процесс (ES) открыт этот сокет. Это делает это, делая некоторые readLink
/ / proc / $ PID / FD / *
, так что он может сделать это только в своих процессах (если только вы root
). Например, здесь:
$ sudo ss -xp
[...]
u_str ESTAB 0 0 @/tmp/.X11-unix/X0 3435997 * 3435996 users:(("Xorg",pid=3080,fd=83))
[...]
$ sudo ls -l /proc/3080/fd/23
lrwx------ 1 root root 64 Mar 12 16:34 /proc/3080/fd/83 -> socket:[3435997]
Чтобы узнать, какой процесс (ES) имеет 3435996, вы можете посмотреть свой вход в вывод SS -xp
:
$ ss -xp | awk '$6 == 3435996'
u_str ESTAB 0 0 * 3435996 * 3435997 users:(("xterm",pid=29215,fd=3))
Вы также можете использовать этот скрипт как Обелочка вокруг LSOF
, чтобы легко показать соответствующую информацию там:
#! /usr/bin/perl
# lsof wrapper to add peer information for unix domain socket.
# Needs Linux 3.3 or above and CONFIG_UNIX_DIAG enabled.
# retrieve peer and direction information from ss
my (%peer, %dir);
open SS, '-|', 'ss', '-nexa';
while (<SS>) {
if (/\s(\d+)\s+\*\s+(\d+) ([<-]-[->])$/) {
$peer{$1} = $2;
$dir{$1} = $3;
}
}
close SS;
# Now get info about processes tied to sockets using lsof
my (%fields, %proc);
open LSOF, '-|', 'lsof', '-nPUFpcfin';
while (<LSOF>) {
if (/(.)(.*)/) {
$fields{$1} = $2;
if ($1 eq 'n') {
$proc{$fields{i}}->{"$fields{c},$fields{p}" .
($fields{n} =~ m{^([@/].*?)( type=\w+)?$} ? ",$1" : "")} = "";
}
}
}
close LSOF;
# and finally process the lsof output
open LSOF, '-|', 'lsof', @ARGV;
while (<LSOF>) {
chomp;
if (/\sunix\s+\S+\s+\S+\s+(\d+)\s/) {
my $peer = $peer{$1};
if (defined($peer)) {
$_ .= $peer ?
" ${dir{$1}} $peer\[" . (join("|", keys%{$proc{$peer}})||"?") . "]" :
"[LISTENING]";
}
}
print "$_\n";
}
close LSOF or exit(1);
Например:
$ sudo that-lsof-wrapper -ad3 -p 29215 COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME xterm 29215 stephane 3u unix 0xffff8800a07da4c0 0t0 3435996 type=STREAM <-> 3435997[Xorg,3080,@/tmp/.X11-unix/X0]
Старый API Linux для получения информации о сокете Unix - через / proc / net / Unix
Текстовый файл. Он перечисляет все сокеты домена UNIX (включая сокет отправления). Первое поле там (если не скрыто для не суперпроужиров с помощью Kernel.kptr_restrict
Sysctl Parameter) AS , уже объяснено @TOTOR , содержит адрес ядра A Unix_sock
Структура, которая содержит поля Peer
, указывая на соответствующую Peer Unix_sock
. Это также то, что выходы LSOF
для столбца в столбце
на разъеме Unix.
Теперь получение стоимости этого Peer
поле означает возможность читать память ядра и знать смещение поля Peer
в зависимости от адреса Unix_sock
Отказ
Несколько GDB
и и SystemTap
решений уже даны, но они требуют GDB
/ SystemTap
И символы отладки ядра Linux для установки беговой ядра, который, как правило, не имеет место в производственных системах.
Харкодирование смещения не совсем вариант, так как это варьируется в зависимости от версии ядра.
Теперь мы можем использовать эвристический подход при определении смещения: у нашего инструмента создать манекен Socketpair
(тогда мы знаем адрес обоих сверстников),и поиск адреса Peer вокруг памяти на другом конце, чтобы определить смещение.
Вот подтверждающий концептуальный скрипт, который делает только что с использованием Perl
(успешно протестировано с ядром 2.4.27 и 2.6.32 на I386 и 3.13 и 3.16 на AMD64). Как указано выше, он работает как обертка вокруг LSOF
:
Например:
$ that-lsof-wrapper -aUc nm-applet COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME nm-applet 4183 stephane 4u unix 0xffff8800a055eb40 0t0 36888 type=STREAM -> 0xffff8800a055e7c0[dbus-daemon,4190,@/tmp/dbus-AiBCXOnuP6] nm-applet 4183 stephane 7u unix 0xffff8800a055e440 0t0 36890 type=STREAM -> 0xffff8800a055e0c0[Xorg,3080,@/tmp/.X11-unix/X0] nm-applet 4183 stephane 8u unix 0xffff8800a05c1040 0t0 36201 type=STREAM -> 0xffff8800a05c13c0[dbus-daemon,4118,@/tmp/dbus-yxxNr1NkYC] nm-applet 4183 stephane 11u unix 0xffff8800a055d080 0t0 36219 type=STREAM -> 0xffff8800a055d400[dbus-daemon,4118,@/tmp/dbus-yxxNr1NkYC] nm-applet 4183 stephane 12u unix 0xffff88022e0dfb80 0t0 36221 type=STREAM -> 0xffff88022e0df800[dbus-daemon,2268,/var/run/dbus/system_bus_socket] nm-applet 4183 stephane 13u unix 0xffff88022e0f80c0 0t0 37025 type=STREAM -> 0xffff88022e29ec00[dbus-daemon,2268,/var/run/dbus/system_bus_socket]
Вот сценарий:
#! /usr/bin/perl
# wrapper around lsof to add peer information for Unix
# domain sockets. needs lsof, and superuser privileges.
# Copyright Stephane Chazelas 2015, public domain.
# example: sudo this-lsof-wrapper -aUc Xorg
use Socket;
open K, "<", "/proc/kcore" or die "open kcore: $!";
read K, $h, 8192 # should be more than enough
or die "read kcore: $!";
# parse ELF header
my ($t,$o,$n) = unpack("x4Cx[C19L!]L!x[L!C8]S", $h);
$t = $t == 1 ? "L3x4Lx12" : "Lx4QQx8Qx16"; # program header ELF32 or ELF64
my @headers = unpack("x$o($t)$n",$h);
# read data from kcore at given address (obtaining file offset from ELF
# @headers)
sub readaddr {
my @h = @headers;
my ($addr, $length) = @_;
my $offset;
while (my ($t, $o, $v, $s) = splice @h, 0, 4) {
if ($addr >= $v && $addr < $v + $s) {
$offset = $o + $addr - $v;
if ($addr + $length - $v > $s) {
$length = $s - ($addr - $v);
}
last;
}
}
return undef unless defined($offset);
seek K, $offset, 0 or die "seek kcore: $!";
my $ret;
read K, $ret, $length or die "read($length) kcore \@$offset: $!";
return $ret;
}
# create a dummy socketpair to try find the offset in the
# kernel structure
socketpair(Rdr, Wtr, AF_UNIX, SOCK_STREAM, PF_UNSPEC)
or die "socketpair: $!";
$r = readlink("/proc/self/fd/" . fileno(Rdr)) or die "readlink Rdr: $!";
$r =~ /\[(\d+)/; $r = $1;
$w = readlink("/proc/self/fd/" . fileno(Wtr)) or die "readlink Wtr: $!";
$w =~ /\[(\d+)/; $w = $1;
# now $r and $w contain the socket inodes of both ends of the socketpair
die "Can't determine peer offset" unless $r && $w;
# get the inode->address mapping
open U, "<", "/proc/net/unix" or die "open unix: $!";
while (<U>) {
if (/^([0-9a-f]+):(?:\s+\S+){5}\s+(\d+)/) {
$addr{$2} = hex $1;
}
}
close U;
die "Can't determine peer offset" unless $addr{$r} && $addr{$w};
# read 2048 bytes starting at the address of Rdr and hope to find
# the address of Wtr referenced somewhere in there.
$around = readaddr $addr{$r}, 2048;
my $offset = 0;
my $ptr_size = length(pack("L!",0));
my $found;
for (unpack("L!*", $around)) {
if ($_ == $addr{$w}) {
$found = 1;
last;
}
$offset += $ptr_size;
}
die "Can't determine peer offset" unless $found;
my %peer;
# now retrieve peer for each socket
for my $inode (keys %addr) {
$peer{$addr{$inode}} = unpack("L!", readaddr($addr{$inode}+$offset,$ptr_size));
}
close K;
# Now get info about processes tied to sockets using lsof
my (%fields, %proc);
open LSOF, '-|', 'lsof', '-nPUFpcfdn';
while (<LSOF>) {
if (/(.)(.*)/) {
$fields{$1} = $2;
if ($1 eq 'n') {
$proc{hex($fields{d})}->{"$fields{c},$fields{p}" .
($fields{n} =~ m{^([@/].*?)( type=\w+)?$} ? ",$1" : "")} = "";
}
}
}
close LSOF;
# and finally process the lsof output
open LSOF, '-|', 'lsof', @ARGV;
while (<LSOF>) {
chomp;
for my $addr (/0x[0-9a-f]+/g) {
$addr = hex $addr;
my $peer = $peer{$addr};
if (defined($peer)) {
$_ .= $peer ?
sprintf(" -> 0x%x[", $peer) . join("|", keys%{$proc{$peer}}) . "]" :
"[LISTENING]";
last;
}
}
print "$_\n";
}
close LSOF or exit(1);
Это решение, хотя и работает, но представляет ограниченный интерес, так как если у вас есть достаточно свежая системная запись, то, скорее всего, у вас будет достаточно свежее ядро, в котором вы можете использовать
ss
на основе подходов , а если вы используете более старое ядро, то это другое решение , хотя более hacky более вероятно будет работать и не требует дополнительного программного обеспечения.По-прежнему полезно в качестве демонстрации того, как использовать
systemtap
для такого рода задач.
Если на недавней системе Linux с рабочей системной записью (1.8 или более новой), вы можете использовать скрипт ниже для постобработки вывода lsof
:
Например:
$ lsof -aUc nm-applet | sudo that-script COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME nm-applet 4183 stephane 4u unix 0xffff8800a055eb40 0t0 36888 type=STREAM -> 0xffff8800a055e7c0[dbus-daemon,4190,@/tmp/dbus-AiBCXOnuP6] nm-applet 4183 stephane 7u unix 0xffff8800a055e440 0t0 36890 type=STREAM -> 0xffff8800a055e0c0[Xorg,3080,@/tmp/.X11-unix/X0] nm-applet 4183 stephane 8u unix 0xffff8800a05c1040 0t0 36201 type=STREAM -> 0xffff8800a05c13c0[dbus-daemon,4118,@/tmp/dbus-yxxNr1NkYC] nm-applet 4183 stephane 11u unix 0xffff8800a055d080 0t0 36219 type=STREAM -> 0xffff8800a055d400[dbus-daemon,4118,@/tmp/dbus-yxxNr1NkYC] nm-applet 4183 stephane 12u unix 0xffff88022e0dfb80 0t0 36221 type=STREAM -> 0xffff88022e0df800[dbus-daemon,2268,/var/run/dbus/system_bus_socket] nm-applet 4183 stephane 13u unix 0xffff88022e0f80c0 0t0 37025 type=STREAM -> 0xffff88022e29ec00[dbus-daemon,2268,/var/run/dbus/system_bus_socket]
(если вы видите 0x000000000000 выше вместо 0xffff.... то это потому, что в вашей системе установлен sysctl параметр kernel.kptr_restrict
, что приводит к сокрытию указателей ядра от непривилегированных процессов, и в этом случае для получения значимого результата необходимо запустить lsof
в качестве корня).
Этот скрипт не делает никаких попыток справиться с именами файлов сокетов с символами новой строки, но также lsof
(и lsof
не справляется с пробелами или двоеточиями). Здесь
systemtap
используется для дампа адреса и однорангового адреса всех структур unix_sock
в хэше unix_socket_table
кернела.
Только в Linux 3.16 amd64 с systemtap 2.6 и 3.13 с 2.3.
#! /usr/bin/perl
# meant to process lsof output to try and find the peer of a given
# unix domain socket. Needs a working systemtap, lsof, and superuser
# privileges. Copyright Stephane Chazelas 2015, public domain.
# Example: lsof -aUc X | sudo this-script
open STAP, '-|', 'stap', '-e', q{
probe begin {
offset = &@cast(0, "struct sock")->__sk_common->skc_node;
for (i = 0; i < 512; i++)
for (p = @var("unix_socket_table@net/unix/af_unix.c")[i]->first;
p;
p=@cast(p, "struct hlist_node")->next
) {
sock = p - offset;
printf("%p %p\n", sock, @cast(sock, "struct unix_sock")->peer);
}
exit()
}
};
my %peer;
while (<STAP>) {
chomp;
my ($a, $b) = split;
$peer{$a} = $b;
}
close STAP;
my %f, %addr;
open LSOF, '-|', 'lsof', '-nPUFpcfdn';
while (<LSOF>) {
if (/(.)(.*)/) {
$f{$1} = $2;
if ($1 eq 'n') {
$addr{$f{d}}->{"$f{c},$f{p}" . ($f{n} =~ m{^([@/].*?)( type=\w+)?$} ? ",$1" : "")} = "";
}
}
}
close LSOF;
while (<>) {
chomp;
for my $addr (/0x[0-9a-f]+/g) {
my $peer = $peer{$addr};
if (defined($peer)) {
$_ .= $peer eq '0x0' ?
"[LISTENING]" :
" -> $peer\[" . join("|", keys%{$addr{$peer}}) . "]";
last;
}
}
print "$_\n";
}
Вы можете теперь получить эту информацию с помощью ss
:
# ss -xp
Теперь вы можете увидеть в столбце Peer
ID (номер inode), который соответствует другому ID в столбце Local
. Соответствующие идентификаторы - это два конца сокета.
Примечание. В вашем ядре должна быть включена опция UNIX_DIAG
.
Linux не предоставлял эту информацию пользователю.
Однако, заглянув в память ядра , мы можем получить доступ к этой информации.
Примечание. В этом ответе используется gdb
, однако, пожалуйста, см. Ответ @ StéphaneChazelas , который более подробно описан в этом отношении.
# lsof | grep whatever
mysqld 14450 (...) unix 0xffff8801011e8280 (...) /var/run/mysqld/mysqld.sock
mysqld 14450 (...) unix 0xffff8801011e9600 (...) /var/run/mysqld/mysqld.sock
Имеется 2 разных сокета, 1 прослушивающий и 1 установленный. Шестнадцатеричное число - это адрес соответствующей структуры ядра unix_sock
, имеющей атрибут peer
, являющийся адресом другого конца сокета (также экземпляр структуры unix_sock
).
Теперь мы можем использовать gdb
, чтобы найти одноранговый узел
в памяти ядра:
# gdb /usr/lib/debug/boot/vmlinux-3.2.0-4-amd64 /proc/kcore
(gdb) print ((struct unix_sock*)0xffff8801011e9600)->peer
$1 = (struct sock *) 0xffff880171f078c0
# lsof | grep 0xffff880171f078c0
mysql 14815 (...) unix 0xffff880171f078c0 (...) socket
Итак, другой конец сокета удерживается mysql
], PID 14815.
Ваше ядро должно быть скомпилировано с KCORE_ELF
, чтобы использовать / proc / kcore
. Кроме того, вам понадобится версия образа ядра с отладочными символами. В Debian 7 этот файл предоставит apt-get install linux-image-3.2.0-4-amd64-dbg
.
Если у вас нет (или вы не хотите сохранять) образ ядра отладки в системе, вы можете дать gdb
смещение памяти для «ручного» доступа к одноранговому узлу
значение. Это значение смещения обычно отличается в зависимости от версии ядра или архитектуры.
Я знаю, что в моем ядре смещение составляет 680 байт, то есть в 85 раз больше по 64 бита. Итак, я могу сделать:
# gdb /boot/vmlinux-3.2.0-4-amd64 /proc/kcore
(gdb) print ((void**)0xffff8801011e9600)[85]
$1 = (void *) 0xffff880171f078c0
Voilà, тот же результат, что и выше.
Если у вас одно и то же ядро работает на нескольких машинах, этот вариант проще использовать, потому что вам не нужен отладочный образ, а только значение смещения.
Чтобы (легко) обнаружить это значение смещения сначала, вам понадобится отладочный образ:
$ pahole -C unix_sock /usr/lib/debug/boot/vmlinux-3.2.0-4-amd64
struct unix_sock {
(...)
struct sock * peer; /* 680 8 */
(...)
}
Вот, 680 байт, это 85 x 64 бита или 170 x 32 бита.
Большая заслуга в этом ответе принадлежит MvG .
4.89 lsof поддерживает отображение параметров конечной точки.
Цитата из lsof.8:
+|-E +E specifies that process intercommunication channels should be
displayed with endpoint information and the channels
of the endpoints should also be displayed. Currently
only pipe on Linux is implemented.
Endpoint information is displayed in the NAME column
in the form "PID,cmd,FDmode". PID is the endpoint
process ID; cmd is the endpoint process command; FD is
the endpoint file's descriptor; and mode is the
endpoint file's access mode. Multiple occurrences of
this information can appear in a file's NAME column.
-E specfies that Linux pipe files should only be
displayed with endpoint information.
Пример вывода:
mozStorag 21535 22254 yamato 6u unix 0xf... 0t0 348924 type=STREAM pino=351122 4249,dbus-daem,55u
mozStorag 21535 22254 yamato 10u unix 0xf... 0t0 356193 type=STREAM pino=356194 21535,gdbus,11u
mozStorag 21535 22254 yamato 11u unix 0xf... 0t0 356194 type=STREAM pino=356193 21535,gdbus,10u
mozStorag 21535 22254 yamato 21u unix 0xf... 0t0 355141 type=STREAM pino=357544 4249,dbus-daem,60u
mozStorag 21535 22254 yamato 26u unix 0xf... 0t0 351134 type=STREAM pino=355142 5015,gdbus,17u
mozStorag 21535 22254 yamato 69u unix 0xf... 0t0 469354 type=STREAM pino=468160 4545,alsa-sink,21u
mozStorag 21535 22254 yamato 82u unix 0xf... 0t0 449383 type=STREAM pino=449384 12257,Chrome_Ch,3u
mozStorag 21535 22254 yamato 86u unix 0xf... 0t0 355174 type=SEQPACKET pino=355175 21535,gdbus,95u
mozStorag 21535 22254 yamato 95u unix 0xf... 0t0 355175 type=SEQPACKET pino=355174 21535,gdbus,86u 12257,Chrome_Ch,4u
mozStorag 21535 22254 yamato 100u unix 0xf... 0t0 449389 type=STREAM pino=456453 3614,Xorg,38u
mozStorag 21535 22254 yamato 105u unix 0xf... 0t0 582613 type=STREAM pino=586261
obexd 22163 yamato 1u unix 0xf... 0t0 361859 type=STREAM pino=365931
obexd 22163 yamato 2u unix 0xf... 0t0 361860 type=STREAM pino=365934
obexd 22163 yamato 3u unix 0xf... 0t0 361241 type=DGRAM pino=10028
obexd 22163 yamato 6u unix 0xf... 0t0 361242 type=STREAM pino=361864 4249,dbus-daem,70u
Начиная с ядра Linux 4.2 существует CONFIG_UNIX_DIAG
, который предоставляет дополнительную информацию о сокетах домена UNIX, а именноVirtual File System
(информацию VFS ), которая содержит до сих пор отсутствующую информацию для связи Inode с пути к процессу..Его уже можно запросить с помощью инструмента ss
из iproute2 , начиная с версии v4.19.0 ~55:
$ ss --processes --unix --all --extened
...
Netid State Recv-Q Send-Q Local Address:Port Peer Address:Port
u_str LISTEN 0 5 /tmp/socket 13381347 * 0 users:(("nc",pid=12550,fd=3)) <-> ino:1569897 dev:0/65025 peers:
Номер устройства и Inode пути, которые вы можете получить из
$ stat -c 'ino:%i dev:0/%d' /tmp/socket
ino:1569946 dev:0/65025
ss
также поддерживает фильтрацию:
ss --processes --unix --all --extended 'sport = /tmp/socket'
но имейте в виду, что здесь может быть указан не тот сокет, который вам нужен, так как злой процесс может переименовать исходный сокет и заменить его собственным злым:
mv /tmp/socket /tmp/socket.orig
nc -U -l /tmp/socket.evil &
mv /tmp/socket.evil /tmp/socket
lsof /tmp/socket
, fuser /tmp/socket
и ss --processes --unix --all --extended 'sport = /tmp/socket'
будут перечислять исходный процесс, , а не замену злого. Вместо этого используйте что-то вроде этого:
id=$(stat -c 'ino:%i dev:0/%d' /tmp/socket)
ss --processes --unix --all --extended | grep -F "$id"
Или напишите свою маленькую программу на основе шаблона, содержащегося в man 7 sock _diag .
Я бы использовал px .
Отказ от ответственности :Я написал это, поэтому, конечно, я рекомендую это.
px
сообщит вам, с какими другими процессами общается ваш.
Пример вывода, прокрутите вниз для трассировки сокетов:
~ $ sudo px 49903
/Applications/Google Chrome.app/Contents/MacOS/Google Chrome
--enable-audio-service-sandbox
--origin-trial-disabled-features=MeasureMemory
kernel(0) root
launchd(1) root
--> Google Chrome(49903) johan
Google Chrome Helper(49922) johan
Google Chrome Helper(49958) johan
Google Chrome Helper (GPU)(49920) johan
Google Chrome Helper (Renderer)(49935) johan
Google Chrome Helper (Renderer)(49936) johan
Google Chrome Helper (Renderer)(49943) johan
Google Chrome Helper (Renderer)(49950) johan
Google Chrome Helper (Renderer)(49951) johan
Google Chrome Helper (Renderer)(49957) johan
Google Chrome Helper (Renderer)(64466) johan
Google Chrome Helper (Renderer)(75275) johan
Google Chrome Helper (Renderer)(76225) johan
Google Chrome Helper (Renderer)(76650) johan
Google Chrome Helper (Renderer)(76668) johan
Google Chrome Helper (Renderer)(76712) johan
7d21h ago Google Chrome was started, at 2020-09-04T19:15:03+02:00.
0.3% has been its average CPU usage since then, or 32m25s/7d21h
Other processes started close to Google Chrome(49903):
Google Chrome/chrome_crashpad_handler(49912) was started just after Google Chrome(49903)
AlertNotificationService(49924) was started 1.0s after Google Chrome(49903)
Google Chrome Helper(49922) was started 1.0s after Google Chrome(49903)
Google Chrome Helper (GPU)(49920) was started 1.0s after Google Chrome(49903)
Google Chrome Helper (Renderer)(49935) was started 1.0s after Google Chrome(49903)
Google Chrome Helper (Renderer)(49936) was started 1.0s after Google Chrome(49903)
VTDecoderXPCService(49934) was started 1.0s after Google Chrome(49903)
Users logged in when Google Chrome(49903) started:
johan
2020-09-12T16:28:30.587930: Now invoking lsof, this can take over a minute on a big system...
2020-09-12T16:28:30.901834: lsof done, proceeding.
Others sharing this process' working directory (/)
Working directory too common, never mind.
File descriptors:
stdin : [CHR] /dev/null
stdout: [CHR] /dev/null
stderr: [CHR] /dev/null
Network connections:
[IPv4] *:* (LISTEN)
Inter Process Communication:
mDNSResponder(291): [unix] ->0x2b8028c5de1ab5b
mDNSResponder(291): [unix] ->0x2b8028c5de1c5eb
For a list of all open files, do "sudo lsof -p 49903", or "sudo watch lsof -p 49903" for a live view.
~ $
socketpair
, и два конца сокета не коррелируются кроме определенным для типаsocketpair
метод. Для сокетов Unix этоunix_socketpair
в 'net/unix/af_unix.c. Было бы хорошо иметь эту информацию для каналов, также. – Gilles 'SO- stop being evil' 10.07.2011, 01:35