Linux proc system
proc 文件系統(tǒng)是由內(nèi)核創(chuàng)建的虛擬文件系統(tǒng)亭病,被內(nèi)核用來(lái)向外界報(bào)告信息的一個(gè)文件系統(tǒng),存儲(chǔ)著當(dāng)前內(nèi)核運(yùn)行狀態(tài)的一系列特殊文件吸重,是在系統(tǒng)運(yùn)行時(shí)才創(chuàng)建的蚕涤,所以它僅存在于內(nèi)存之中而不在外存(硬盤淹父、flash)上噪裕。通過(guò)proc虛擬文件可以實(shí)現(xiàn)Linux內(nèi)核空間和用戶間之間進(jìn)行通信蹲盘,可以說(shuō)是內(nèi)核向用戶空間打開(kāi)的一扇窗戶。
1.proc目錄分析
Linux系統(tǒng)開(kāi)機(jī)完成進(jìn)入文件系統(tǒng)后膳音,進(jìn)入proc目錄
這邊對(duì)proc目錄下常見(jiàn)文件進(jìn)行簡(jiǎn)要分析:
1.cat /proc/number
proc目錄下包含許多以數(shù)字命名的子目錄召衔,這些數(shù)字表示系統(tǒng)當(dāng)前正在運(yùn)行進(jìn)程的進(jìn)程號(hào),里面包含對(duì)應(yīng)該進(jìn)程相關(guān)的多個(gè)信息文件祭陷。
例如打開(kāi)進(jìn)程270的目錄苍凛,如下:
/proc/270# ls
auxv exe net stack
cgroup fd ns stat
clear_refs fdinfo oom_adj statm
cmdline limits oom_score status
comm maps oom_score_adj task
coredump_filter mem pagemap wchan
cpuset mountinfo personality
cwd mounts root
environ mountstats smaps
其中每一個(gè)文件都有具體的含義,
如:cmdline-啟動(dòng)當(dāng)前進(jìn)程的完整命令兵志,mem-當(dāng)前進(jìn)程所占用的內(nèi)存空間等
2.cat /proc/cmdline
在啟動(dòng)時(shí)傳遞至內(nèi)核的相關(guān)參數(shù)信息毫深,這些信息通常由u-boot傳遞的;
/proc# cat cmdline
console=ttyS0,115200n8, init=/etc/preinit mac_addr=00:0A:0B:0C:0D:0E,, ip=none root=ubi0:rootfs ubi.mtd=4 rootfstype=ubifs rw noinitrd
3.cat /proc/cpuinfo
處理器的相關(guān)信息的文件毒姨;
proc# cat cpuinfo
Processor : ARMv7 Processor rev 1 (v7l)
processor : 0
BogoMIPS : 1292.69
processor : 1
BogoMIPS : 1292.69
Features : swp half thumb fastmult vfp edsp neon vfpv3 tls
CPU implementer : 0x41
CPU architecture: 7
CPU variant : 0x2
CPU part : 0xc09
CPU revision : 1
4.cat /proc/crypto
系統(tǒng)上已安裝的內(nèi)核使用的密碼算法及每個(gè)算法的詳細(xì)信息列表哑蔫;
/proc# cat crypto
name : hmac(sha256)
driver : hmac(sha256-generic)
module : kernel
priority : 0
refcnt : 1
selftest : passed
type : shash
blocksize : 64
digestsize : 32
name : md5
driver : md5-generic
module : kernel
priority : 0
refcnt : 1
selftest : passed
type : shash
blocksize : 64
digestsize : 16
5.cat /proc/devices
系統(tǒng)已經(jīng)加載的所有塊設(shè)備和字符設(shè)備的信息,包含主設(shè)備號(hào)和設(shè)備組名弧呐;
/proc# cat devices
Character devices:
1 mem
4 ttyS
5 /dev/tty
5 /dev/console
5 /dev/ptmx
10 misc
13 input
89 i2c
90 mtd
180 usb
188 ttyUSB
Block devices:
259 blkext
8 sd
9 md
31 mtdblock
65 sd
66 sd
6.cat /proc/filesystems
當(dāng)前被內(nèi)核支持的文件系統(tǒng)類型列表文件闸迷,被標(biāo)示為nodev的文件系統(tǒng)表示不需要塊設(shè)備的支持;通常mount一個(gè)設(shè)備時(shí)俘枫,如果沒(méi)有指定文件系統(tǒng)類型將通過(guò)此文件來(lái)決定其所需文件系統(tǒng)的類型腥沽;
/proc# cat filesystems
nodev sysfs
nodev rootfs
nodev bdev
nodev proc
nodev cgroup
nodev cpuset
nodev tmpfs
nodev debugfs
nodev sockfs
nodev usbfs
nodev pipefs
nodev anon_inodefs
nodev rpc_pipefs
nodev devpts
nodev ramfs
nodev nfs
nodev jffs2
yaffs
yaffs2
nodev mtd_inodefs
nodev ubifs
vfat
fuseblk
nodev fuse
nodev fusectl
7.cat /proc/interrupts
架構(gòu)系統(tǒng)上每個(gè)IRQ相關(guān)的中斷號(hào)列表,多路處理器平臺(tái)上每個(gè)CPU對(duì)于每個(gè)I/O設(shè)備均有自己的中斷號(hào);
/proc# cat interrupts
CPU0 CPU1
29: 351743 3480462 GIC twd
36: 2005 0 GIC pfe_hif
37: 0 0 GIC pfe_hif_nocpy
45: 0 0 GIC spacc
53: 1 0 GIC dwc_otg, dwc_otg:usb3
54: 0 0 GIC xhci-hcd:usb1
59: 1621 0 GIC serial
60: 192 0 GIC comcerto_spi
61: 0 0 GIC comcerto_spi
62: 12 0 GIC I2C
90: 0 0 GIC pmutimer
91: 15 0 GIC timer4
92: 0 0 GIC timer5
94: 0 0 GIC rtc-alarm
IPI0: 0 0 Timer broadcast interrupts
IPI1: 17381 7533 Rescheduling interrupts
IPI2: 0 0 Function call interrupts
IPI3: 92 63 Single function call interrupts
IPI4: 0 0 CPU stop interrupts
Err: 0
8.cat /proc/iomem
每個(gè)物理設(shè)備在系統(tǒng)內(nèi)存中的映射信息鸠蚪;
/proc# cat iomem
00000000-02bfffff : System RAM
03400000-03ffffff : ddr
04000000-3fffffff : System RAM
04008000-0455dfff : Kernel text
0458a000-0461ea07 : Kernel data
83000000-83001fff : iram
904500d0-904500d8 : comcerto_wdt
90498000-90498fff : comcerto_spi.0
9049c000-9049cfff : I2C
904e0000-904e001f : c2k-rtc
90500000-9050ffff : apb
905e0000-905e0403 : c2k mdma base address
92000000-92ffffff : dwc_otg.0
96000000-960002c0 : dw_dmac.0
96400000-9640001f : serial
96500000-96500fff : comcerto_spi.1
9a000000-9affffff : ipsec
9b000000-9bffffff : elp
9c000000-9cffffff : axi
9d000000-9d00ffff : ahci
9f000000-9f7fffff : xhci-hcd
c0000000-c3ffffff : comcertoflash.0
c8300000-c8301fff : comcertonand
9.cat /proc/meminfo
系統(tǒng)中關(guān)于當(dāng)前內(nèi)存的利用狀況等的信息今阳,其內(nèi)容顯示為兩列,前者為統(tǒng)計(jì)屬性茅信,后者為對(duì)應(yīng)的值盾舌;
/proc# cat meminfo
MemTotal: 1012928 kB
MemFree: 901932 kB
Buffers: 0 kB
Cached: 32764 kB
SwapCached: 0 kB
Active: 56176 kB
Inactive: 21676 kB
Active(anon): 46048 kB
Inactive(anon): 4644 kB
Active(file): 10128 kB
Inactive(file): 17032 kB
Unevictable: 0 kB
Mlocked: 0 kB
HighTotal: 0 kB
AnonPages: 45120 kB
Mapped: 9912 kB
Shmem: 5604 kB
Slab: 17872 kB
SReclaimable: 2860 kB
SUnreclaim: 15012 kB
KernelStack: 1072 kB
PageTables: 1276 kB
10.cat /proc/mounts
系統(tǒng)當(dāng)前掛載的所有文件系統(tǒng),此文件指向/proc/self/mounts蘸鲸。
如下所示妖谴,其中第一列表示掛載的設(shè)備,第二列表示在當(dāng)前目錄樹(shù)中的掛載點(diǎn)酌摇,第三點(diǎn)表示當(dāng)前文件系統(tǒng)的類型膝舅,第四列表示掛載屬性(ro或者rw),第五列和第六列用來(lái)匹配/etc/mtab文件中的轉(zhuǎn)儲(chǔ)(dump)屬性窑多;
/proc# cat mounts
rootfs / rootfs rw 0 0
ubi0:rootfs / ubifs rw,noatime 0 0
proc /proc proc rw,noatime 0 0
sysfs /sys sysfs rw,noatime 0 0
tmpfs /tmp tmpfs rw,nosuid,nodev,noatime 0 0
tmpfs /dev tmpfs rw,noatime,size=512k,mode=755 0 0
devpts /dev/pts devpts rw,noatime,mode=600 0 0
debugfs /sys/kernel/debug debugfs rw,relatime 0 0
none /proc/bus/usb usbfs rw,relatime 0 0
11.cat /proc/modules
當(dāng)前裝入內(nèi)核的所有模塊名稱列表仍稀,其實(shí)與lsmod命令得到的結(jié)果一樣,只不過(guò)lsmod排版的更好看,/proc/modules的信息更全面埂息。
如下所示技潘,其中第一列表示模塊名遥巴,第二列表示此模塊占用內(nèi)存空間大小,第三列表示此模塊有多少實(shí)例被裝入崭篡,第四列表示此模塊依賴于其它哪些模塊挪哄,第五列表示此模塊的裝載狀態(tài)(Live:已經(jīng)裝入;Loading:正在裝入琉闪;Unloading:正在卸載)迹炼,第六列表示此模塊在內(nèi)核內(nèi)存(kernel memory)中的偏移量;
/proc# cat modules
cls_fw 3409 0 - Live 0x8352d000
sbr_cdev 1970 0 - Live 0x83529000 (O)
nbvpn 4111 1 sbr_cdev, Live 0x83524000 (O)
nf_nat_ftp 1346 0 - Live 0x834ee000
nf_conntrack_ftp 4626 1 nf_nat_ftp, Live 0x834e4000
fci 3474 5 - Live 0x834c2000 (O)
/proc# lsmod
Module Size Used by Tainted: P
cls_fw 3409 0
sbr_cdev 1970 0
nbvpn 4111 1 sbr_cdev
nf_nat_ftp 1346 0
nf_conntrack_ftp 4626 1 nf_nat_ftp
fci 3474 5
12.cat /proc/partitions
塊設(shè)備每個(gè)分區(qū)的主設(shè)備號(hào)(major)和次設(shè)備號(hào)(minor)等信息颠毙,同時(shí)包括每個(gè)分區(qū)所包含的塊
(block)數(shù)目斯入,可以與/proc/mtd的內(nèi)容一起查看;
/proc# cat partitions
major minor #blocks name
31 0 1024 mtdblock0
31 1 1024 mtdblock1
31 2 1024 mtdblock2
31 3 8192 mtdblock3
31 4 94208 mtdblock4
31 5 1024 mtdblock5
31 6 8192 mtdblock6
31 7 94208 mtdblock7
31 8 1024 mtdblock8
31 9 2048 mtdblock9
31 10 12288 mtdblock10
31 11 32768 mtdblock11
31 12 2048 mtdblock12
31 13 128 mtdblock13
31 14 512 mtdblock14
31 15 128 mtdblock15
31 16 128 mtdblock16
31 17 64 mtdblock17
31 18 64 mtdblock18
31 19 84320 mtdblock19
/proc# cat mtd
dev: size erasesize name
mtd0: 00100000 00020000 "barebox"
mtd1: 00100000 00020000 "bareboxfact"
mtd2: 00100000 00020000 "env"
mtd3: 00800000 00020000 "kernel1"
mtd4: 05c00000 00020000 "rootfs1"
mtd5: 00100000 00020000 "reserved_dtb1"
mtd6: 00800000 00020000 "kernel2"
mtd7: 05c00000 00020000 "rootfs2"
mtd8: 00100000 00020000 "reserved_dtb2"
mtd9: 00200000 00020000 "configcert"
mtd10: 00c00000 00020000 "reserved_avcsign"
mtd11: 02000000 00020000 "webrootdb"
mtd12: 00200000 00020000 "license"
mtd13: 00020000 00010000 "uloader"
mtd14: 00080000 00010000 "barebox"
mtd15: 00020000 00010000 "env"
mtd16: 00020000 00010000 "boardinfo"
mtd17: 00010000 00010000 "md5sum1"
mtd18: 00010000 00010000 "md5sum2"
mtd19: 05258000 0001f000 "rootfs"
以上內(nèi)容只是對(duì)proc目錄進(jìn)行簡(jiǎn)單的分析蛀蜜,更具體的可以查看proc文件系統(tǒng)詳解刻两。
2.proc接口的實(shí)現(xiàn)
在proc文件系統(tǒng)中,我們可以將對(duì)虛擬文件的讀寫(xiě)作為與內(nèi)核中實(shí)體進(jìn)行通信的一種手段滴某,進(jìn)行傳輸操作內(nèi)核數(shù)據(jù)磅摹,但是與普通文件不同的是,這些虛擬文件的內(nèi)容都是動(dòng)態(tài)創(chuàng)建的霎奢。
proc的定義在include/linux/proc_fs.h
下户誓,接口函數(shù)的實(shí)現(xiàn)在/fs/proc/generic.c
或/fs/proc/
文件夾下尋找,第一節(jié)的proc目錄分析幕侠,很多都是在/fs/proc/
文件夾在實(shí)現(xiàn)的帝美,從文件名稱就可以看出,如下:晤硕。
/fs/proc$ ls
array.c generic.c kcore.c mmu.c proc_sysctl.c task_mmu.c
base.c inode.c kmsg.c nommu.c proc_tty.c task_nommu.c
cmdline.c internal.h loadavg.c page.c root.c uptime.c
cpuinfo.c interrupts.c Makefile proc_devtree.c softirqs.c version.c
devices.c Kconfig meminfo.c proc_net.c stat.c vmcore.c
proc接口的創(chuàng)建有兩種方式悼潭,create_proc_entry
和proc_create
,下面分別舉例說(shuō)明:
1.create_proc_entry方式
直接查看源碼舞箍,應(yīng)該比較容易理解
//包含proc頭文件
#include <linux/proc_fs.h>
//定義proc接口
static struct proc_dir_entry *proc_dir = NULL;
static struct proc_dir_entry *proc_test1 = NULL;
static struct proc_dir_entry *proc_test2 = NULL;
//proc read的實(shí)現(xiàn)函數(shù)
static int proc_test1_read(char *page, char **start, off_t off, int count, int *eof, void *data)
{
int len = 0;
len = sprintf(page, "proc_test1 read ok!\n");
return len;
}
//proc write的實(shí)現(xiàn)函數(shù)
static int proc_test1_write(struct file *file, const char __user * buf, unsigned long count, void *data)
{
int val;
if(sscanf(buf, "%d", &val) != 1)
return -EINVAL;
if(val == 1)
printk("proc_test1 write true\n");
else
printk("proc_test1 write false\n");
return val;
}
//proc接口創(chuàng)建
static int proc_test_fs_create(void)
{
proc_dir = proc_mkdir("proc_test", NULL);
if(!proc_dir)
return -ENOMEM;
proc_test1 = create_proc_entry("proc_test1", 0644, proc_dir);
if(!proc_test1)
return -ENOMEM;
proc_test1->read_proc = proc_test1_read;
proc_test1->write_proc = proc_test1_write;
}
- 要使用proc虛擬文件需要包含頭文件<linux/proc_fs.h>
-
struct proc_dir_entry
結(jié)構(gòu)體是proc的數(shù)據(jù)結(jié)構(gòu) -
proc_mkdir("proc_test", NULL)
即在proc目錄下創(chuàng)建proc_test文件夾舰褪; -
create_proc_entry("proc_test1", 0644, proc_dir)
即在proc_test文件夾(父)下創(chuàng)建proc_test1文件(子); -
proc_test1_read()
函數(shù)即cat /proc/proc_test/proc_test1時(shí)顯示的數(shù)據(jù) -
proc_test1_write()
函數(shù)即echo 1 > /proc/proc_test/pro_test1時(shí)寫(xiě)入的數(shù)據(jù)
2.proc_create方式
我們首先查看這兩個(gè)創(chuàng)建函數(shù)的結(jié)構(gòu):
create_proc_entry(const char *name, mode_t mode, struct proc_dir_entry *parent)
proc_create(const char *name,mode_t mode, struct proc_dir_entry *parent, const struct file_operations *proc_fops)
可以觀察到proc_create
函數(shù)增加一個(gè)struct file_operations
結(jié)構(gòu)體创译,那在實(shí)現(xiàn)的時(shí)候有什么區(qū)別呢抵知?
proc_create
方式的實(shí)現(xiàn)其實(shí)在/fs/proc/
文件夾下有很多例子,如cmdline.c/version.c等软族,對(duì)應(yīng)申明等動(dòng)作上面已經(jīng)給出,這邊就不再重復(fù)了残制,直接寫(xiě)一個(gè)proc_create
方式的例子吧立砸。
static int proc_test2_show(struct seq_file *seq, void *v)
{
seq_printf(seq, "proc_test2 read ok!\n");
return 0;
}
static int proc_test2_open(struct inode *inode, struct file *file)
{
return single_open(file, proc_test2_oshow, NULL);
}
static int proc_test2_write (struct file *file, const char *buf,
unsigned long count, void *data)
{
int val;
if(sscanf(buf, "%d", &val) != 1)
return -EINVAL;
if(val == 1)
printk("proc_test2 write true\n");
else
printk("proc_test2 write false\n");
return val;
}
static struct file_operations proc_test2_fops = {
.open = proc_test2_open,
.write = proc_test2_write,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
static int proc_test_fs_create(void)
{
proc_test2 = proc_create ("proc_test2", 0644, proc_dir, &proc_test2_fops);
if (!proc_test2)
return -ENOENT;
}
注意到proc_create
函數(shù)增加一個(gè)struct file_operations
結(jié)構(gòu)
,而不是像create_proc_entry
那樣直接返回初茶。其實(shí)原理也一樣颗祝,一個(gè)是將成員函數(shù)write、read等指向proc接口proc_dir_entry
,而這邊是將成員函數(shù)wriet螺戳、read等指向結(jié)構(gòu)體file_operations
搁宾。
使用proc_create
方式則不使用read成員,因?yàn)楫?dāng)cat該proc成員時(shí)倔幼,seq_read()函數(shù)被反復(fù)調(diào)用盖腿,導(dǎo)致一直打印read函數(shù)的內(nèi)容,不過(guò)也可以通過(guò)判斷off_t *off
變量進(jìn)行處理损同,這邊不過(guò)多描述翩腐。
既然不使用read的方式,那就有新的方式代替膏燃,這邊使用成員open茂卦,通過(guò)上面的例子可以很直觀的看到,open函數(shù)會(huì)調(diào)用show函數(shù)组哩,所以show函數(shù)的內(nèi)容就是cat時(shí)得到的內(nèi)容等龙,write成員則與create_proc_entry
的實(shí)現(xiàn)方式一致。
Linux proc system的分析就到這邊伶贰,有感悟時(shí)會(huì)持續(xù)會(huì)更新蛛砰。
注:以上內(nèi)容都是本人在學(xué)習(xí)過(guò)程積累的一些心得,難免會(huì)有參考到其他文章的一些知識(shí)幕袱,如有侵權(quán)暴备,請(qǐng)及時(shí)通知我,我將及時(shí)刪除或標(biāo)注內(nèi)容出處们豌,如有錯(cuò)誤之處也請(qǐng)指出涯捻,進(jìn)行探討學(xué)習(xí)。文章只是起一個(gè)引導(dǎo)作用望迎,詳細(xì)的數(shù)據(jù)解析內(nèi)容還請(qǐng)查看Linux相關(guān)教程障癌,感謝您的查閱。