Відповіді:
Щоразу, коли ви читаєте файл під /proc
, він викликає якийсь код у ядрі, який обчислює текст для читання як вміст файлу. Той факт, що вміст генерується на льоту, пояснює, чому майже всі файли повідомляють про свій час як зараз, а їх розмір повідомляється як 0 - тут слід прочитати 0 як "не знаю". На відміну від звичайних файлових систем, встановлена на них файлова система /proc
, яка називається procfs , не завантажує дані з диска або іншого носія інформації (наприклад, FAT, ext2, zfs, ...) або через мережу (наприклад, NFS, Samba,…) і не викликає код користувача (на відміну від FUSE ).
Procfs присутній у більшості не-BSD-одиниць. Він розпочав своє життя в Bell Labs AT&T у 8-му виданні UNIX як спосіб повідомляти інформацію про процеси (і ps
часто є досить-таки принтером для інформації, яку читають /proc
). Більшість реалізацій procfs мають файл або каталог, викликаний /proc/123
для повідомлення інформації про процес з PID 123. Linux розширює файлову систему proc на багато інших записів, які повідомляють про стан системи, включаючи ваш приклад /proc/cpuinfo
.
Раніше Linux /proc
придбавав різні файли, які надають інформацію про драйвери, але це використання зараз застаріло на користь /sys
, і /proc
зараз розвивається повільно. Записи подобаються /proc/bus
та /proc/fs/ext4
залишаються там, де вони є для зворотної сумісності, але нові аналогічні інтерфейси створюються під /sys
. У цій відповіді я зупинюсь на Linux.
Ваші перші та другі точки входу для документації про /proc
Linux є:
proc(5)
сторінка людей ;/proc
Файлова система в документації до ядру .Третя точка входу, коли документація не охоплює її, читає джерело . Ви можете завантажити джерело на свою машину, але це величезна програма, і LXR , перехресне посилання на Linux, є великою підмогою. (Є багато варіантів LXR; той, на якому працює, lxr.linux.no
є найкращим на сьогоднішній день, але, на жаль, сайт часто знижений.) Потрібно небагато знань C, але вам не потрібно бути програмістом, щоб відстежувати загадкове значення .
Основна обробка /proc
записів знаходиться в fs/proc
каталозі. Будь-який драйвер може зареєструвати записи /proc
(хоча, як зазначено вище, це тепер застаріло на користь /sys
), тому якщо ви не знайдете те, що шукаєте fs/proc
, шукайте всюди інше. Драйвери виклику функцій, оголошених у include/linux/proc_fs.h
. Версії ядра до 3.9 містять функції create_proc_entry
та деякі обгортки (особливо create_proc_read_entry
), а версії ядра 3.10 і вище забезпечують лише proc_create
та proc_create_data
(та ще декілька).
Беручи в /proc/cpuinfo
якості прикладу, пошук "cpuinfo"
приводить вас до виклику proc_create("cpuinfo, …")
в fs/proc/cpuinfo.c
. Ви можете бачити, що цей код є дуже великим кодовим шаблоном: оскільки більшість файлів /proc
лише скидають деякі текстові дані, для цього є допоміжні функції. Існує лише seq_operations
структура, і справжнє м'ясо знаходиться в cpuinfo_op
структурі даних, яка залежить від архітектури, зазвичай визначається в arch/<architecture>/kernel/setup.c
(або іноді в іншому файлі). Беручи до прикладу x86, нас ведуть до цього arch/x86/kernel/cpu/proc.c
. Там основна функціяshow_cpuinfo
, який виводить потрібний вміст файлу; інша частина інфраструктури є для того, щоб подавати дані в процес зчитування зі швидкістю, яку він вимагає. Ви можете бачити дані, що збираються на льоту, з даних різних змінних в ядрі, включаючи кілька чисел, обчислених на льоту, таких як частота процесора .
Значну частину /proc
становить інформація про процес у /proc/<PID>
. Ці записи реєструються в fs/proc/base.c
, у tgid_base_stuff
масиві ; деякі зареєстровані тут функції визначені в інших файлах. Давайте розглянемо кілька прикладів створення цих записів:
cmdline
генерується proc_pid_cmdline
у тому самому файлі. Він знаходить ці дані в процесі та роздруковує їх.clear_refs
На відміну від записів, які ми бачили до цього часу, є записаними, але не читабельними. Тому proc_clear_refs_operations
структури визначають clear_refs_write
функцію, але не функцію зчитування.cwd
це символічне посилання (злегка магічне), оголошене компанією proc_cwd_link
, яке шукає поточний каталог процесу та повертає його як вміст посилання.fd
є підкаталогом. Операції над самим каталогом визначені в proc_fd_operations
структурі даних (вони є котлетною платою, за винятком функції, яка перераховує записи proc_readfd
, яка перераховує відкриті файли процесу), тоді як операції над записами знаходяться в `proc_fd_inode_operations .Інша важлива область /proc
є /proc/sys
, що є прямим інтерфейсом до sysctl
. Читання з запису в цій ієрархії повертає значення відповідного значення sysctl, а запис задає значення sysctl. Точки входу для sysctl знаходяться в fs/proc/proc_sysctl.c
. У Sysctls є власна система реєстрації з register_sysctl
друзями.
Коли ви намагаєтесь зрозуміти, яка магія відбувається за лаштунками, ваш найкращий друг strace
. Навчитися керувати цим інструментом - одна з найкращих речей, яку ти можеш зробити, щоб краще оцінити те, що шалена магія відбувається за лаштунками.
$ strace -s 200 -m strace.log cat /proc/cpuinfo
...
read(3, "processor\t: 0\nvendor_id\t: GenuineIntel\ncpu family\t: 6\nmodel\t\t: 37\nmodel name\t: Intel(R) Core(TM) i5 CPU M 560 @ 2.67GHz\nstepping\t: 5\nmicrocode\t: 0x4\ncpu MHz\t\t: 1199.000\ncache size\t: 3072 KB\nphy"..., 65536) = 3464
write(1, "processor\t: 0\nvendor_id\t: GenuineIntel\ncpu family\t: 6\nmodel\t\t: 37\nmodel name\t: Intel(R) Core(TM) i5 CPU M 560 @ 2.67GHz\nstepping\t: 5\nmicrocode\t: 0x4\ncpu MHz\t\t: 1199.000\ncache size\t: 3072 KB\nphy"..., 3464) = 3464
read(3, "", 65536) = 0
close(3) = 0
...
З наведеного вище висновку видно, що /proc/cpuinfo
це просто звичайний файл, або, принаймні, здається, що це один. Тож давайте копаємо глибше.
Дивлячись на сам файл, здавалося б, це "просто файл".
$ ls -l /proc/cpuinfo
-r--r--r--. 1 root root 0 Mar 26 22:45 /proc/cpuinfo
Але придивіться уважніше. Ми отримуємо перший натяк на те, що його особливий, зауважте, розмір файлу - 0 байт.
№2 - зі стат ..Якщо ми зараз розглянемо файл, використовуючи, stat
ми можемо отримати наступний натяк на те, що є щось особливе /proc/cpuinfo
.
$ stat /proc/cpuinfo
File: ‘/proc/cpuinfo’
Size: 0 Blocks: 0 IO Block: 1024 regular empty file
Device: 3h/3dInode: 4026532023 Links: 1
Access: (0444/-r--r--r--) Uid: ( 0/ root) Gid: ( 0/ root)
Context: system_u:object_r:proc_t:s0
Access: 2014-03-26 22:46:18.390753719 -0400
Modify: 2014-03-26 22:46:18.390753719 -0400
Change: 2014-03-26 22:46:18.390753719 -0400
Birth: -
запуск №2
$ stat /proc/cpuinfo
File: ‘/proc/cpuinfo’
Size: 0 Blocks: 0 IO Block: 1024 regular empty file
Device: 3h/3dInode: 4026532023 Links: 1
Access: (0444/-r--r--r--) Uid: ( 0/ root) Gid: ( 0/ root)
Context: system_u:object_r:proc_t:s0
Access: 2014-03-26 22:46:19.945753704 -0400
Modify: 2014-03-26 22:46:19.945753704 -0400
Change: 2014-03-26 22:46:19.945753704 -0400
Birth: -
Помічаєте час доступу, зміни та зміни часу? Вони постійно змінюються для кожного доступу. Це дуже незвично, що всі 3 змінилися б так. Якщо відредаговані атрибути часової позначки файлу, як правило, не змінюються.
№3 - з файлом ..Ще одна підказка, що цей файл - це не що інше, як звичайний файл:
$ file /proc/cpuinfo
/proc/cpuinfo: empty
Якби це був якийсь прояв названої труби, він показав би подібний до одного з цих файлів:
$ ls -l /dev/initctl /dev/zero
prw-------. 1 root root 0 Mar 26 20:09 /dev/initctl
crw-rw-rw-. 1 root root 1, 5 Mar 27 00:39 /dev/zero
$ file /dev/initctl /dev/zero
/dev/initctl: fifo (named pipe)
/dev/zero: character special
Якщо ми торкнемось, то emptyfile
, /proc/cpuinfo
схоже, більше схожий на файл, а на трубу:
$ touch emptyfile
$ ls -l emptyfile
-rw-rw-r--. 1 saml saml 0 Mar 27 07:40 emptyfile
$ file emptyfile
emptyfile: empty
№4 - із кріпленням ..
Тому в цей момент нам потрібно зробити крок назад і трохи зменшити масштаб. Ми дивимося на певний файл, але, можливо, ми повинні дивитись на файлову систему, на якій знаходиться цей файл. І для цього ми можемо використовувати mount
команду.
$ mount | grep " /proc "
proc on /proc type proc (rw,nosuid,nodev,noexec,relatime)
Гаразд, тому тип файлової системи має тип proc
. Отже /proc
, це інший тип файлової системи, і це наш натяк на те, що файли під цим /proc
є спеціальними. Вони не є лише вашим запуском файлів млина. Тож давайте дізнаємось більше інформації про те, що робить proc
файлову систему особливою.
Переглядаючи mount
сторінку чоловіка:
Файлова система proc не пов'язана зі спеціальним пристроєм, і при її монтажі замість специфікації пристрою може використовуватися довільне ключове слово, наприклад proc. (Звичайний вибір не менш щасливий: повідомлення про помилку `не зайнято 'з umount може бути заплутаним.)
А якщо ми подивимося на proc
сторінку чоловіка:
Файлова система proc - це псевдофайлова система, яка використовується як інтерфейс до структур даних ядра. Він зазвичай монтується в / proc. Більшість є лише для читання, але деякі файли дозволяють змінювати змінні ядра.
Трохи далі на цій самій сторінці чоловіка:
/ proc / cpuinfo
Це колекція елементів, залежних від процесора та системної архітектури, для кожної підтримуваної архітектури є інший список. Дві загальні записи - це процесор, який дає номер CPU та bogomips; системна константа, яка обчислюється під час ініціалізації ядра. Машини SMP мають інформацію для кожного процесора. Команда lscpu (1) збирає свою інформацію з цього файлу.
Внизу сторінки man є посилання на документ ядра, який ви можете знайти тут, з назвою: THE / proc FILESYSTEM . Цитуючи цей документ:
Файлова система proc діє як інтерфейс до внутрішніх структур даних у ядрі. Він може використовуватися для отримання інформації про систему та для зміни певних параметрів ядра під час виконання (sysctl).
То що ми тут дізналися? Зважаючи на те, що /proc
це називається псевдофайловою системою, а також "інтерфейсом до внутрішніх структур даних", можливо, можна припустити, що елементи в ній не є фактичними файлами, а скоріше просто проявами, схожими на файли, але насправді це не так.
Я закінчу цю цитату, яка, мабуть, була в попередній версії man 5 proc
приблизно з 2004 року, але з будь-якої причини більше не включається. ПРИМІТКА. Я не впевнений, чому його видалено, оскільки він дуже добре описує, що /proc
таке:
Каталог / proc в системах GNU / Linux забезпечує файлову систему, як інтерфейс до ядра. Це дозволяє програмам та користувачам отримувати інформацію з ядра та встановлювати значення в ядрі, використовуючи звичайні операції вводу / виводу файлової системи.
Файлову систему proc іноді називають псевдофайловою системою інформації про процес. Він не містить `` реальних '' файлів, а швидше системну інформацію (наприклад, системну пам'ять, встановлені пристрої, конфігурацію обладнання тощо). З цієї причини його можна розглядати як центр контролю та інформації для ядра. Насправді досить багато системних утиліт - це просто дзвінки до файлів у цьому каталозі. Наприклад, команда lsmod, яка перелічує модулі, завантажені ядром, в основному є такою ж, як 'cat / proc / module', тоді як lspci, який перераховує пристрої, підключені до шини PCI системи, такий же як 'cat / proc / pci '. Змінюючи файли, розташовані в цьому каталозі, ви можете змінювати параметри ядра під час роботи системи.
Джерело: Файлова система Pro псевдо
strace -o catcpuproc.txt cat /proc/cpuinfo
Відповідь, надана @slm, є дуже вичерпною, але я думаю, що більш просте пояснення може бути наслідком зміни точки зору.
У щоденному використанні ми можемо розглядати файли як фізичні речі, тобто. шматки даних, що зберігаються на якомусь пристрої. Це робить файли на зразок / proc / cpuinfo дуже таємничими та заплутаними. Однак все має сенс, якщо ми розглянемо файли як інтерфейс ; спосіб надсилання даних в якусь програму і з неї.
Програми, які таким чином надсилають та отримують дані, - це файлові системи або драйвери (залежно від того, як ви визначаєте ці терміни, це може бути занадто широким або занадто вузьким визначенням). Важливим моментом є те, що деякі з цих програм використовують апаратний пристрій для зберігання та отримання даних, що надсилаються через цей інтерфейс; але не всі.
Деякі приклади файлових систем, які не використовують пристрій збереження даних (принаймні безпосередньо):
ОС Plan9 ( http://en.wikipedia.org/wiki/Plan_9_from_Bell_Labs ) є крайнім прикладом використання файлів як загального інтерфейсу програмування.