CSDN博客

img collide

The proc File System:

发表于2004/10/6 13:01:00  1670人阅读

分类: Linux 内核研究

The proc File System:
 在这篇摘抄的文章里,我们主要介绍一下此文件系统是如何工作的,以及现有的网络代码是如何使用这个文件系统的,以及我们在程序

中如何写,使用proc entry。

Overview:
 proc文件系统在很多程序中被频繁的使用,尽管它被设计成像其它文件系统那样有目录结构和inode,但事实上,是一些注册了的函数

,它们提供了重要的系统变量的信息。
 proc目录有很多的子目录-每一个运行中的进程一个以及一些关于子系统的,如文件系统,接口,终端,网络(/proc/net)。在

/proc主目录中也有许多的文件-interrupts,ioports,loadavg等等。在每个进程的子目录中的文件描述此进程的一些信息,如command

line, current working directory, status等等。
 内核监视所有对proc文件系统的访问,用特殊的函数来替代普通的文件操作函数。当一个在/proc目录下的文件被创建时,它向内核注

册一些函数来告诉内核如果本文件被读或者写的话,应该如何操作。许多的file只允许读操作,向控制台打印一些状态信息而已。
 需要注意的一点是:内核在每次读操作时,呼叫产生状态信息的函数,因此如果没有一次读完的情况下,接下来的读操作可能会覆盖原

有的信息,所以我们最好一次读完状态信息,最好的方法是提供一个大的缓冲区,如PAGE_SIZE字节大小最好,可以一次读完。


Network proc Files:
 arp 显示neighbor table(arp_tbl);ip地址/硬件地址,硬件类型,设备,标志等。(arp_get_info():net/ipv4/arp.c)
 dev 显示每个注册了的设备的统计信息。
 dev_stat 显示接收到/丢弃的包的数量以及FASTROUTE统计信息(dev_proc_stats():net/core/dev.c)
 netstat display sync cookie, pruning, and ICMP statistics(netstat_get_info():net/ipv4/proc.c)
 raw 为每一个已经打开的原始套接字根据struct proto raw_prot来显示地址,队列以及超时信息。(

get_netinfo():net/ipv4/proc.c)
 route 显示FIB表(main_table),the interface, address, gateway, flags, and usage information

(fib_get_procinfo()):net/ipv4/fib_frontend.c)
 rt_cache 显示routing cache(rt_hash_table), the interface, address, gateway, usage,source, and other

infomation. (rt_cache_get_info() : net/ipv4/route.c)
 sockstat display number of sockets that have been used and some statistics on how many were TCP, UDP,

and RAW(afinet_get_info() : net/ipv4/proc.c)
 tcp display address, queue, and timeout information for each open TCP socket form struct proto tcp_prot

(get__netinfo() : net/ipv4/proc.c)
 udp display address, queue, and timeout information for each open UDP socket form struct proto udp_prot

(get__netinfo() : net/ipv4/proc.c)
 
注册proc文件:
 这段中我们介绍一个最简单的注册只读proc文件的方法(只适合linux 2.0及其以后的版本),我们可以通过实现file_operations

和inode_operations结构来使它具有更多的功能。但是后者比我们提到的第一种方法复杂,可以看看源代码来得知后者如何实现。下面提及的

方法:定义一个函数,然后registering/unregisteriing这个函数到内核中,提供了绝大多数测试、跟踪系统资源的方法。但要注意:只有

内核能注册proc文件,用户可以创建/安装内核模块(root用户身份)。下面的过程假设已经安装上了linux源代码,并且内核被编译成允许使

用模块。

格式化提供信息的函数(Formatting a Function to Provide Information)
 static int read_proc_function(char *buf, char **start, off_t offset, int len, int unused)
 以上是linux内核在它读proc文件时要调用的函数原型。其中最重要的一个参数时buf,一个指向缓冲区的指针,供内核储存输出的信

息。其它的参数一般不会改变。
 一般来说,这个函数打印一个头部(header),然后遍历表,打印出它的内容(使用sprintf),并返回结果字符串的长度,唯一的限

制是buf不能超过PAGE_SIZE大小(PAGE_SIZE最小是4kb)。

创建proc条目:
 因为是文件系统的一部分,所以这个entry需要一个inode,可以使用proc_dir_entry结构来搞定。

 #include <linux/proc_fs.h>
 struct proc_dir_entry new_proc_entry = {
  0,   // low_ino - inode number (0 for dynamic)
  5,   // namelen - length of entry name
  "entry",  // name
  S_IFREG | S_IRUGO // mode
  1,   // nlinks
  0,   // uid - owner
  0,   // gid - group
  0,   // size - not used
  NULL,    // ops - inode operations (use default)
  &read_proc_function // read_proc - address of read function
     // leave rest blank!
 }
 
 以上得我们可以复用,只需要改改name, namelen和read_proc字段就可以了。不过内核定义了许多得条目,使用它们自己得inode

number(如PROC_NET_ROUTE),注意不要与之冲突。(在include/linux/proc_fs.h)
 
注册一个proc条目:
 int proc_register(struct proc_dir_entry *dir, struct proc_dir_entry *entry)
 int proc_net_register(struct proc_dir_entry *entry)
 dir指向一个entry所属的目录-&proc_root和proc_net(include/proc_fs.h)可能是最有用的。entry是指向自己的指针,以上

两个函数是相同的,除了第二个使用proc/net做为目录。返回0(成功)或者EAGAIN(没有可利用的inode)。

卸载一个proc条目:
 int proc_unregister(struct proc_dir_entry *dir, int inode)
 int proc_net_unregister(int inode)
 dir是文件(条目)驻留的目录,inode是此文件的inode编号(proc_dir_entry.low_ino),第二个函数使用/proc/net目录。返

回0(成功)或者EAGAIN(没有可利用的inode)。

例子:
 simple_entry.c
 
 /* simple_entry.c
  *
  * This program provides an example of how to install an entry into the
  *  /proc File System. All this entry does is display some statistical
  *  information about IP.
         */

 #define MODULE
 #include <linux/module.h>
 /* proc_fs.h contains proc_dir_entry and register/unregister prototypes */
 #include <linux/proc_fs.h>
 /* ip.h contains the ip_statistics variable */
 #include <net/ip.h>

 /* show_ip_stats
  * this function is what the /proc FS will call when anything tries to read
  * from the file /proc/simple_entry - it puts some of the kernel global
  * variable ip_statistics's contents into the return buffer
  */
 int
 show_ip_stats(char *buf, char **start, off_t offset, int len, int unused)
 {
  len = sprintf(buf, "Some IP Statistics:/nIP Forwarding is ");
  if( ip_statistics.IpForwarding )
   len += sprintf(buf+len, "on/n");
  else
   len += sprintf(buf+len, "off/n");
  len += sprintf(buf+len, "Default TTL: %lu/n", ip_statistics.IpDefaultTTL);
  len += sprintf(buf+len, "Frag Creates: %lu/n", ip_statistics.IpFragCreates);
  /* this could show more... */
  return len;
 } /* show_ip_stats */






阅读全文
0 0

相关文章推荐

img
取 消
img