5-Linux proc system

题图:gratisography

Linux proc system

proc 文件系统是由内核创建的虚拟文件系统,被内核用来向外界报告信息的一个文件系统,存储着当前内核运行状态的一系列特殊文件,是在系统运行时才创建的,所以它仅存在于内存之中而不在外存(硬盘、flash)上。通过proc虚拟文件可以实现Linux内核空间和用户间之间进行通信,可以说是内核向用户空间打开的一扇窗户。

1.proc目录分析


Linux系统开机完成进入文件系统后,进入proc目录

这边对proc目录下常见文件进行简要分析:

1.cat /proc/number

proc目录下包含许多以数字命名的子目录,这些数字表示系统当前正在运行进程的进程号,里面包含对应该进程相关的多个信息文件。

例如打开进程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

其中每一个文件都有具体的含义,

如:cmdline-启动当前进程的完整命令,mem-当前进程所占用的内存空间等

2.cat /proc/cmdline

在启动时传递至内核的相关参数信息,这些信息通常由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

处理器的相关信息的文件;

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

系统上已安装的内核使用的密码算法及每个算法的详细信息列表;

/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

系统已经加载的所有块设备和字符设备的信息,包含主设备号和设备组名;

/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

当前被内核支持的文件系统类型列表文件,被标示为nodev的文件系统表示不需要块设备的支持;通常mount一个设备时,如果没有指定文件系统类型将通过此文件来决定其所需文件系统的类型;

/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

架构系统上每个IRQ相关的中断号列表,多路处理器平台上每个CPU对于每个I/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

每个物理设备在系统内存中的映射信息;

/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

系统中关于当前内存的利用状况等的信息,其内容显示为两列,前者为统计属性,后者为对应的值;

/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

系统当前挂载的所有文件系统,此文件指向/proc/self/mounts。

如下所示,其中第一列表示挂载的设备,第二列表示在当前目录树中的挂载点,第三点表示当前文件系统的类型,第四列表示挂载属性(ro或者rw),第五列和第六列用来匹配/etc/mtab文件中的转储(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

当前装入内核的所有模块名称列表,其实与lsmod命令得到的结果一样,只不过lsmod排版的更好看,/proc/modules的信息更全面。

如下所示,其中第一列表示模块名,第二列表示此模块占用内存空间大小,第三列表示此模块有多少实例被装入,第四列表示此模块依赖于其它哪些模块,第五列表示此模块的装载状态(Live:已经装入;Loading:正在装入;Unloading:正在卸载),第六列表示此模块在内核内存(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

块设备每个分区的主设备号(major)和次设备号(minor)等信息,同时包括每个分区所包含的块
(block)数目,可以与/proc/mtd的内容一起查看;

/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"

以上内容只是对proc目录进行简单的分析,更具体的可以查看proc文件系统详解

2.proc接口的实现


在proc文件系统中,我们可以将对虚拟文件的读写作为与内核中实体进行通信的一种手段,进行传输操作内核数据,但是与普通文件不同的是,这些虚拟文件的内容都是动态创建的。

proc的定义在include/linux/proc_fs.h下,接口函数的实现在/fs/proc/generic.c/fs/proc/文件夹下寻找,第一节的proc目录分析,很多都是在/fs/proc/文件夹在实现的,从文件名称就可以看出,如下:。

/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接口的创建有两种方式,create_proc_entryproc_create,下面分别举例说明:

1.create_proc_entry方式

直接查看源码,应该比较容易理解

//包含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的实现函数
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的实现函数
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接口创建
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结构体是proc的数据结构
  • proc_mkdir("proc_test", NULL)即在proc目录下创建proc_test文件夹;
  • create_proc_entry("proc_test1", 0644, proc_dir)即在proc_test文件夹(父)下创建proc_test1文件(子);
  • proc_test1_read()函数即cat /proc/proc_test/proc_test1时显示的数据
  • proc_test1_write()函数即echo 1 > /proc/proc_test/pro_test1时写入的数据

2.proc_create方式

我们首先查看这两个创建函数的结构:

  • 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函数增加一个struct file_operations结构体,那在实现的时候有什么区别呢?

proc_create方式的实现其实在/fs/proc/文件夹下有很多例子,如cmdline.c/version.c等,对应申明等动作上面已经给出,这边就不再重复了,直接写一个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函数增加一个struct file_operations结构
,而不是像create_proc_entry那样直接返回。其实原理也一样,一个是将成员函数write、read等指向proc接口proc_dir_entry,而这边是将成员函数wriet、read等指向结构体file_operations

使用proc_create方式则不使用read成员,因为当cat该proc成员时,seq_read()函数被反复调用,导致一直打印read函数的内容,不过也可以通过判断off_t *off变量进行处理,这边不过多描述。

既然不使用read的方式,那就有新的方式代替,这边使用成员open,通过上面的例子可以很直观的看到,open函数会调用show函数,所以show函数的内容就是cat时得到的内容,write成员则与create_proc_entry的实现方式一致。

Linux proc system的分析就到这边,有感悟时会持续会更新。

注:以上内容都是本人在学习过程积累的一些心得,难免会有参考到其他文章的一些知识,如有侵权,请及时通知我,我将及时删除或标注内容出处,如有错误之处也请指出,进行探讨学习。文章只是起一个引导作用,详细的数据解析内容还请查看Linux相关教程,感谢您的查阅。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,290评论 4 363
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,399评论 1 294
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,021评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,034评论 0 207
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,412评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,651评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,902评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,605评论 0 199
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,339评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,586评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,076评论 1 261
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,400评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,060评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,083评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,851评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,685评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,595评论 2 270

推荐阅读更多精彩内容

  • linux资料总章2.1 1.0写的不好抱歉 但是2.0已经改了很多 但是错误还是无法避免 以后资料会慢慢更新 大...
    数据革命阅读 12,018评论 2 34
  • make menuconfig过程解析作者 codercjg 在 28 九月 2015, 5:27 下午 make...
    codercjg阅读 867评论 0 1
  • 转载自:http://blog.csdn.net/hguisu/article/details/6122513原作...
    miaoiao阅读 1,469评论 0 7
  • Linux系统一般有4个主要部分: 内核、shell、文件系统和应用程序。内核、shell和文件系统一起形成了基本...
    偷风筝的人_阅读 3,182评论 1 17
  • 人体内毒素好厉害呀,必须要排毒的。
    徐子迦阅读 243评论 0 0