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相關教程,感謝您的查閱。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • linux資料總章2.1 1.0寫的不好抱歉 但是2.0已經改了很多 但是錯誤還是無法避免 以后資料會慢慢更新 大...
    數據革命閱讀 12,203評論 2 33
  • make menuconfig過程解析作者 codercjg 在 28 九月 2015, 5:27 下午 make...
    codercjg閱讀 978評論 0 1
  • 轉載自:http://blog.csdn.net/hguisu/article/details/6122513原作...
    miaoiao閱讀 1,542評論 0 7
  • Linux系統一般有4個主要部分: 內核、shell、文件系統和應用程序。內核、shell和文件系統一起形成了基本...
    偷風箏的人_閱讀 3,270評論 1 17
  • 人體內毒素好厲害呀,必須要排毒的。
    徐子迦閱讀 334評論 0 0