Hlavní navigace

Co před námi tají /proc (1)

22. 6. 2001
Doba čtení: 7 minut

Sdílet

Jedna ze základních vlastností operačního systému Unixového typu je, že před vámi nic neskrývá. Druhou by mohlo být, že vše lze přizpůsobit a nastavit k obrazu svému. K čtení i nastavování hodnot jádra systému se dnes nejčastěji používá souborový systém /proc.

Na základě vlastní potřeby a vyburcován dopisy v linux@linux.cz jsem se rozhodl vytvořit malý seriál o tomto souborovém systému. Pro začátek bych se rád ponořil do obsahu jeho mnoha podadresářů a souborů a pro sebe i pro vás se pokusil zjistit, co všechna ta čísla vlastně znamenají. Možná to bude trochu připomínat detektivní pátrání, ale věřím, že s pomocí Webu, zdrojového kódu Linuxu a grepu se mi podaří shromáždit spoustu zajímavých informací.

Pokud bude zájem, mohl bych též připojit jeden díl o programování modulů pro jádro, které vytváří položky v adresáři /proc. Možná by neškodilo i malé zamyšlení nad přenositelností programů využívajících tyto informace a knihovny typu libproc.

Takže vzhůru do pátrání. Nejprve malý úvod pro ty, kteří nemají úplně jasno v tom, co to ten /proc je. Jedná se o virtuální souborový systém připojovaný do adresáře /proc. K připojení se použije klasický příkaz mount, například takto:

mount -t proc proc /proc

Na první pohled je podivné, co je to za speciální soubor v druhém parametru. Odpověď je (překvapivě) zcela prostá. Žádné zařízení proc neexistuje a v zápise je použito pouze pro zachování stejné syntaxe s ostatními druhy souborových systémů. Vše, co je třeba, pozná mount podle typu. Ten je v tomto případě proc. Pokud jste se někdy vrtali v jádře, víte, že operace nad souborovými systémy (jakož i nad spoustou jiných věcí) jsou realizovány přes popisnou strukturu daného zařízení. Ta obsahuje ukazatele na funkce pro všechny možné operace. Pokud tedy například provedeme otevření souboru v systému, kde je Ext2, použije se ukazatel na funkci „open“, který je pro systém Ext2 nastaven na funkci řekněme „ext2_open“. Ta schroustá data z disku (respektive z cache) a vrátí je uživateli. Pokud je ale daným systémem souborů /proc, má nastavenu funkci, která data vygeneruje z informací v jádře. A uživatel nic nepozná, pracuje se soubory úplně stejně. Zápis probíhá obdobně, až na to, že zapisovaná data se nikam neukládají, ale použijí se k nastavení parametrů jádra.

Teď už máme představu, jak souborový systém proc funguje, takže vzhůru na prozkoumávání jeho obsahu. Ten se samozřejmě bude lišit v závislosti na verzi jádra operačního systému, ale hlavně dle toho, co všechno jsme do jádra zakompilovali a/nebo jaké jsou v daném okamžiku nahrány moduly. Určitý základ ale bude stejný, zbytek bude vycházet z mého aktuálního nastavení. Pokud Vám tedy bude nějaká oblast chybět, řekněte si. Na mém počítači je nyní poslední stabilní jádro 2.4.5 (ano, jsem sebevrah :).

Nejprve se podíváme na výpis adresáře /proc:

924/     devices      interrupts  loadavg  net/        sys/
946/     dma          iomem       locks    partitions  sysvipc/
968/     driver/      ioports     meminfo  pci         tty/
apm      execdomains  irq/        misc     self@       uptime
bus/     filesystems  kcore       modules  slabinfo    version
cmdline  fs/          kmsg        mounts   stat
cpuinfo  ide/         ksyms       mtrr     swaps

Tento výpis je „poněkud“ zkrácen, adresářů pojmenovaných číslem je ve skutečnosti mnohem víc. Nyní se pojďme podívat na jednotlivé položky výpisu. V tomto dílu si jako předkrm před dalšími zajímavostmi, na jejichž pečlivější nastudování budu potřebovat trochu času, podíváme na informace o procesech. To jsou právě ony adresáře pojmenované číslem. Jak jistě uhodnete, číslo odpovídá PID procesu.

