![當我運行命令 cat /proc/cpuinfo 時會發生什麼?](https://rvso.com/image/52103/%E7%95%B6%E6%88%91%E9%81%8B%E8%A1%8C%E5%91%BD%E4%BB%A4%20cat%20%2Fproc%2Fcpuinfo%20%E6%99%82%E6%9C%83%E7%99%BC%E7%94%9F%E4%BB%80%E9%BA%BC%EF%BC%9F.png)
當我寫時會發生什麼cat /proc/cpuinfo
。這是作業系統的命名管道(或其他東西),它會動態讀取 CPU 資訊並在每次調用它時生成該文字?
答案1
每當您讀取 下的檔案時/proc
,都會呼叫核心中的一些程式碼來計算要讀取的文字作為檔案內容。內容是動態生成的這一事實解釋了為什麼幾乎所有文件的時間都報告為現在,大小報告為 0 — 此處您應該將 0 讀作「不知道」。與通常的檔案系統不同,掛載在 上的檔案系統/proc
稱為行程檔案系統,不會從磁碟或其他儲存媒體(如 FAT、ext2、zfs 等)或透過網路(如 NFS、Samba 等)載入數據,並且不會呼叫使用者程式碼(與保險絲)。
Procfs 存在於大多數非 BSD unice 中。它誕生於 AT&T 貝爾實驗室UNIX 第 8 版作為報告有關進程的資訊的一種方式(並且ps
通常是用於讀取資訊的漂亮印表機/proc
)。大多數 procfs 實作都有一個檔案或目錄,用於/proc/123
報告有關 PID 123 的進程的資訊/proc/cpuinfo
。
過去,Linux/proc
獲取了提供有關驅動程式資訊的各種文件,但現在不建議使用這種用途,而是使用/sys
,/proc
現在發展緩慢。為了向後相容,類似/proc/bus
和 的條目保留在原來的位置,但更新的類似介面是在 下建立的。在這個答案中,我將重點放在 Linux。/proc/fs/ext4
/sys
有關 Linux 的文檔的第一個和第二個入口點/proc
是:
當文件未涵蓋時,您的第三個入口點是閱讀原始碼。您可以在您的電腦上下載原始程式碼,但這是一個巨大的程序,並且LXRLinux 交叉引用是一個很大的幫助。 (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, …")
infs/proc/cpuinfo.c
。您可以看到程式碼幾乎是樣板程式碼:由於下面的大多數檔案/proc
只是轉儲一些文字數據,因此有輔助函數可以執行此操作。僅有一個seq_operations
結構,真正的肉在cpuinfo_op
資料結構,與體系結構相關,通常定義在arch/<architecture>/kernel/setup.c
(有時是不同的文件)中。以 x86 為例,我們得到arch/x86/kernel/cpu/proc.c
。其中主要功能是show_cpuinfo
列印出想要的文件內容;基礎設施的其餘部分按照讀取過程請求的速度將資料提供給讀取過程。您可以看到從核心中各個變數中的資料動態組裝的數據,包括一些動態計算的數字,例如CPU頻率。
其中很大一部分/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_操作。
的另一個重要領域/proc
是/proc/sys
,它是一個直接接口sysctl
。從此層次結構中的項目讀取會傳回對應 sysctl 值的值,寫入會設定 sysctl 值。 sysctl 的入口點位於fs/proc/proc_sysctl.c
。 Sysctl 有自己的註冊系統register_sysctl
和朋友。
答案2
當你試圖深入了解幕後正在發生什麼樣的魔法時,你最好的朋友就是你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
只是一個常規文件,或者至少看起來是一個。那麼讓我們深入挖掘一下。
更深層的潛水
#1- 與 ls..查看文件本身,它似乎“只是一個文件”。
$ 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- 帶文件..還有另一個線索表明該文件絕不是常規文件:
$ 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)來取代裝置規格。 (習慣選擇 none 不太幸運:來自 umount 的錯誤訊息「none busy」可能會令人困惑。)
如果我們看一下proc
的手冊頁:
proc 檔案系統是一個偽檔案系統,用作核心資料結構的介面。它通常安裝在/proc。其中大部分是唯讀的,但有些檔案允許更改核心變數。
在同一個手冊頁中再往下一點:
/proc/cpu訊息
這是 CPU 和系統架構相關項目的集合,對於每個支援的架構都有不同的清單。兩個常見的條目是處理器,它提供 CPU 編號和 bogomips;在核心初始化期間計算的系統常數。 SMP 機器具有每個 CPU 的資訊。 lscpu(1) 指令從此文件收集其資訊。
手冊頁的底部是對內核文檔的引用,您可以在此處找到該文檔,標題為:/proc 檔案系統。引用該文件:
proc 檔案系統可作為核心中內部資料結構的介面。它可用於獲取有關係統的資訊並在運行時更改某些核心參數(sysctl)。
結論
那我們在這裡學到了什麼?考慮到它/proc
被稱為偽文件系統,也是“內部資料結構的介面”,因此可以安全地假設其中的項目是不是實際的文件,而只是看起來像文件的表現形式,但實際上不是。
我將以這句話作為結束語,它顯然曾經出現在該版本的早期版本中 man 5 proc
我將以這句話作為結束語,它顯然曾經出現在大約 2004 年筆記:我不知道為什麼它被刪除,因為它很好地描述了什麼/proc
:
GNU/Linux 系統上的 /proc 目錄提供了一個類似檔案系統的核心介面。這允許應用程式和用戶使用正常的檔案系統 I/O 操作從核心獲取資訊並在核心中設定值。
proc 檔案系統有時被稱為進程資訊偽檔案系統。它不包含“真實”文件,而是包含運行時系統資訊(例如係統記憶體、安裝的設備、硬體配置等)。因此,它可以被視為內核的控制和資訊中心。事實上,相當多的系統實用程式只是呼叫該目錄中的檔案。例如,指令 lsmod 列出了核心載入的模組,與「cat /proc/modules」基本上相同,而 lspci 指令列出了連接到系統 PCI 總線的設備,與「cat /」相同。透過更改此目錄中的文件,您可以在系統運行時更改核心參數。
來源: proc 偽檔案系統
參考
答案3
@slm給出的答案非常全面,但我認為更簡單的解釋可能來自於視角的改變。
在日常使用中,我們可以將文件視為物理事物,即。儲存在某些裝置上的資料塊。這使得 /proc/cpuinfo 這樣的檔案變得非常神秘和令人困惑。然而,如果我們將文件視為一個介面;一種將資料傳入和傳出某些程式的方法。
以這種方式發送和接收資料的程式是檔案系統或驅動程式(取決於您如何定義這些術語,定義可能太廣泛或太窄)。重要的一點是一些這些程式使用硬體設備來儲存和檢索透過該介面發送的資料;但不是所有的。
文件系統的一些範例不使用儲存設備(至少直接)是:
- 使用尋找或計算資料的檔案系統。 Proc 就是一個例子,因為它從各個核心模組取得資料。一個極端的例子是 πfs ( github.com/philipl/pifs )
- 所有 FUSE 檔案系統,使用常規使用者空間程式處理數據
- 即時轉換另一個檔案系統資料的檔案系統,例如使用加密、壓縮甚至音訊轉碼( khenriks.github.io/mp3fs/ )
Plan9 作業系統 (http://en.wikipedia.org/wiki/Plan_9_from_Bell_Labs)是使用檔案作為通用程式介面的極端範例。