轉自:網路
proc簡介
在linux的根目錄下存在一個/proc目錄,/proc檔案系統是一種虛擬檔案系統,以檔案系統目錄和檔形式,提供一個指向內核數據結構的介面,透過它能夠檢視和改變各種系統內容.proc目錄通常情況下是由系統自動掛載在/proc目錄下,但是我們也可以自行手動掛載.
1 | mount -t proc proc /proc |
/proc
目錄下的大部份檔都是唯讀的,部份檔是可寫的,我們透過這些可寫的檔來修改內核的一些配置;
說明
在/proc目錄下,一般會存在如下檔和目錄.
/proc/pid
每一個
/proc/pid
目錄中還存在一系列目錄和檔,這些檔和目錄記錄的都是關於pid對應行程的資訊.例如,在
/proc/pid
的目錄下存在一個task目錄,在task目錄下又存在
task/tid
這樣的目錄,這個目錄就是包含此行程中的每個執行緒的資訊,其中的tid是內核執行緒的tid;透過 GETDENTS(2) 遍歷/proc就能夠看到所有的
/proc/pid
的目錄,當然透過
ls -al /proc
的方式也可以看到所有的資訊.
/proc/tid
/proc/tid
每一個
/proc/tid
目錄中還存在一系列目錄和檔,這些檔和目錄記錄的都是有關執行緒tid對應的資訊,這些資訊與具體的
/proc/pid/task/tid
的目錄相同,所記錄的資訊也是相同的.我們遍歷/proc時並不能看到
/proc/tid
的資訊,同樣透過
ls -al /proc
的方式也無法看到.但是雖然無法看到,但是卻可以透過
cd /proc/tid
進入到這個執行緒的內部;傳統的透過
ps | grep tid
是無法看到資訊的,透過
ps -T -p pid
的方式就能夠看到tid的資訊.
/proc/self
這是一個link,當行程存取此連結時,就會存取這個行程本身的
/proc/pid
目錄,如下所示:
1 | ls -al /proc/self |
/proc/thread-self
這是一個link,當存取次連結時,就會存取行程的
/proc/self/task/tid
目錄。
1 | ls -al /proc/thread-self |
/proc/[a-z]*
/proc/[a-z]*
, proc下面還有許多其他的檔,記錄了系統中的各種資訊,Linux /proc、/dev Principle 這篇文章對proc目錄下的檔進行了詳細的說明.
檔和目錄
在第一節主要是對poc目錄進行了一個簡單的介紹,本章節則主要是關註/proc/pid中記錄的行程的具體的資訊。
/proc/pid
每一個執行的行程都存在pid,對應的在/proc就存在一個/proc/pid的目錄,這個/proc/pid目錄也是一個 偽檔案系統 .通常情況下每個/proc/pid是屬於執行行程的有效使用者的UID和GID.但是如果一個行程的dumpable內容的值大於1,從安全形度考慮,/proc/pid的內容就是root:root.
在4.11的內核版本之前,root:root表示的是全域UID和GID (在初始化的使用者空間中的UID和GID都是0).但是在4.11之後的內核版本,如果這個行程不是在初始化的使用者空間中,它的UID卻是0,那麽對應的/proc/pid的許可權也是root:root.這就意味著在docker容器內,如果將行程的PID設定為0,那麽這個行程在容器內就是以root許可權執行的.
行程的 dumpable 的內容可能因為如下的原先發生改變:
透過 prctl 設定了 PR_SET_DUMPABLE 內容
透過
/proc/sys/fs/suid_dumpable
檔修改
將dumpable重設為1,就可以恢復
/proc/[pid]/*
檔到行程有效的UID和GID.
/proc/pid/attr
/proc/pid/attr
是一個目錄,這個目錄下的檔的作用是為安全模組提供了API.透過這些檔我們可以讀取或者設定一些安全相關的選項.這個目錄目前能夠支持SELinux,但是本意是為了能夠支持更多的其他的安全模組.以下將會演示SELinux如何使用這些檔.
PS: 只有內核開啟了CONFIG_SECURITY選項,才能夠看到這個目錄.
/proc/pid/attr/current
這個檔的內容記錄了當前行程的安全內容
在SELinux中,這個檔主要是用於得到當前行程的安全上下文.在2.6.11的內核之前,這個檔不能用來設定安全上下文(寫操作是不允許的),因為SELinux限制了行程安全轉換為
EXECVE
(2) (參考下方的
/proc/pid/attr/exec
). 從2.6.11之後,SELinux取消了這個限制.如果策略允許,SELinux透過向這個檔寫入來支持設定行為,雖然這個操作僅僅只是為了維護老的上下文和新的上下文的隔離.在2.6.28之前,SELinux不允許多執行緒程式的執行緒透過這個值來設定安全上下文,因為這樣會導致共享記憶體空間的縣城的安全上下文不一致.從2.6.28之後,SELinux取消了這個限制,開始支持多執行緒的設定方法.但是需要滿足一定的條件,新的安全上下文需要繫結在老的上下文上,並且這個繫結關系是設定在策略當中的,同時新的安全上下文是老的安全上下文的一個子集.
/proc/pid/attr/exec
這個檔代表給行程的execve的內容.
在SELinux中,有時候需要支持role/domain的轉換,execve(2)一般都是作為這種轉換的首選,因為它提供了對行程的新的安全標簽和狀態繼承的更好的控制.在SELinux中,如果重設了execve(2),那麽這個程式就會恢復到execve(2)所設定的狀態.
/proc/pid/attr/fscreate
這個檔代表行程與檔有關的許可權,包括open(2) mkdir(2) symlink(2) mknod(2)
SELinux透過此檔能夠保證以一個安全的方式建立檔,所以這裏不會存在不安全的存取的風險(在檔建立和檔內容設定).如果重設了execve(2),那麽程式也會被重設,包括程式所建立的檔.
/proc/pid/attr/keycreate
如果行程將安全上下文寫入此檔,那麽所有建立key的行為都會被載入到此上下文中.更多的資訊可以參考內核檔 Documentation/security/keys/core.rst (在Linux3.0和Linux4.13中檔是 Documentation/security/keys.txt 在Linux3.0之前是 Documentation/keys.txt )
/proc/pid/attr/prev
這個檔包含了行程在執行最後一個execve(2)的安全上下文.換句話說,這個檔的內容是
/proc/pid/attr/current
前一個值
/proc/pid/attr/socketcreate
如果一個行程向這個檔寫入安全上下文,那麽之後所有的sockets的建立行為都會在此行程上下文中;
/proc/pid/autogroup
參考 sched(7)
/proc/pid/auxv
這個檔包含了在行程執行時,傳遞給行程的ELF的直譯器的資訊.這個檔的格式是一個無符號的long型別的ID加上每個entry的一個無符號的long型別,這最後的一個entry包含了兩個零。參考 getauxval(3)
/proc/pid/cgroup
參考 cgroups(7)
/proc/pid/clear_refs
這是一個只寫檔,只有行程的owner能夠寫.只有下面這些值能夠被寫入:
(Since Linux 2.6.22)對行程所有的相關的頁重設所有的PG_Referenced 和ACCESSED/YOUNG位 (在2.6.32之前,任何的非零的值寫入到此檔都是有效的)
(Since Linux2.6.32) 對行程所有的匿名頁重設所有的PG_Referenced和ACCESSED/YOUNG位
(Since Linux2.6.32)對行程所有的與檔相關的頁重設所有的PG_Referenced和ACCESSED/YOUNG位.清除所有的PG_Referenced和ACCESSED/YOUNG提供了一個方法用於測量一個行程是有了多少記憶體.第一個可以參考的是/proc/[pid]/smaps中的VMAs中的值.當清除了PG_Referenced和ACCESSED/YOUNG 經過一段時間之後,再次測量這個值.
(Since Linux3.11) 清空掉行程所有的頁的soft-dirty位.透過向/proc/[pid]/clear_refs清空,就能夠知道哪些頁是被汙染了.
將peak resident重設為行程當前的resident的大小.
如果向/proc/pid/clear_refs寫入其他的任何值,不會有任何的效果;只有當啟用了CONFGI_PROC_PAGE_MONITOR的內核選項之,才會出現/proc/pid/clear_refs檔
/proc/pid/cmdline
這個唯讀檔是包含了行程執行的完整命令.如果此行程是一個僵屍行程,那麽次檔沒有任何的內容.
/proc/pid/comm
此檔記錄的是行程命令的comm.在同一個行程中的不同執行緒的comm可能不同,可以存取
/proc/[pid]/task/tid/comm
獲取行程中的每個執行緒的comm.透過向
/proc/self/task/tid/comm
寫入就能夠修改自己或者其他執行緒的comm.如果comm超過TASK_COMM_LEN(16)就會被截斷.
這個檔的值可以透過 prctl(2) 的PR_SET_NAME和PR_GET_NAME的操作來設定和獲取,透過 pthread_setname_np(3) 能夠設定執行緒的comm
/proc/pid/coredump_filter
參考 core(5)
/proc/pid/cpuset
參考 cpuset(7)
/proc/pid/cwd
這是一個當前的行程的工作目錄.比如如果想要知道pid為4451的行程的工作目錄,可以透過如下的命令檢視:
1 | cd /proc/4451/cwd; /bin/pwd |
在bash環境下,可能會出現/bin/pwd: couldn’t find directory entry in ‘..’ with matching i-node的錯誤,這是因為pwd通常是shell內建的,需要使用這樣的命令:
1 | /proc/4451/cwd; pwd -P |
在多執行緒的程式中,如果主執行緒已經結束了,那麽cwd的結果就是空.
取消或者是讀取(readlink(2))這個連結的內容的許可權是由ptrace的存取模式PTRACE_MODE_READ_FSCREDS來控制的,參考ptrace(2).
/proc/pid/environ
這個檔包含的是當程式使用execve啟動程式時的環境變量的值,其中的entries是透過
0x0
分割的,結尾是可能是null.如果我們需要查詢一個指定的行程的環境變量,我們可以采用如下的方法:
1 | #cat /proc/4451/environ | tr '\000' '\n' |
如果執行了execve(2)之後,行程呼叫了putenv(3)或者是直接修改environ(7) ,那麽environ變量的值是無法隨之改變的.
更進一步,行程能夠透過prctl(2)修改PR_SET_MM_ENV_START的值來修改這個檔所參照的記憶體位置.
讀取這個檔的許可權是由ptrace(2)的PTRACE_MODE_READ_FSCREDS來控制.
/proc/pid/exe
在Linux2.2的內核及其之後,/proc/pid/exe是直接執行的二進制檔的符號連結.這個符號連結能夠被取消.嘗試開啟這個檔就相當與開啟了二進制檔,甚至可以透過重新輸入/proc/pid/exe重新執行一個對應於pid的二進制檔.在一個多執行緒的程式中,如果主執行緒已經結束了,就無法存取這個符號連結.
在Linux2.0及其之前,/proc/pid/exe是指向當前行程執行的二進制檔.采用readlink()讀取返回如下的結果: [device]:inode
/proc/pid/fd
這是一個子目錄,包含了當前行程開啟的每一個檔.每一個條目都是一個檔描述符,是一個符號連結,指向的是實際開啟的地址.0表示標準輸入,1表示標準輸出,2表示標準錯誤.在多執行緒程式中,如果主程式結束了,那麽這個資料夾將不能被存取.
程式能夠使用檔名作為命令列參數,如果沒有提供這樣的參數,就不會從標準輸入中讀取資訊也不會將標準輸出發送到檔中.但是即使沒有提供與檔相關的命令列參數,我們仍然可以使用標準的輸出輸入.例如我們可以透過-i和-o分別指向輸入和輸出檔.如下所是:
1 | $ foobar -i /proc/self/fd/0 -o /proc/self/fd/1 ... |
在某些UNIX或者類似UNIX的系統中,/proc/self/fd/N與/dev/fd/N大致相同.大部份系統提供/dev/stdin,/dev/stdout,/dev/stderr的符號連結,分別只想的是/proc/self/fd中的0,1,2.所以上述的命令也可以寫為:
1 | $ foobar -i /dev/stdin -o /dev/stdout ... |
/proc/pid/fdinfo/
這是一個子目錄,包括了當前行程開啟的所有的檔的檔描述符.可以讀取每一個檔描述符的內容一獲取i資訊.如下所示:
1 | $ cat /proc/5040/fdinfo/99 |
pos 是十進制,顯示當前檔的偏移量
flag是八進制,顯示檔的存取模式和檔狀態標誌.
該目錄中的檔只有行程的所有者才可以讀.
/proc/pid/limits
該檔顯示了每個行程的軟中斷,硬中斷和度量單位.在Linux2.6.35之前,這個檔僅僅只能被行程實際的UID存取.在26.36之後,該檔可以被系統中所有的使用者讀取.
/proc/pid/maps
包含了當前行程對映的記憶體區域以及他們的存取許可權.檔格式如下:
1 | address perms offset dev inode pathname |
address,表示行程占用的地址.
perms, 表示一系列許可權.r=read,w=write,x=execute,s=shared,p=private(copy on write)
offset, 表示檔偏移量
dev:表示裝置 (主要裝置,次要裝置)
inode: 表示裝置上面的inode編號.如果是0,表示沒有索引節點與記憶體區域關聯,就如同BSS段一樣.
pathname,在Linux2.0之前,沒有pathname欄位.
/proc/pid/mem
該檔可以透過open,read,seek存取行程的記憶體頁.
/proc/pid/mountinfo
這個檔主要是包含了掛載資訊.檔內容結構如下:
1 | 36 35 98:0 /mnt1 /mnt2 rw,noatime master:1 - ext3 /dev/root rw,errors=continue |
mount ID,掛載點的唯一標識
parent ID,當前掛載點的父掛載點的ID
major:minor, files的st_dev的值
root: 檔案系統的根掛載點
mount point: 相對於行程根目錄的掛載點
mount options: 預掛載選項
options fields:
tag:[value]
型別的欄位
sparator: options fields結束標誌
file systemtype: 檔案系統的名稱,以
type[.subtype]
的方式命名
mount source: 檔特定資訊
super options: 超級塊選項
/proc/pid/mounts
列出在當前行程掛載空間下所有的已經掛載過的檔.檔的格式透過 fstab 檢視.在kernel 2.6.15之後,這個檔是論詢式的.在讀取檔之後,這個事件會導致select標記這個檔是可讀的,並且pool()和epoll_wait()會將此檔標記為遇到了錯誤.
/proc/pid/mountstas
該檔會列舉在當前行程掛載空間下的所有掛載點的詳細資訊,包括統計資訊,配置資訊.檔格式如下:
1 | device /dev/sda7 mounted on /home with fstype ext3 [statistics] |
載的裝置名
掛載點
檔案系統型別
可選的統計和配置資訊.在2.6.26之後,僅NFS檔案系統可以到處此欄位資訊
/proc/pid/ns/
這是一個子目錄.每一個子目錄可以透過 setns 操作.關於更多的操作,參見clone
/proc/pid/ns/ipc
將檔掛載在其他地方可以使pid指定的行程的IPC名稱空間保持活動狀態,即使在當前名稱空間的所有的行程全部都截止了.開啟次檔就會返回檔控制代碼.只要檔保持開啟狀態,那麽IPC的名稱空間就可以保持活動狀態.檔描述符可以透過 setns 傳遞.
/proc/pid/ns/net
將檔掛載在其他地方可以使pid指定的行程的網路名稱空間保持活動狀態,即使在當前名稱空間的所有的行程全部都截止了.開啟次檔就會返回檔控制代碼.只要檔保持開啟狀態,那麽網路的名稱空間就可以保持活動狀態.檔描述符可以透過 setns 傳遞.
/proc/pid/ns/uts
將檔掛載在其他地方可以使pid指定的行程的UTS 名稱空間保持活動狀態,即使在當前名稱空間的所有的行程全部都截止了.開啟次檔就會返回檔控制代碼.只要檔保持開啟狀態,那麽UTS名稱空間就可以保持活動狀態.檔描述符可以透過 setns 傳遞
/proc/pid/numa_maps
參見 numa
/proc/pid/oom_adj
這個方法用於決定在出現OOM的情況下,哪個行程被殺掉.內核使用該值對行程的oom_score的值進行設定,oom_score的有效取值區間是-17至15.-17將會完全殺死這個行程.正數會增加行程當oom時被殺掉的可能性,負數會減小行程被oom殺掉的可能性.
該檔的預設值是0.新行程會繼承其父行程的oom_adj設定.只有具有CAP_SYS_RESOURCE許可權的行程才能夠更新此檔.
在Linux2.6.36,推薦使用/proc/[pid]/oom_score_adj.
/proc/pid/oom_score
該檔顯示了如果內核出現oom情況時決定殺死該行程時的分數.分數越高意味著行程越容易被殺掉.
/proc/pid/oom_adj_score
這個檔用於調整在記憶體不足時應該殺掉哪個行程的分數判斷.
/proc/pid/root
該值可以用於 chroot 預先設定行程的根檔案系統. 這個檔指向當前行程的根目錄.作業類似於前面說過的 exe fd/* 等等.
在多執行緒的程式中,如果主執行緒推出了此符號連結的內容將無法存取.
/proc/pid/smaps
這個檔顯示了每個行程對映的記憶體消耗.每一個記憶體消耗都有如下的設定:
1 | 08048000-080bc000 r-xp 00000000 03:02 13130 /bin/bash |
第一行顯示的資訊與/proc/[pid]/maps中的對映資訊相同.剩下分別表示的是,對映的大小,RAM中當前駐留的對映大小,對映中幹凈和臟共享頁的大小以及對映中幹凈和臟共享私有頁數.
只有在啟用了CONFIG_MMU內核配置選項時,此檔才會存在.
/proc/pid/stat
關於行程的狀態資訊.主要是用於 ps 展示。
/proc/pid/statm
提供記憶體的使用情況.格式如下所示:
1 | size (1) total program size |
/proc/pid/status
以更加可讀的形式提供與
/proc/pid/stat
和
/proc/pid/statm
一樣的資訊.以下是範例.
1 | $ cat /proc/$$/status |
/proc/pid/task
該目錄包含的是行程中的每一個執行緒.每一個目錄的名字是以執行緒ID命名的(tid).在每一個tid下面的目錄結構與
/proc/pid
下面的目錄結構相同.對於所有執行緒共享的內容,
task/tid
子目錄中的每個檔內容與
/proc/pid
目錄中的相應檔內容相同.例如所有執行緒中的
task/tid/cwd
檔和父目錄中的
/proc/pid/cwd
檔內容相同,因為所有的執行緒共享一個工作目錄.對於每個執行緒的不同內容,
task/tid
下相應檔的值也不相同.
/proc/cmdline
在引導時傳遞給內核的參數
/proc/cpuinfo
cpu和系統結構的資訊.常見資訊包括CPU的數量以及常見的系統常數.
/proc/meminfo
此檔包含了系統當前記憶體的使用資訊. free 用來報告系統中可用記憶體和已使用記憶體(實體記憶體和交換記憶體)以及內核中共享記憶體和緩沖區的大小.每一行都是以
參數名:參數值
顯示.格式如下所示:
1 | $ cat /proc/$$/status |
/proc/modules
顯示當前載入到系統中所有的模組.
/proc/mounts
在內核2.4.19之前,這個檔會列舉當前系統中掛載的所有的節點資訊.在2.4.19之後,僅僅只會列舉出當前行程在mount的名稱空間下的掛載資訊,即/proc/self/mounts的掛載資訊,參見 fstab
/proc/net
此目錄下面個中文虛擬的檔案系統,主要是記錄了系統中各種與網路有關的資訊.這個檔都是普通 ASCII檔 ,都可以透過cat的方式讀取.
/proc/net/arp
此檔主要是包含了用於地址解析的內核
ARP
表的資訊.範例如下:
1 | IP address HW type Flags HW address Mask Device |
IP address 是主機的IPv4的地址
HW type 是來自與RFC826的硬體型別的地址
Flags 是ARP 結構中的內部標識 參見 /usr/include/linux/if_arp.h
HW address 是數據鏈路層的對映地址
/proc/net/dev
dev虛擬檔案系統顯示網路狀態的資訊,包括發送和接受的封包的數量,錯誤和沖突以及其他的統計資訊,這些資訊也可以透過ifconfig檢視. 範例如下:
1 | Inter-| Receive | Transmit |
/proc/net/raw
儲存的是RAW套接字表的資訊
/proc/net/snmp
保存的是SNMP代理的IP,ICMP以及UDP的管理資訊
/proc/net/tcp
保存的是系統中的TCP表的資訊
/proc/net/udp
保存的是系統中的UDP表的資訊
/proc/net/unix
顯示當前系統所有的UNIX domain socket以及它們的狀態資訊.範例如下:
1 | Num RefCount Protocol Flags Type St Path |
Num 是kernle table slot number
Refcount 是使用這個套接字的使用者數
Protocol 當前永遠是0
Flags 表示當前內部內核標誌 用於表示套接字狀態
Type 當前永遠是1
St 套接字內部狀態
Path 是套接字繫結路徑
/proc/stat
內核/系統的資訊
/proc/sys
該目錄下有很多的目錄和子目錄,其中主要是記錄了與內核變量相關的資訊.
<END>
點這裏👇關註我,記得標星呀~
感謝你的分享,點贊,在看三連