Příkladem nám bude adresář informací o procesu bash. Tento proces má PID podle následujícího výpisu programu ps -e rovno 300:

  PID TTY          TIME CMD
  ...
  300 tty1     00:00:00 bash
  ...

Vybrali jsme proces, který jsme sami vytvořili, abychom měli patřičná přístupová práva ke čtení jeho informací. Obsah adresáře /proc/300 je potom následující:

-r--r--r--   1 sioux  users   0 Jun 16 13:07 cmdline
lrwxrwxrwx   1 sioux  users   0 Jun 16 13:07 cwd -> /home/sioux
-r--------   1 sioux  users   0 Jun 16 13:07 environ
lrwxrwxrwx   1 sioux  users   0 Jun 16 13:07 exe -> /bin/bash
dr-x------   2 sioux  users   0 Jun 16 13:07 fd/
-r--r--r--   1 sioux  users   0 Jun 16 13:07 maps
-rw-------   1 sioux  users   0 Jun 16 13:07 mem
lrwxrwxrwx   1 sioux  users   0 Jun 16 13:07 root -> /
-r--r--r--   1 sioux  users   0 Jun 16 13:07 stat
-r--r--r--   1 sioux  users   0 Jun 16 13:07 statm
-r--r--r--   1 sioux  users   0 Jun 16 13:07 status

Poprvé si to ještě trochu rozpitváme, příště už se budeme zajímat především o obsah souborů. Nejprve práva. Většina je pouze pro čtení, mem, což je obraz paměti, je i zapisovatelný (ale pouze pro majitele). Nic překvapujícího, tedy dále. Vlastník souborů je určen podle aktuálního EUID a EGID procesu. Pokud tedy proces bude po dobu svého běhu nějak měnit efektivní UID nebo GID, změna se zde projeví. Velikost je u většiny položek při výpisu adresářů nulová, neboť skutečný obsah je generován až při samotném přístupu k souboru a může se tedy měnit. Časy vytvoření (ale i přístupu atd.) jsou nastaveny na dobu vygenerování záznamů.

A teď už konečně jednotlivé položky:

