- 内容摘要:Linux系统上的/proc目录是一种文件系统,即proc文件系统。
[root@rhel5 ~]# ll /proc total 0 dr-xr-xr-x 5 root root 0 Feb 8 17:08 1 dr-xr-xr-x 5 root root 0 Feb 8 17:08 10 dr-xr-xr-x 5 root root 0 Feb 8 17:08 11 dr-xr-xr-x 5 root root 0 Feb 8 17:08 1156 dr-xr-xr-x 5 root root 0 Feb 8 17:08 139 dr-xr-xr-x 5 root root 0 Feb 8 17:08 140 dr-xr-xr-x 5 root root 0 Feb 8 17:08 141 dr-xr-xr-x 5 root root 0 Feb 8 17:09 1417 dr-xr-xr-x 5 root root 0 Feb 8 17:09 1418 |
[root@rhel5 ~]# ll /proc/2674 total 0 dr-xr-xr-x 2 root root 0 Feb 8 17:15 attr -r-------- 1 root root 0 Feb 8 17:14 auxv -r--r--r-- 1 root root 0 Feb 8 17:09 cmdline -rw-r--r-- 1 root root 0 Feb 8 17:14 coredump_filter -r--r--r-- 1 root root 0 Feb 8 17:14 cpuset lrwxrwxrwx 1 root root 0 Feb 8 17:14 cwd -> /var/run/saslauthd -r-------- 1 root root 0 Feb 8 17:14 environ lrwxrwxrwx 1 root root 0 Feb 8 17:09 exe -> /usr/sbin/saslauthd dr-x------ 2 root root 0 Feb 8 17:15 fd -r-------- 1 root root 0 Feb 8 17:14 limits -rw-r--r-- 1 root root 0 Feb 8 17:14 loginuid -r--r--r-- 1 root root 0 Feb 8 17:14 maps -rw------- 1 root root 0 Feb 8 17:14 mem -r--r--r-- 1 root root 0 Feb 8 17:14 mounts -r-------- 1 root root 0 Feb 8 17:14 mountstats -rw-r--r-- 1 root root 0 Feb 8 17:14 oom_adj -r--r--r-- 1 root root 0 Feb 8 17:14 oom_score lrwxrwxrwx 1 root root 0 Feb 8 17:14 root -> / -r--r--r-- 1 root root 0 Feb 8 17:14 schedstat -r-------- 1 root root 0 Feb 8 17:14 smaps -r--r--r-- 1 root root 0 Feb 8 17:09 stat -r--r--r-- 1 root root 0 Feb 8 17:14 statm -r--r--r-- 1 root root 0 Feb 8 17:10 status dr-xr-xr-x 3 root root 0 Feb 8 17:15 task -r--r--r-- 1 root root 0 Feb 8 17:14 wchan |
[root@rhel5 ~]# more /proc/2674/cmdline /usr/sbin/saslauthd |
[root@rhel5 ~]# more /proc/2674/environ TERM=linuxauthd |
[root@rhel5 ~]# ll /proc/2674/fd total 0 lrwx------ 1 root root 64 Feb 8 17:17 0 -> /dev/null lrwx------ 1 root root 64 Feb 8 17:17 1 -> /dev/null lrwx------ 1 root root 64 Feb 8 17:17 2 -> /dev/null lrwx------ 1 root root 64 Feb 8 17:17 3 -> socket:[7990] lrwx------ 1 root root 64 Feb 8 17:17 4 -> /var/run/saslauthd/saslauthd.pid lrwx------ 1 root root 64 Feb 8 17:17 5 -> socket:[7991] lrwx------ 1 root root 64 Feb 8 17:17 6 -> /var/run/saslauthd/mux.accept |
[root@rhel5 ~]# cat /proc/2674/maps 00110000-00239000 r-xp 00000000 08:02 130647 /lib/libcrypto.so.0.9.8e 00239000-0024c000 rwxp 00129000 08:02 130647 /lib/libcrypto.so.0.9.8e 0024c000-00250000 rwxp 0024c000 00:00 0 00250000-00252000 r-xp 00000000 08:02 130462 /lib/libdl-2.5.so 00252000-00253000 r-xp 00001000 08:02 130462 /lib/libdl-2.5.so |
[root@rhel5 ~]# more /proc/2674/status Name: saslauthd State: S (sleeping) SleepAVG: 0% Tgid: 2674 Pid: 2674 PPid: 1 TracerPid: 0 Uid: 0 0 0 0 Gid: 0 0 0 0 FDSize: 32 Groups: VmPeak: 5576 kB VmSize: 5572 kB VmLck: 0 kB VmHWM: 696 kB VmRSS: 696 kB ………… |
[root@rhel5 ~]# more /proc/cmdline ro root=/dev/VolGroup00/LogVol00 rhgb quiet |
[root@rhel5 ~]# more /proc/crypto name : crc32c driver : crc32c-generic module : kernel priority : 0 type : digest blocksize : 32 digestsize : 4 ………… |
[root@rhel5 ~]# more /proc/devices Character devices: 1 mem 4 /dev/vc/0 4 tty 4 ttyS ………… Block devices: 1 ramdisk 2 fd 8 sd ………… |
[root@rhel5 ~]# more /proc/dma 2: floppy 4: cascade |
[root@rhel5 ~]# more /proc/execdomains 0-0 Linux [kernel] |
[root@rhel5 ~]# more /proc/filesystems nodev sysfs nodev rootfs nodev proc iso9660 ext3 ………… ………… |
[root@rhel5 ~]# more /proc/interrupts CPU0 0: 1305421 IO-APIC-edge timer 1: 61 IO-APIC-edge i8042 185: 1068 IO-APIC-level eth0 ………… |
[root@rhel5 ~]# more /proc/iomem 00000000-0009f7ff : System RAM 0009f800-0009ffff : reserved 000a0000-000bffff : Video RAM area 000c0000-000c7fff : Video ROM ………… |
3.2.12. /proc/iomem
This file shows you the current map of the system's memory for each physical device:
00000000-0009fbff : System RAM0009fc00-0009ffff : reserved 000a0000-000bffff : Video RAM area000c0000-000c7fff : Video ROM 000f0000-000fffff : System ROM00100000-07ffffff : System RAM 00100000-00291ba8 : Kernel code00291ba9-002e09cb : Kernel data e0000000-e3ffffff : VIA Technologies, Inc. VT82C597 [Apollo VP3] e4000000-e7ffffff : PCI Bus #01 e4000000-e4003fff : Matrox Graphics, Inc. MGA G200 AGP e5000000-e57fffff : Matrox Graphics, Inc. MGA G200 AGP e8000000-e8ffffff : PCI Bus #01 e8000000-e8ffffff : Matrox Graphics, Inc. MGA G200 AGP ea000000-ea00007f : Digital Equipment Corporation DECchip 21140 [FasterNet]ea000000-ea00007f : tulip ffff0000-ffffffff : reserved
The first column displays the memory registers used by each of the different types of memory. The second column lists the kind of memory located within those registers and displays which memory registers are used by the kernel within the system RAM or, if the network interface card has multiple Ethernet ports, the memory registers assigned for each port.
/opt/qtmarvell/mvqt # cat /proc/iomem
00000000-0fffffff : System RAM 0002b000-00554fff : Kernel text 00556000-005a22f3 : Kernel data 10000000-1fffffff : System RAM e0000000-e7ffffff : PEX0 Memory e0000000-e0003fff : 0000:00:01.0 e0004000-e0004fff : 0000:00:01.0 e8000000-efffffff : PEX1 Memory f1012100-f10121ff : serial8250.0 f1012100-f101211f : serial f1090000-f10903ff : mvsdio f1090000-f10903ff : mvsdio f10a0000-f10a3fff : mv88fx_snd.0 f10a0000-f10a3fff : mv88fx_snd f10c0000-f10d0000 : dovefb.0 寄存器地址映射到这个 f10c0000-f10d0000 : dovefb_ovly.0
/opt/qtmarvell/mvqt # ./framebuffer
The framebuffer device was opened successfully.Fixed screen info:
id: GFX Layer 0 smem_start: 0x12000000 smem_len: 33554432 type: 0 type_aux: 0 visual: 2 xpanstep: 1 ypanstep: 1 ywrapstep: 0 line_length: 2560 mmio_start: 0xf10c0000 mmio_len: 65537[root@rhel5 ~]# less /proc/ioports 0000-001f : dma1 0020-0021 : pic1 0040-0043 : timer0 0050-0053 : timer1 0060-006f : keyboard ………… |
[root@rhel5 ~]# more /proc/kallsyms c04011f0 T _stext c04011f0 t run_init_process c04011f0 T stext ………… |
[root@rhel5 ~]# more /proc/loadavg 0.45 0.12 0.04 4/125 5549 [root@rhel5 ~]# uptime 06:00:54 up 1:06, 3 users, load average: 0.45, 0.12, 0.04 |
[root@rhel5 ~]# more /proc/locks 1: POSIX ADVISORY WRITE 4904 fd:00:4325393 0 EOF 2: POSIX ADVISORY WRITE 4550 fd:00:2066539 0 EOF 3: FLOCK ADVISORY WRITE 4497 fd:00:2066533 0 EOF |
[root@rhel5 ~]# less /proc/mdstat Personalities : unused devices: <none> |
[root@rhel5 ~]# less /proc/meminfo MemTotal: 515492 kB MemFree: 8452 kB Buffers: 19724 kB Cached: 376400 kB SwapCached: 4 kB ………… |
[root@rhel5 ~]# ll /proc |grep mounts lrwxrwxrwx 1 root root 11 Feb 8 06:43 mounts -> self/mounts |
[root@rhel5 ~]# more /proc/mounts rootfs / rootfs rw 0 0 /dev/root / ext3 rw,data=ordered 0 0 /dev /dev tmpfs rw 0 0 /proc /proc proc rw 0 0 /sys /sys sysfs rw 0 0 /proc/bus/usb /proc/bus/usb usbfs rw 0 0 ………… |
[root@rhel5 ~]# more /proc/modules autofs4 24517 2 - Live 0xe09f7000 hidp 23105 2 - Live 0xe0a06000 rfcomm 42457 0 - Live 0xe0ab3000 l2cap 29505 10 hidp,rfcomm, Live 0xe0aaa000 ………… |
[root@rhel5 ~]# more /proc/partitions major minor #blocks name 8 0 20971520 sda 8 1 104391 sda1 8 2 6907950 sda2 8 3 5630782 sda3 8 4 1 sda4 8 5 3582463 sda5 |
[root@rhel5 ~]# more /proc/slabinfo slabinfo - version: 2.1 # name <active_objs> <num_objs> <objsize> <objperslab> <pagesperslab> : tunables <limit> <batchcount> <sharedfactor> : slabdata <ac tive_slabs> <num_slabs> <sharedavail> rpc_buffers 8 8 2048 2 1 : tunables 24 12 8 : slabdata 4 4 0 rpc_tasks 8 20 192 20 1 : tunables 120 60 8 : slabdata 1 1 0 rpc_inode_cache 6 9 448 9 1 : tunables 54 27 8 : slabdata 1 1 0 ………… ………… ………… |
[root@rhel5 ~]# more /proc/stat cpu 2751 26 5771 266413 2555 99 411 0 cpu0 2751 26 5771 266413 2555 99 411 0 intr 2810179 2780489 67 0 3 3 0 5 0 1 0 0 0 1707 0 0 9620 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 5504 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 12781 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ctxt 427300 btime 1234084100 processes 3491 procs_running 1 procs_blocked 0 |
[root@rhel5 ~]# more /proc/swaps Filename Type Size Used Priority /dev/sda8 partition 642560 0 -1 |
[root@rhel5 ~]# more /proc/uptime 3809.86 3714.13 |
[root@rhel5 ~]# more /proc/version Linux version 2.6.18-128.el5 (mockbuild@hs20-bc1-5.build.redhat.com) (gcc version 4.1.2 20080704 (Red Hat 4.1.2-44)) #1 SMP Wed Dec 17 11:42:39 EST 2008 |
[root@rhel5 ~]# more /proc/vmstat nr_anon_pages 22270 nr_mapped 8542 nr_file_pages 47706 nr_slab 4720 nr_page_table_pages 897 nr_dirty 21 nr_writeback 0 ………… |
[root@rhel5 ~]# more /proc/zoneinfo Node 0, zone DMA pages free 1208 min 28 low 35 high 42 active 439 inactive 1139 scanned 0 (a: 7 i: 30) spanned 4096 present 4096 nr_anon_pages 192 nr_mapped 141 nr_file_pages 1385 nr_slab 253 nr_page_table_pages 2 nr_dirty 523 nr_writeback 0 nr_unstable 0 nr_bounce 0 protection: (0, 0, 296, 296) pagesets all_unreclaimable: 0 prev_priority: 12 start_pfn: 0 ………… |
Linux内核通信之---proc文件系统
使用 /proc 文件系统来访问 Linux 内核的内容,这个虚拟文件系统在内核空间和用户空间之间打开了一个通信窗口:
/proc 文件系统是一个虚拟文件系统,通过它可以使用一种新的方法在 Linux内核空间和用户间之间进行通信。在 /proc 文件系统中,我们可以将对虚拟文件的读写作为与内核中实体进行通信的一种手段,但是与普通文件不同的是,这些虚拟文件的内容都是动态创建的。本文对 /proc 虚拟文件系统进行了介绍,并展示了它的用法。
最初开发 /proc 文件系统是为了提供有关系统中进程的信息。但是由于这个文件系统非常有用,因此内核中的很多元素也开始使用它来报告信息,或启用动态运行时配置。清单 1 是对 /proc 中部分元素进行一次交互查询的结果。它显示的是 /proc 文件系统的根目录中的内容。注意,在左边是一系列数字编号的文件。每个实际上都是一个目录,表示系统中的一个进程。由于在 GNU/Linux 中创建的第一个进程是 init
进程,因此它的 process-id
为 1。然后对这个目录执行一个 ls
命令,这会显示很多文件。每个文件都提供了有关这个特殊进程的详细信息。/proc 中另外一些有趣的文件有:cpuinfo
,它标识了处理器的类型和速度;pci
,显示在 PCI 总线上找到的设备;modules
,标识了当前加载到内核中的模块。
另外,我们还可以使用 sysctl
来配置这些内核条目。/proc 文件系统并不是 GNU/Linux 系统中的惟一一个虚拟文件系统。在这种系统上,sysfs 是一个与 /proc 类似的文件系统,但是它的组织更好(从 /proc 中学习了很多教训)。不过 /proc 已经确立了自己的地位,因此即使 sysfs 与 /proc 相比有一些优点,/proc 也依然会存在。还有一个 debugfs 文件系统,不过(顾名思义)它提供的更多是调试接口。debugfs 的一个优点是它将一个值导出给用户空间非常简单(实际上这不过是一个调用而已)。
这些文件的解释和意义如下:
cmdline:系统启动时输入给内核命令行参数 cpuinfo:CPU的硬件信息 (型号, 家族, 缓存大小等) devices:主设备号及设备组的列表,当前加载的各种设备(块设备/字符设备) dma:使用的DMA通道 filesystems:当前内核支持的文件系统,当没有给 mount(1) 指明哪个文件系统的时候, mount(1) 就依靠该文件遍历不同的文件系统 interrupts :中断的使用及触发次数,调试中断时很有用 ioports I/O:当前在用的已注册 I/O 端口范围 kcore:该伪文件以 core 文件格式给出了系统的物理内存映象(比较有用),可以用 GDB 查探当前内核的任意数据结构。该文件的总长度是物理内存 (RAM) 的大小再加上 4KB kmsg:可以用该文件取代系统调用 syslog(2) 来记录内核日志信息,对应dmesg命令 kallsym:内核符号表,该文件保存了内核输出的符号定义, modules(X)使用该文件动态地连接和捆绑可装载的模块 loadavg:负载均衡,平均负载数给出了在过去的 1、 5,、15 分钟里在运行队列里的任务数、总作业数以及正在运行的作业总数。 locks:内核锁 。 meminfo物理内存、交换空间等的信息,系统内存占用情况,对应df命令。 misc:杂项 。 modules:已经加载的模块列表,对应lsmod命令 。 mounts:已加载的文件系统的列表,对应mount命令,无参数。 partitions:系统识别的分区表 。 slabinfo:sla池信息。 stat:全面统计状态表,CPU内存的利用率等都是从这里提取数据。对应ps命令。 swaps:对换空间的利用情况。 version:指明了当前正在运行的内核版本。 |
可加载内核模块(LKM)是用来展示 /proc 文件系统的一种简单方法,这是因为这是一种用来动态地向 Linux 内核添加或删除代码的新方法。LKM 也是 Linux 内核中为设备驱动程序和文件系统使用的一种流行机制。如果你曾经重新编译过 Linux 内核,就可能会发现在内核的配置过程中,有很多设备驱动程序和其他内核元素都被编译成了模块。如果一个驱动程序被直接编译到了内核中,那么即使这个驱动程序没有运行,它的代码和静态数据也会占据一部分空间。但是如果这个驱动程序被编译成一个模块,就只有在需要内存并将其加载到内核时才会真正占用内存空间。
集成到 /proc 文件系统中
内核程序员可以使用的标准 API,LKM 程序员也可以使用。
方法一:(create_proc_entry创建proc文件)
1.1 .创建目录:
- struct proc_dir_entry *proc_mkdir(const char *name,
- struct proc_dir_entry *parent);
1.2 .创建proc文件:
- struct proc_dir_entry *create_proc_entry( const char *name, mode_t mode,
- struct proc_dir_entry *parent );
create_proc_entry函数用于创建一个一般的proc文件,其中name是文件名,比如“hello”,mode是文件模式,parent是要创建的proc文件的父目录(若parent = NULL则创建在/proc目录下)。create_proc_entry
的返回值是一个 proc_dir_entry
指针(或者为 NULL,说明在 create
时发生了错误)。然后就可以使用这个返回的指针来配置这个虚拟文件的其他参数,例如在对该文件执行读操作时应该调用的函数。
- struct proc_dir_entry {
- ......
- const struct file_operations *proc_fops; <==文件操作结构体
- struct proc_dir_entry *next, *parent, *subdir;
- void *data;
- read_proc_t *read_proc; <==读回调
- write_proc_t *write_proc; <==写回调
- ......
- };
1.3 .删除proc文件/目录:
- void remove_dir_entry(const char *name, struct proc_dir_entry *parent);
要从 /proc 中删除一个文件,可以使用 remove_proc_entry
函数。要使用这个函数,我们需要提供文件名字符串,以及这个文件在 /proc 文件系统中的位置(parent)。
3、proc文件读回调函数
static int (*proc_read)(char *page, char **start, off_t off, int count, int *eof, void *data);
4、proc文件写回调函数
static int proc_write_foobar(struct file *file, const char *buffer, unsigned long count, void *data);
proc文件实际上是一个叫做proc_dir_entry的struct(定义在proc_fs.h),该struct中有int read_proc和int write_proc两个元素,要实现proc的文件的读写就要给这两个元素赋值。但这里不是简单地将一个整数赋值过去就行了,需要实现两个回调函数。在用户或应用程序访问该proc文件时,就会调用这个函数,实现这个函数时只需将想要让用户看到的内容放入page即可。在用户或应用程序试图写入该proc文件时,就会调用这个函数,实现这个函数时需要接收用户写入的数据(buff参数)。
写回调函数
我们可以使用 write_proc
函数向 /proc 中写入一项。这个函数的原型如下:
int mod_write( struct file *filp, const char __user *buff, unsigned long len, void *data );
filp
参数实际上是一个打开文件结构(我们可以忽略这个参数)。buff
参数是传递给您的字符串数据。缓冲区地址实际上是一个用户空间的缓冲区,因此我们不能直接读取它。len
参数定义了在 buff
中有多少数据要被写入。data
参数是一个指向私有数据的指针。在这个模块中,我们声明了一个这种类型的函数来处理到达的数据。
Linux 提供了一组 API 来在用户空间和内核空间之间移动数据。对于 write_proc
的情况来说,我们使用了 copy_from_user
函数来维护用户空间的数据。
读回调函数
我们可以使用 read_proc
函数从一个 /proc 项中读取数据(从内核空间到用户空间)。这个函数的原型如下:
int mod_read( char *page, char **start, off_t off, int count, int *eof, void *data );
page
参数是这些数据写入到的位置,其中 count
定义了可以写入的最大字符数。在返回多页数据(通常一页是 4KB)时,我们需要使用 start
和 off
参数。当所有数据全部写入之后,就需要设置 eof
(文件结束参数)。与 write
类似,data
表示的也是私有数据。此处提供的 page
缓冲区在内核空间中。因此,我们可以直接写入,而不用调用 copy_to_user
。
实例代码:
-
- #include <linux/module.h>
- #include <linux/kernel.h>
- #include <linux/init.h>
- #include <linux/proc_fs.h>
- #include <linux/jiffies.h>
- #include <asm/uaccess.h>
- #define MODULE_VERS "1.0"
- #define MODULE_NAME "procfs_example"
- #define FOOBAR_LEN 8
- struct fb_data_t {
- char name[FOOBAR_LEN + 1];
- char value[FOOBAR_LEN + 1];
- };
- static struct proc_dir_entry *example_dir, *foo_file;
- struct fb_data_t foo_data;
- static int proc_read_foobar(char *page, char **start,
- off_t off, int count,
- int *eof, void *data)
- {
- int len;
- struct fb_data_t *fb_data = (struct fb_data_t *)data;
- /* DON'T DO THAT - buffer overruns are bad */
- len = sprintf(page, "%s = '%s'\n",
- fb_data->name, fb_data->value);
- return len;
- }
- static int proc_write_foobar(struct file *file,
- const char *buffer,
- unsigned long count,
- void *data)
- {
- int len;
- struct fb_data_t *fb_data = (struct fb_data_t *)data;
- if(count > FOOBAR_LEN)
- len = FOOBAR_LEN;
- else
- len = count;
- if(copy_from_user(fb_data->name, buffer, len))
- return -EFAULT;
- fb_data->value[len] = '\0';
- return len;
- }
- static int __init init_procfs_example(void)
- {
- int rv = 0;
- /* create directory */
- example_dir = proc_mkdir(MODULE_NAME, NULL);
- if(example_dir == NULL) {
- rv = -ENOMEM;
- goto out;
- }
- /* create foo and bar files using same callback
- * functions
- */
- foo_file = create_proc_entry("foo", 0644, example_dir);
- if(foo_file == NULL) {
- rv = -ENOMEM;
- goto no_foo;
- }
- strcpy(foo_data.name, "foo");
- strcpy(foo_data.value, "foo");
- foo_file->data = &foo_data;
- foo_file->read_proc = proc_read_foobar;
- foo_file->write_proc = proc_write_foobar;
- /* everything OK */
- printk(KERN_INFO "%s %s initialised\n",
- MODULE_NAME, MODULE_VERS);
- return 0;
- no_foo:
- remove_proc_entry("jiffies", example_dir);
- out:
- return rv;
- }
- static void __exit cleanup_procfs_example(void)
- {
- remove_proc_entry("foo", example_dir);
- remove_proc_entry(MODULE_NAME, NULL);
- printk(KERN_INFO "%s %s removed\n",
- MODULE_NAME, MODULE_VERS);
- }
- module_init(init_procfs_example);
- module_exit(cleanup_procfs_example);
- MODULE_AUTHOR("Erik Mouw");
- MODULE_DESCRIPTION("procfs examples");
- MODULE_LICENSE("GPL");