proc − 進程信息偽檔案系統
/proc 是一個偽檔案系統, 被用作核心數據結構的接口, 而不僅僅 是解釋說明 /dev/kmem. /proc裏的大多數檔案都是只讀的, 但也可 以通過寫一些檔案來改變核心變量.
下面對整個 /proc 目錄作一個大略的介紹.
[number]
在 /proc 目錄裏, 每個正在運行的進程都有一個以該進程 ID 命名的子目錄, 其下包括如下的目錄和偽檔案.
cmdline
該檔案保存了進程的完整命令行. 如果該進程已經 被交換出記憶體, 或者該進程已經僵死, 那麼就沒有 任何東西在該檔案裏, 這時候對該檔案的讀操作將返回零 個字符. 該檔案以空字符 null 而不是換行符作為結 束標誌.
cwd |
一個符號連接, 指向進程當前的工作目錄. 例如, 要找出進程 20 的 cwd, 你可以: |
cd /proc/20/cwd; /bin/pwd
請注意 pwd 命令通常是 shell 內置的, 在這樣的情況下可能 工作得不是很好.
environ
該檔案保存進程的環境變量, 各項之間以空字符分隔, 結尾也可能是一個空字符. 因此, 如果要輸出進程 1 的環境變量, 你應該:
(cat /proc/1/environ; echo) | tr ";\000"; ";\n";
(至於為什麼想要這麼做, 請參閱 lilo(8).)
exe |
也是一個符號連接, 指向被執行的二進制代碼. |
在 Linux 2.0 或者更早的版本下, 對 exe 特殊檔案的 readlink(2) 返回一個如下格式的字符串:
[設備號]:節點號
舉個例子, [0301]:1502 就是某設備的 1502 節點, 該設備的主設備號為 03 (如 IDE, MFM 等驅動器), 從設備號為 01 (第一個驅動器的第一分區).
而在 Linux 2.2 下, readlink(2) 則給出命令的實際路徑名.
另外, 該符號連接也可以正常析引用(試圖打開 exe 檔案實際上將打開一個可執行檔案). 你甚至可以鍵入 /proc/[number]/exe 來運行 [number] 進程的副本.
帶 -inum 選項的 find(1) 命令可以定位該檔案.
fd |
進程所打開的每個檔案都有一個符號連接在該子目 錄裏, 以檔案描述符命名, 這個名字實際上是指向 真正的檔案的符號連接,(和 exe 記錄一樣). 例如, 0 是標準輸入, 1 是標準輸出, 2 是標準錯誤, 等等. |
程式有時可能想要讀取一個檔案卻不想要標準輸入, 或者想寫到一個檔案卻不想將輸出送到標準輸出去, 那麼就可以很有效地用如下的辦法騙過(假定 -i 是輸入 檔案的標誌, 而 -o 是輸出檔案的標誌):
foobar -i /proc/self/fd/0 -o /proc/self/fd/1 ...
這樣就是一個能運轉的過濾器. 請注意該方法不能 用來在檔案裏搜索, 這是因為 fd 目錄裏的檔案是 不可搜索的.
在 UNIX 類的系統下, /proc/self/fd/N 基本上就與 /dev/fd/N 相同. 實際上, 大多數的 Linux MAKEDEV 稿本都將 /dev/fd 符號連接到 [..]/proc/self/fd 上.
maps |
該檔案包含當前的映像記憶體區及他們的訪問許可. |
格式如下:
address perms offset dev inode 00000000-0002f000 r-x-- 00000400 03:03 1401 0002f000-00032000 rwx-p 0002f400 03:03 1401 00032000-0005b000 rwx-p 00000000 00:00 0 60000000-60098000 rwx-p 00000400 03:03 215 60098000-600c7000 rwx-p 00000000 00:00 0 bfffa000-c0000000 rwx-p 00000000 00:00 0
address 是進程所佔據的地址空間, perms 是權限集:
r = read
w = write
x = execute
s = shared
p = private (copy on write)
offset 是檔案或者別的什麼的偏移量, dev 是設備號(主設 備號:從設備號), 而 inode 則是設備的節點號. 0 表明沒有 節點與記憶體相對應, 就像 bss 的情形.
在 Linux 2.2 下還增加了一個域給可用的路徑名.
mem |
該檔案並不是 mem (1:1) 設備, 儘管它們有相同的設備號. /dev/mem 設備是做任何地址轉換之前的物理記憶體, 而這裏的 mem 檔案是訪問它的進程的記憶體.目前這個 mem 還不能 mmap(2) (記憶體映射)出去,而且可能一直要等到核心中增加了一個通用的 mmap(2) 以後才能實現. (也許在你讀本手冊頁時這一切已經發生了) |
||
mmap |
mmap(2) 做的 maps 映射目錄,是和 exe, fd/* 等類似的符號連接. 請注意 maps 包含了比 /proc/*/mmap 更多的信息, 所以應該廢棄 mmap. |
";0"; 通常指 libc.so.4.
在 linux 核心 1.1.40 裏, /proc/*/mmap 被取消了. (現在是 真的 廢棄不用了!)
root |
依靠系統調用 chroot(2), unix 和 linux 可以讓 每個進程有各自的檔案系統根目錄. 由 chroot(2) 系統調用設置. 根指向檔案系統的根,性質就像 exe, fd/* 等一樣. |
||
stat |
進程狀態信息, 被命令 ps(1) 使用. |
現將該檔案裏各域, 以及他們的 scanf(3) 格式說明符, 按順序分述如下:
pid %d |
進程標識. |
comm %s
可執行檔案的檔名, 包括路徑. 該檔案是否可 見取決於該檔案是否已被交換出記憶體.
state %c
";RSDZT"; 中的一個, R 是正在運行, S 是 在可中斷的就緒態中睡眠, D 是在不可中 斷的等待或交換態中睡眠, Z 是僵死, T 是被跟蹤或被停止(由於收到信號).
ppid %d
父進程 PID.
pgrp %d
進程的進程組 ID.
session %d
進程的會話 ID.
tty %d |
進程所使用終端. |
tpgid %d
當前擁有該進程所連接終端的進程所在的進程 組 ID.
flags %u
進程標誌. 目前每個標誌都設了數學位, 所以輸出裏就不包括該位. crt0.s 檢查數學仿真 這可能是一個臭蟲, 因為不是每個進 程都是用 c 編譯的程式. 數學位應該是十 進制的 4, 而跟蹤位應該是十進制的 10.
minflt %u
進程所導致的小錯誤(minor faults)數目, 這樣的 小錯誤(minor faults)不需要從磁碟重新載入一個 記憶體頁.
cminflt %u
進程及其子進程所導致的小錯誤(minor faults)數目.
majflt %u
進程所導致的大錯誤(major faults)數目, 這樣的 大錯誤(major faults)需要重新載入記憶體頁.
cmajflt %u
進程及其子進程所導致的大錯誤(major faults)數目.
utime %d
進程被調度進使用者態的時間(以 jiffy 為單 位, 1 jiffy=1/100 秒,另外不同硬體體系略有不同).
stime %d
進程被調度進核心態的時間, 以 jiffy 為 單位.
cutime %d
進程及其子進程被調度進使用者態的時間, 以 jiffy 為單位.
cstime %d
進程及其子進程被調度進核心態的時間, 以 jiffy 為單位.
counter %d
如果進程不是當前正在運行的進程, 就是 進程在下個時間片當前可以擁有的最大時 間, 以 jiffy 為單位. 如果進程是當前正 在運行的進程, 就是當前時間片中所剩下 jiffy 數目.
priority %d
標準優先數只再加上 15, 在核心裏該值總 是正的.
timeout %u
當前至進程的下一次間歇時間, 以 jiffy 為單位.
itrealvalue %u
由於計時間隔導致的下一個 SIGALRM 發送進程的時延,以 jiffy 為單位.
starttime %d
進程自系統啟動以來的開始時間, 以 jiffy 為單位.
vsize %u
虛擬記憶體大小.
rss %u |
Resident Set Size(駐留大小): 進程所佔用的真實內 存大小, 以頁為單位, 為便於管理而減去 了 3. rss 只包括正文, 數據以及堆棧的空間, 但不包括尚未要求裝入記憶體的或已被交換出去的. |
rlim %u
當前進程的 rss 限制, 以字節為單位, 通 常為 2,147,483,647.
startcode %u
正文部分地址下限.
endcode %u
正文部分地址上限.
startstack %u
堆棧開始地址.
kstkesp %u
esp(32 位堆棧指針) 的當前值, 與在進程 的核心堆棧頁得到的一致.
kstkeip %u
EIP(32 位指令指針)的當前值.
signal %d
待處理信號的 bitmap(通常為 0).
blocked %d
被阻塞信號的 bitmap(對 shell 通常是 0, 2).
sigignore %d
被忽略信號的 bitmap.
sigcatch %d
被俘獲信號的 bitmap.
wchan %u
進程在其中等待的通道, 實際是一個系統 調用的地址. 如果你需要文字格式的, 也 可以在名字列表中找到. (如果有最新版本的 /etc/psdatabase, 你 可以在 ps -l 的結果中的 WCHAN 域看到)
cpuinfo
保存了CPU 以及體系架構依賴條目的列表. 對於不同的系 統架構有不同的列表, 共有的兩項是 cpu 和 BogoMIPS, cpu 可能是當前在用的 CPU, 而 BogoMIPS 則是核心初始化時計算出 的一個系統常數.
devices
主設備號及設備組的列表, 文字格式. MAKEDEV 稿本使用 該檔案來維持核心的一致性.
dma |
一個列表, 指出正在使用的ISA DMA (直接記憶體訪問)通道. |
filesystems
以文字格式列出了被編譯進核心的檔案系統. 當沒有給 mount(1) 指明哪個檔案系統的時候, mount(1) 就依靠該檔案遍歷不同的檔案系統.
interrupts
該檔案以 ASCII 格式記錄了(至少是在 i386 體系上的)每次 IRQ 的中斷數目.
ioports
該檔案列出了當前在用的已注冊 I/O 端口范圍.
kcore |
該偽檔案以 core 檔案格式給出了系統的物理記憶體映像, 再 利用未卸載的核心 (/usr/src/linux/tools/zSystem), 我 們就可以用 GDB 查探當前核心的任意數據結構. |
該檔案的總長度是物理記憶體 (RAM) 的大小再加上 4KB.
kmsg |
可以用該檔案取代系統調用 syslog(2) 來記錄核心信息. 但是讀該檔案需要超級使用者權限, 並且一次只能有一個進 程可以讀該檔案, 因而如果一個使用了 syslog(2) 系統調用功能來記錄核心信息的系統日誌進程正在運行的話, 別的進程就不能再去讀該偽檔案了. |
該檔案的內容可以用 dmesg(8) 來察看.
ksyms |
該檔案保存了核心輸出的符號定義, modules(X) 使用該檔案 動態地連接和捆綁可裝載的模塊. |
loadavg
平均負載數給出了在過去的 1, 5, 15 分鐘裏在運行隊列裏 的任務數, 與 uptime(1) 等命令的結果相同.
locks |
這個檔案顯示當前檔案鎖. |
||
malloc |
只有在編譯時定義了 CONFIGDEBUGMALLOC 才會有該檔案. |
meminfo
free(1) 利用該檔案來給出系統總的空閒記憶體和已用記憶體 (包括物理記憶體和交換記憶體), 以及核心所使用的共享記憶體 和緩沖區.
該檔案與 free(1) 格式相同, 但是以字節為單位而不是 KB.
modules
列出了系統已載入的模塊, 文字格式.
net |
該子目錄包括多個 ASCII 格式的網路偽檔案, 描述了網路 層的部分情況. 可以用 cat 來察看這些檔案, 但標準的 netstat(8) 命令組更清晰地給出了這些檔案的信息. |
arp
該檔案以 ASCII 格式保存了核心 ARP 表, 用於地址解析, 包括靜態和動態 arp 數據. 檔案格式如下: |
IP address HW type Flags HW address 10.11.100.129 0x1 0x6 00:20:8A:00:0C:5A 10.11.100.5 0x1 0x2 00:C0:EA:00:00:4E 44.131.10.6 0x3 0x2 GW4PTS
其中 ’IP address’ 是機器的 IPv4 地址; ’HW type’ 是地址的硬 件類型, 遵循 RFC 826; flags 是 ARP 結構的內部標誌, 在 /usr/include/linux/if_arp.h 中定義; ’HW address’ 是該 IP 地址的物理層映射(如果知道的話).
dev |
該偽檔案包含網路設備狀態信息, 給出了發送和收 到的包的數目, 錯誤和沖突的數目, 以及別的一些 基本統計數據. ifconfig(8) 利用了該檔案來報 告網路設備狀態. 檔案格式如下: |
Inter-| Receive | Transmit face |packets errs drop fifo frame|packets errs drop fifo colls carrier lo: 0 0 0 0 0 2353 0 0 0 0 0 eth0: 644324 1 0 0 1 563770 0 0 0 581 0
ipx |
無信息. |
ipx_route
無信息.
rarp |
該檔案具有和 arp 同樣的格式, 包含當前的逆向 地址映射數據. rarp(8) 利用這些數據來作逆向 地址查詢服務. 只有將 RARP 配置進核心, 該檔案才 存在. |
||
raw |
該檔案保存了 RAW 套接字表, 大部分信息除用於調試以外沒有什麼用. ‘sl’ 指出了套接字的核心散列槽號; ’local address’ 包括本地地址和協議號對; "St" 是套接字的內部狀態; tx_queue 和 rx_queue 是核心存儲器使用意義上的輸入輸 出數據隊列; RAW 沒有使用"tr", "tm->when" 和 "rexmits"; uid 是套接字創建者的有效 uid. |
||
route |
沒有信息, 但是看上去類似於 route(8) |
||
snmp |
該檔案以 ASCII 格式保存了 IP, ICMP, TCP 以及 UDP 管理所需的數據信息, 基於 snmp 協議. TCP mib (TCP 管理數據庫)尚未完善, 可能在 1.2.0 核心能夠 完成. |
||
tcp |
該檔案保存了 TCP 套接字表, 大部分信息除用於調試以外沒有什麼用. "sl" 指出了套接字的核心散列槽號; "local address" 包括本地地址和端口號; "remote address" 包括遠地 地址和端口號(如果有連接的話); ’St’ 是套接字的內 部狀態; ’tx_queue’ 和 ’rx_queue’ 是核心存儲器使用意義上 的輸入輸出數據隊列; "tr", "tm->when" 和 "rexmits" 保存 了核心套接字聲明的內部信息, 只用於調試; uid 是套接字創建者的有效 uid. |
||
udp |
該檔案保存了 UDP 套接字表, 大部分信息除用於調試以外沒有什麼用. "sl" 指出了套接字的核心散列槽號; "local address" 包括本地地址和端口號; "remote address" 包括遠地 地址和端口號(如果有連接的話); "St" 是套接字的內 部狀態; "tx_queue" 和 "rx_queue" 是核心存儲器使用意義上 的輸入輸出數據隊列; UDP 沒有使用 "tr","tm->when" 和 "rexmits"; uid 是套接字創建者的有效 uid. 格式如下: |
sl local_address rem_address st tx_queue rx_queue tr rexmits tm->when uid 1: 01642C89:0201 0C642C89:03FF 01 00000000:00000001 01:000071BA 00000000 0 1: 00000000:0801 00000000:0000 0A 00000000:00000000 00:00000000 6F000100 0 1: 00000000:0201 00000000:0000 0A 00000000:00000000 00:00000000 00000000 0
unix |
列出了當前系統的UNIX域套接字以及它們的狀態, 格式如下: |
Num RefCount Protocol Flags Type St Path 0: 00000002 00000000 00000000 0001 03 1: 00000001 00000000 00010000 0001 01 /dev/printer
‘Num’ 是核心散列槽號; ’RefCount’ 是使用者套接字號; ’Protocol’ 當前總是 0; ’Flags’ 是核心標誌, 指出了套接字的狀態; ’Type’ 當前總是 1(在核心中尚未支持 unix 域數據報套接字); ’St’ 是套接字內部狀態; ’Path’ 套接字綁捆的路徑(如果有的話).
pci |
該檔案列出了核心初始化時發現的所有 PCI 設備及其配置. |
||
scsi |
該目錄包括 scsi 中間層偽檔案及各種 SCSI 底層驅動器子目錄, 對系統中每個 SCSI host, 子目錄中都存在一個檔案與之對應, 展示了部分 SCSI IO 子系統的狀態. 這些檔案是 ASCII 格式 的, 可用cat閱讀. |
你也可以通過寫其中某些檔案來重新配置該子系統, 開關一些功能.
scsi |
該檔案列出了核心掌握的所有 SCSI 設備, 其內容就 和系統啟動時所看到的類似. 目前 scsi 只支持 singledevice命令, 該命令允許 root 添加一個熱插 拔(hotplugged)設備到一個已知設備列表中. |
命令 echo ’scsi singledevice 1 0 5 0’ > /proc/scsi/scsi 令 host scsi1 掃描 SCSI 通道 0, 看在 ID 5 LUN 0 是否存在設備, 如果在該地址 存在設備, 或者該地址無效, 則返回一個錯誤.
drivername
目前 drivername 可包含: NCR53c7xx, aha152x, aha1542, aha1740, aic7xxx, buslogic, eata_dma, eata_pio, fdomain, in2000, pas16, qlogic, scsi_debug, seagate, t128, u15-24f, ultrastore 或者 wd7000. 這些目錄展示那些至少注冊了一個 SCSI HBA 的驅動. 而對每個已注冊的 host, 每個目錄中都包含一個檔案與之對應, 而這些對應的 host 檔案就以初始化時分配給 host 的數字來命名.
這些檔案給出了驅動程式以及設備的配置, 統計數據等.
可以通過寫這些檔案實現不同的 host 上做不同的工作. 例如, root 可以用 latency 和 nolatency 命令打 開或者關閉 eata_dma 驅動器上測量延時的代碼, 也可以用 lockup 和 unlock 命令 控制 scsi_debug 驅動器所模擬的總線鎖操作.
self |
當某進程訪問 /proc 目錄時, 該目錄就指向 /proc 下以該進 程 ID 命名的目錄. |
||
stat |
核心及系統的統計數據. |
cpu 3357 0 4313 1362393
系統分別消耗在使用者模式, 低優先權的使用者模式(nice), 系統模式, 以及空閒任務的時間, 以 jiffy 為單位. 最後一個數值應該是 uptime 偽檔案第二個數值的 100 倍.
disk 0 0 0 0
目前並沒有實現這四個磁碟記錄, 我甚至認為就不應該實現它, 這是由於在別的機器上核心統計通常依賴轉換率及 每秒 I/O 數, 而這令每個驅動器只能有一個域.
page 5741 1808
系統(從磁碟)交換進的頁數和交換出去的頁數.
swap 1 0
取入的交換頁及被取出的交換頁的頁數.
intr 1462898
系統自啟動以來所收到的中斷數.
ctxt 115315
系統所作的進程環境切換次數.
btime 769041601
系統自 1970 年 1 月 1 號以來總的運行時間, 以秒為單位.
sys |
該目錄在 1.3.57 的核心裏開始出現, 包含一些對應於內 核變量的檔案和子目錄. 你可以讀這些變量, 有的也可以 通過proc修改, 或者用系統調用 sysctl(2) 修改. 目前該目錄下有如下三個子目錄: kernel;, ;net;, ;vm 每個各自包括一些檔案和子目錄. |
kernel
該目錄包括如下檔案: domainname;, ;file-max;, ;file-nr;, ;hostname;, ; inode-max;, ;inode-nr;, ;osrelease;, ;ostype;, ; panic;, ;real-root-dev;, ;securelevel;, ;version, 由檔名就可以清楚地得知各檔案功能. |
只讀檔案 file-nr 給出當前打開的檔案數.
檔案 file-max 給出系統所容許的最大可打開檔案數. 如果 1024 不夠大的話, 可以
echo 4096 > /proc/sys/kernel/file-max
類似地, 檔案 inode-nr 以及檔案 inode-max 指出了當前 inode 數和最大 inode 數.
檔案 ostype;, ;osrelease;, ;version 實際上是 /proc/version 的子字串.
檔案 panic 可以對核心變量 panic_timeout 進行讀/寫訪問. 如果該值為零, 核心在 panic 時進入(死)循環; 如果非零, 該值指出核心將自動重起的時間, 以秒為單位.
檔案 securelevel 目前似乎沒什麼意義 - root 無所不能.
uptime |
該檔案包含兩個數: 系統正常運行時間和總的空閒時間, 都以秒為單位. |
version
指明了當前正在運行的核心版本, 例如:
Linux version 1.0.9 (quinlan@phaze) #1 Sat May 14 01:51:54 EDT 1994
cat(1), find(1), free(1), mount(1), ps(1), tr(1), uptime(1), readlink(2), mmap(2), chroot(2), syslog(2), hier(7), arp(8), dmesg(8), netstat(8), route(8), ifconfig(8), procinfo(8)等等.
本手冊頁基本上是針對 Linux 1.3.11 核心, 如有必要請及時更新!
最後更新也是針對 Linux 1.3.11.
請注意許多字符串(例如環境變量或者命令行)是以內部格式保存的, 以 NUL 作為子域的結束標誌, 可以用 od -c 或者 tr ";\000"; ";\n"; 使之變得更可讀.
本手冊頁還不完善, 可能有不夠確切的地方, 需要經常更新.
/proc 可能會給那些使用了 chroot(2) 的進程帶來安全問題. 例如, 如果 /proc 被 mount 在 chroot 級別裏, 一個 到 /proc/1/root 的 chdir(2) 操作將返回檔案系統的原始根目錄. 由於 Linux 還不支持 fchroot(2) 調用, 該問題可能更應該看作一個特性而不是一個 bug.
mapping <mapping AT 263 DOT net>
2000/11/26
http://cmpp.linuxforum.net