![куда идут данные, записанные в файловый дескриптор, который никогда не открывался](https://rvso.com/image/89176/%D0%BA%D1%83%D0%B4%D0%B0%20%D0%B8%D0%B4%D1%83%D1%82%20%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D0%B5%2C%20%D0%B7%D0%B0%D0%BF%D0%B8%D1%81%D0%B0%D0%BD%D0%BD%D1%8B%D0%B5%20%D0%B2%20%D1%84%D0%B0%D0%B9%D0%BB%D0%BE%D0%B2%D1%8B%D0%B9%20%D0%B4%D0%B5%D1%81%D0%BA%D1%80%D0%B8%D0%BF%D1%82%D0%BE%D1%80%2C%20%D0%BA%D0%BE%D1%82%D0%BE%D1%80%D1%8B%D0%B9%20%D0%BD%D0%B8%D0%BA%D0%BE%D0%B3%D0%B4%D0%B0%20%D0%BD%D0%B5%20%D0%BE%D1%82%D0%BA%D1%80%D1%8B%D0%B2%D0%B0%D0%BB%D1%81%D1%8F.png)
Я захватил вывод с помощью следующей команды:
$ strace -f -e trace=process,socketpair,open,close,dup,dup2,read,write -o rsync.log rsync -avcz --progress src/ dst/
он немного длинный, поэтому я его загрузилздесь. Теперь я хочу провести анализ этого файла.
Следующий вывод показывает порожденные процессы/потоки с использованием clone
системного вызова:
# SPAWNED PROCESSES/THREADS
$ grep 'clone(' rsync.log | awk '{print $1 " -> " $NF}'
1399 -> 1400
1400 -> 1401
Следующий вывод показывает, что в большинстве случаев данные были write
n в файловом дескрипторе с номером 4
:
# PID, FD, NO OF CALLING WRITE SYSCALL
$ cat <(grep 'write(' rsync.log | egrep -v 'unfinished|resumed') <(paste <(grep write rsync.log | grep unfinished) <(grep write rsync.log | grep resumed)) | cut -d',' -f1 | sed 's%write(%%' | awk '{a[$0]++}END{print "PID FD COUNT"; for(i in a){print i " " a[i]}}'
PID FD COUNT
1399 4 1622
1400 1 7
1401 3 307
1401 4 7
1399 1 15
Следующий вывод показывает, что 4
дескриптор никогда не открывался с помощью open
системного вызова (1 — это STDOUT, поэтому я предполагаю, что открывать этот FD нет необходимости):
# LIST OF FILE DESCRIPTORS THAT WAS OPEN
$ grep 'open(' rsync.log | awk 'BEGIN {FS=" = "} {print $NF}' | grep '^[0-9]\+$' | sort | uniq
0
3
6
Два вопроса:
I. Если 4
дескриптор не был open
изменен, куда попадают эти данные и как это возможно, что rsync
все работает так, как ожидалось?:
$ grep 'write(4' rsync.log | head
1399 write(4, "\37\0\0\0", 4 <unfinished ...>
1399 write(4, "I\0\0\7\5(\1.\0\0\0W}%i\360\220\261\177\21\370A\0\0\0\203\347\6vbox"..., 77 <unfinished ...>
1401 write(4, "\4\0\0\7\376\377\377\377", 8) = 8
1399 write(4, "\177\301\0\7\3\n\200\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\177\377\354\226C\214.\0\260"..., 49539) = 49539
1399 write(4, "\2\301\0\7\177\377a\353\35\2433\1\332m\301\330\266\315\216\3557\352\330\266m\333\366\33\333\266;v"..., 49414) = 49414
1399 write(4, "\21\302\0\7\177\377\236mTNG\356\304\376u\237\214\275\310\300*\317\264\221W\372\340\307\36\345%\330"..., 49685 <unfinished ...>
1399 write(4, "\360\300\0\7\177\377\27W\357\24$\f\23,\v\216\355\371\306\266m\333\266m\333\266m\333\266m\333\266"..., 49396 <unfinished ...>
1399 write(4, "\223\301\0\7\177\377D\214# D\304\2\25xA\fY\310U\201Q*e\25\235\20\213\v\320~\331"..., 49559 <unfinished ...>
1399 write(4, "\370\300\0\7\177\377l\275cs.\0\27$\30\334\330\266}c\333\266m\333\266\235<\261m\333\266m"..., 49404 <unfinished ...>
1399 write(4, "\20\301\0\7\177\377\25\255\252Q\223\340\244w3\247\252\322Z\235\310\2424g\330\274\354\3150\237B\26"..., 49428) = 49428
II. Могу ли я как-то получить данные (соответствующие строки), которые были переданы между процессами, например: из 1399
в 1400
или из 1399
в 1401
и т. д. (если таковые имеются)?
Спасибо
решение1
Данные, записанные в файловый дескриптор, который никогда не открывался, никуда не попадают. write
Системный вызов завершается с ошибкой EBADF
(плохой файловый дескриптор).
Номеух заметил, open
это не единственный способ открыть файл. Также есть pipe
возможность создать пару концов канала, socketpair
создать пару сокетов, которые общаются друг с другом, socket
и accept
создать сокеты, которые общаются с удаленным адресом и т. д. (Не говоря уже о типах файлов, которые вы не можете write
открыть, например, каталоги, очереди событий inotify и т. д.)