cmdline
v našem případě je obsahem „-bash“. Jedná se o stejné řetězce, jaké vidí aplikace v poli argv[]. Obsahuje tedy název aplikace a případné parametry.
cwd
symbolický link na aktuální pracovní adresář.
environ
obsahuje seznam proměnných prostředí dostupných danému procesu. Jde o nulou ukončené řetězce:
HOME=/home/sioux\0SHELL=/bin/bash\0TERM=linux\0....
Na konci je pouze nula ukončující poslední řetězec a konec seznamu je nutno rozeznávat podle konce souboru.
exe
symbolický link na soubor, který obsahuje program pro daný proces. Zde je to: „/bin/bash“.
fd
Tento adresář obsahuje odkazy na použité deskriptory souborů. Jde o symbolické linky na soubory (pro příklad: „0 → /dev/tty1“).
maps
V jádrech řady 2.4 jsou diskové soubory jako spustitelné (binární) programy a knihovny připojovány do adresového prostoru procesu pomocí mapování příslušného souboru funkcí mmap(). Ta způsobí zobrazení obsahu souboru z disku do LAP (Logický Adresový Prostor) procesu a pokud je potom požadována stránka z této oblasti, natáhne se při ošetřování výjimky požadovaná stránka do fyzické paměti. Při uvolňování se tyto stránky (u souborů s kódem) prostě zahodí, protože je lze načíst znovu z disku. Tato položka v systému /proc obsahuje informace o takto mapovaných souborech. Každý řádek odpovídá jedné oblasti a obsahuje následující položky: rozsah použitých logických adres, práva pro danou oblast, offset v počtu stránek, hlavní a vedlejší číslo zařízení, ze kterého pochází soubor, inode příslušného souboru a nakonec jméno souboru. Pro nás je začátek souboru následující:
08048000-080c0000 r-xp 00000000 03:04 17053  /bin/bash
080c0000-080c6000 rw-p 00077000 03:04 17053  /bin/bash
080c6000-08100000 rwxp 00000000 00:00 0
40000000-40015000 r-xp 00000000 03:04 15669  /lib/ld-2.2.so
40015000-40016000 rw-p 00014000 03:04 15669  /lib/ld-2.2.so
....
Je vidět i díra v LAP, dále je patrné, že kód a statická data jsou mapována zvlášť kvůli přístupovým právům. Přístupové právo ‚p‘ značí „private“, opakem je ‚s‘ pro „shared“.
mem
Zpřístupňuje logický adresový prostor procesu. Bohužel se mi tento soubor nepodařilo přečíst. Při čtení to vždy hlásilo chybu:
se710.root /proc/277> cat ./mem
cat: ./mem: Tento proces neexistuje
Pokud zjistím, v čem byl problém, dodělám errata.
root
symbolický link na kořenový adresář pro daný proces. Většinou je to „/“, pouze pro chrootované programy je hodnota jiná.
stat
obsahuje informace o procesu. Stejné informace, ale v čitelnější podobě, přináší soubor status
statm
Informace o stavu paměti využívané procesem. Jednotlivé čísla mají následující význam: velikost programu, počet stránek celkem, počet sdílených stránek, počet stránek kódu, počet stránek dat a zásobníku, počet stránek knihoven, počet modifikovaných stránek. Všechny počty stránek se vztahují k aktuálnímu obsahu fyzické paměti pro daný proces. V našem případě je obsah:
"89 1 1 0 0 1 0"
status
Zde lze najít následující informace o procesu (a opět ukázka našeho procesu 300):
Name:   bash
State:  S (sleeping)
Pid:    300
PPid:   294
TracerPid:      0
Uid:    500     500     500     500
Gid:    100     100     100     100
FDSize: 256
Groups: 100
VmSize:     2432 kB
VmLck:         0 kB
VmRSS:         0 kB
VmData:      260 kB
VmStk:        24 kB
VmExe:       480 kB
VmLib:      1412 kB
SigPnd: 0000000000000000
SigBlk: 0000000000010000
SigIgn: 0000000000384004
SigCgt: 000000004b813efb
CapInh: 0000000000000000
CapPrm: 0000000000000000
CapEff: 0000000000000000
Položky jméno, stav, PID, PPID (Parent PID) jsou snad jasné. Jenom připomenu, že možné hodnoty stavu jsou: R(running), S(sleeping), D(disk sleep), Z(zombie), T(stoped), W(paging). Takže co ten zbytek.

TracerPID: dle zdrojového kódu jádra nastaven napevno na hodnotu ‚0‘.
Uid: pole obsahuje postupně UID, EUID, SUID, FSUID
Gid: pole obsahuje postupně GID, EGID, SGID, FSGID
FDSize: velikost tabulky deskriptorů souborů
Groups: seznam skupin do nichž proces patří
VmSize: Obsazený LAP
VmLck: Velikost uzamčené paměti (LAP i FAP)
VmRSS: Velikost přiděleného FAP (RAM)
VmData: Velikost datových stránek
VmStk: Velikost zásobníku
VmExe: Velikost kódu programu
VmLib: Velikost paměti pro kód knihoven
SigPnd: maska signálů doručených během blokování
SigBlk: aktuální maska blokovaných signálů
SigIgn: aktuální maska ignorovaných signálů
SigCgt: aktuální maska obsluhovaných signálů (aplikací)
CapInh,Prm,Eff: zděděné, nastavené a efektivní vlastnosti procesu. Obsluhuje některá (především bezpečnostní) nastavení procesu dle normy POSIX. Příkladem budiž CAP_CHOWN, což je příznak povolující nebo zakazující změnu vlastníka. (detaily – norma POSIX)

Tak a to je pro dnešek vše. Očekávám vaše připomínky, názory a komentáře v diskusi k článku. Ve výpisu adresáře /proc v tomto článku vidíte, co bude postupně obsahem dalších dílů.

Byl pro vás článek přínosný?