дізнайтеся, які дескриптори файлів мають однаковий "відкритий опис файлу"


17

Якщо я (в оболонці Борна):

exec 3> file 4>&3 5> file 6>> file

Дескриптори файлів 3 і 4, оскільки 4 було dup()видано з 3, мають однаковий опис відкритого файлу (ті ж властивості, те ж зміщення у файлі ...). Хоча дескриптори файлів 5 і 6 цього процесу знаходяться в іншому відкритому описі файлу (наприклад, кожен з них має свій вказівник у файлі).

Тепер у lsofвисновку все, що ми бачимо:

zsh     21519 stephane    3w   REG  254,2        0 10505865 /home/stephane/file
zsh     21519 stephane    4w   REG  254,2        0 10505865 /home/stephane/file
zsh     21519 stephane    5w   REG  254,2        0 10505865 /home/stephane/file
zsh     21519 stephane    6w   REG  254,2        0 10505865 /home/stephane/file

Це трохи краще з lsof +fg:

zsh     21519 stephane    3w   REG          W,LG  254,2        0 10505865 /home/stephane/file
zsh     21519 stephane    4w   REG          W,LG  254,2        0 10505865 /home/stephane/file
zsh     21519 stephane    5w   REG          W,LG  254,2        0 10505865 /home/stephane/file
zsh     21519 stephane    6w   REG       W,AP,LG  254,2        0 10505865 /home/stephane/file

(тут на Linux 3.16) в тому, що ми бачимо, що у fd 6 є різні прапори, тому він повинен бути різним описом відкритого файлу, ніж опис на fd 3, 4 або 5, але з цього ми не можемо сказати, що fd 5 знаходиться на a різні відкриті описи файлів . З -o, ми могли б також побачити зсув, але знову ж зміщення не гарантує , що це те ж саме відкрите опис файлу .

Чи є якийсь не нав'язливий 1 спосіб дізнатися це? Зовні або для власних дескрипторів файлів процесу?


1 . Одним із евристичних підходів може бути зміна прапорів одного fd fcntl()і перегляд того, в яких інших дескрипторах файлів оновлені їхні прапори як результат, але це очевидно не є ідеальним, ані дурним доказом


Такий підхід, в принципі, повинен працювати і не бути занадто руйнівним у більшості сценаріїв: спочатку розпрощайте дитину (з ptrace, якщо це робиться ззовні). Потім у дитини зробіть щось із дескриптором файлів, що не впливає на інші процеси. Для Linux оренда повинна працювати для цього.
Жил "ТАК - перестань бути злим"

@Gilles, дякую, але це більш-менш підхід, який я пропоную вже у питанні. оренда (припустимо, ви маєте на увазі F_SETLEASE fcntl, дякую за те, що я повідомив про них BTW) буде працювати лише для звичайних ваших файлів, але не, якщо в цей же файл (EBUSY) є ще один "записувати" відкритий опис , і це не зовсім -інструзивний.
Стефан Шазелас

Ви відмовились від цього питання? Я опублікував інформацію про те, як SystemTap міг робити те, що ви хочете, але ви жодної відповіді не позначив як повну ...?
Ажрей

Відповіді:


2

Для Linux 3.5 і далі це можна зробити за допомогою kcmp (3) :

KCMP_FILE

  • Перевірте, чи дескриптор файлу idx1 у процесі pid1 посилається на той самий опис відкритого файлу (див. Відкритий (2) ), що і дескриптор файлу idx2 у процесі pid2 . Існування двох дескрипторів файлів, які посилаються на один і той самий опис відкритого файлу, може статися в результаті дублювання (2) (і подібного) вилки (2) або передачі дескрипторів файлів через сокет домену (див. Unix (7) ).

Сторінка "man" надає приклад, спеціально для запиту вашої програми використання OP. Зауважте, що для цього системного виклику потрібно скомпілювати ядро ​​з CONFIG_CHECKPOINT_RESTOREнабором.


Спасибі. Саме те, що я шукав. Зауважте, що якщо ви не суперпользователь, це повинні бути два ваші процеси (а не бути налаштованими / налаштованими ...) (зрозуміло)
Stéphane Chazelas

@ StéphaneChazelas Рівно. Якщо з якихось причин підтримка CPIU не була побудована у вашому ядрі, і ви не хочете її відновлювати, то, гадаю, ви завжди можете написати модуль ядра, який експортує деякий інтерфейс користувача, що дозволяє вам порівнювати struct file *покажчики.
minmaxavg

3

Що ви хочете порівняти - це struct fileпокажчики, на які вказують дескриптори файлів. (Всередині ядра - одна task_structструктура даних для кожного потоку. Вона містить вказівник на іншу структуру, яку називають files_struct. І ця структура містить масив покажчиків, кожен на а struct file. Це те, struct fileщо містить зсув пошуку, відкриті прапори та кілька інших полів.)

Я не знаю жодного видимого для користувача способу побачити покажчики, files_structкрім використання деяких нав'язливих інструментів. Наприклад, SystemTap може бути дано PID, і він може знайти відповідний task_structта слідувати вказівникам. Якщо ви шукаєте пасивне, я вважаю, що це саме так. Dell давно випустив інструмент під назвою KME (редактор пам’яті ядра), який дав інтерфейс, подібний до електронних таблиць, для живої пам’яті ядра, і він міг робити все, що завгодно, але він ніколи не переносився на 64-розрядні. (Я спробував, і ніколи не вийшов, щоб він повністю працював, і не знав, чому.)

Однією з причин, яку ви не вважаєте lsofкорисною, є те, що він також не бачить цих покажчиків (але подивіться на +fваріант для не-Linux систем). Теоретично можна порівняти всі поля в struct fileі подумати, що дві структури однакові, але вони все ще можуть бути з окремих open(2)дзвінків.

Погляньте на ідеї сценарію pfiles SystemTap. Якщо ви змінили його для друку адреси адреси struct file, у вас є рішення. Ви також можете перевірити open_file_by_pid.stp, оскільки в ньому є функція, яка ходить files_struct, тобто. таблиця дескрипторів файлів, дивлячись на struct fileоб'єкти ...

Чи можу я запитати, що ви намагаєтеся досягти?


Я мушу визнати, що не можу згадати той самий випадок, коли мені це було потрібно. Якась налагоджувальна чи криміналістична задача без сумніву.
Стефан Шазелас

Я з нетерпінням чекаю коду
системного

Перш ніж я опублікував це запитання, я ознайомився з підходом до системи / / proc / kcore. Важкою частиною було отримати інформацію для кожного фд кожного завдання . Найперспективніший підхід, який я знайшов, - це підключення до функцій, які генерують вміст каталогу / proc / * / task / fd, але єдиними працездатними речами, які я міг би придумати, було причеплення до конкретних номерів рядків у вихідному файлі, так що не переноситься з однієї версії ядра в іншу. Ви не можете реально переглядати список завдань у systemtap. Можливо, через / proc / kcore, але занадто багато зусиль і, ймовірно, ненадійні.
Стефан Шазелас

Дякуємо за найкращу відповідь досі. Я подивлюся на ваші покажчики.
Стефан Шазелас

Впевнені, що зможете! Налаштуйте probe beginблок і дозвольте йому використовувати for_each_processмакрос в блоці коду С, вбудованого в сценарій (для вбудовування коду C вам потрібно буде використовувати режим "гуру" SystemTap). Насправді, щоб зробити це цікавим (!), Ви можете використовувати один із асоціативних масивів SystemTap; використовувати files_structадресу як ключ, а список PID / TID - як значення. Тепер у вас є список кожного відкритого файлу та завдань, якими вони діляться (ними можна ділитися між батьком / дочіркою). Відповідь ще раз, якщо ви хочете обговорити SystemTap.
Ажрей

0

Ось специфічне рішення для Linux: / proc / self / fd - це каталог символьних посилань для відкритих файлових ручок у поточному процесі. Ви можете просто порівняти значення посилань. Це стає складнішим під час використання дочірнього процесу, оскільки дитина матиме інше / proc / self, оскільки це символьне посилання, що залежить від піда. Ви можете вирішити цю проблему, скориставшись / proc / $$ / fd, де $$ - бажаний під.


Спасибі. Але це не те, про що я прошу. У Linux lsof дійсно використовує / proc / pid / fd для отримання шляхів для кожного дескриптора файлів та / proc / pid / fdinfo для прапорів. Але те, що я хочу, - це те, що два файли в одному і тому ж файлі вказують на однаковий опис відкритого файлу чи два дескриптори файлу були відкриті незалежно.
Стефан Шазелас

Ок, після того, як ви знайшли пари дескрипторів файлів, відкритих для одного і того ж імені файлу, скажіть про обидва та порівняйте результати, якщо вони відрізняються, вони є окремими. Якщо вони однакові, шукайте один дескриптор файлу та повторіть, Якщо вони все ще відповідають, вони однакові.
hildred

Ну, це більш нав'язливий варіант евристичного підходу, про який я згадую у питанні, і який працює лише для звичайних файлів (не розетки, пристрої (як термінали), труби ...).
Стефан Шазелас
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.