在 src/Documentation/filesystems/proc.txt,有关 proc.txt的介绍

资料:

在linux系统中,伪文件系统是系统中重要的组成部分,它与普通文件的最大差别在于它的易失性。普通文件都有固定的存储介质,而伪文件系统则存储在内存中,这也使得伪文件系统在系统掉电后,它保存的内容就会挥发掉。

Linux系统中存在以下几类伪文件系统:
1.procfs:proc提供内核和用户交互的平台,由于其文件格式是ASCII,所以用户可以使用cat,vim,echo等命令查看或修改文件,当然必须在root用户下才有相应权限。
在系统中增设了了一个/proc目录,每当创建一个进程时就以pid为目录名在这个目录下建立起一个特殊文件,使得通过这个文件就可以读写相应进程的用户空间。而当进程exit()时则将这个进程文件删除。称为 伪文件系统
     
2.sysfs:与procfs类似,由于出现的比较晚,所以它克服了proc的一些缺点,比proc功能更强大。但是由于其文件格式是二进制形式,所以需要特殊工具。该文件系统主要为开发人员提供。
3.其它伪文件系统如:libfs,debugfs等。
     在这些文件系统中,proc出现比较早,其实现也很典型。proc最初的设计目的是提供内核和用户交互的平台,使用户可以动态的管理系统,同时获取系统的运行时的信息。在proc中主要的信息便是系统进程信息。

proc_fs.h头文件 src/include/linux/proc_fs.h 

在 proc_dir_entry结构体中,定义如下:
  1. 51struct proc_dir_entry {
  2.   52 unsigned int low_ino;
  3.   53 unsigned short namelen;
  4.   54 const char *name;
  5.   55 mode_t mode; // 0444
  6.   56 nlink_t nlink;
  7.   57 uid_t uid;
  8.   58 gid_t gid;
  9.   59 loff_t size;
  10.   60 const struct inode_operations *proc_iops;
  11.   61 /*
  12.   62 * NULL ->proc_fops means "PDE is going away RSN" or
  13.   63 * "PDE is just created". In either case, e.g. ->read_proc won't be
  14.   64 * called because it's too late or too early, respectively.
  15.   65 *
  16.   66 * If you're allocating ->proc_fops dynamically, save a pointer
  17.   67 * somewhere.
  18.   68 */
  19.   69 const struct file_operations *proc_fops;
  20.   70 struct proc_dir_entry *next, *parent, *subdir;
  21.   71 void *data;
  22.   72 read_proc_t *read_proc; //实现接口函数
  23.   73 write_proc_t *write_proc;
  24.   74 atomic_t count; /* use count */
  25.   75 int pde_users; /* number of callers into module in progress */
  26.   76 spinlock_t pde_unload_lock; /* proc_fops checks and pde_users bumps */
  27.   77 struct completion *pde_unload_completion;
  28.   78 struct list_head pde_openers; /* who did ->open, but not ->release */
  29.   79};

1.建立目录proc_mkdir
  1. 148 extern struct proc_dir_entry *proc_mkdir(const char *,struct proc_dir_entry *);
struct proc_dir_entry *:=NULL, 在/proc下新建目录
                         !=NULL, 表示上级目录
  1. mydir = proc_mkdir("mydir", NULL);///proc目录下新建mydir目录

2.建立文件create_proc_entry()
  1. 109extern struct proc_dir_entry *create_proc_entry(const char *name, mode_t mode,
  2.  110 struct proc_dir_entry *parent);
const char *name :文件名称
mode_t mode: 文件权限值 0666 mode_t内核文件权限值
struct proc_dir_entry:若 parent=mydir,在../mydidr/新建文件
                      若 parent=null, 在 /proc/下 新建文件
  1. pfile = create_proc_entry("pool", 0666, mydir);/proc/mydir/下新建pool文件
3.移除目录或文件remove_proc_entry
  1. 115 extern void remove_proc_entry(const char *name, struct proc_dir_entry *parent);
const char *name: 要移除的目录或文件的名称
struct proc_dir_entry *parent: 若parent=null,在/proc/删除 目录
                               若parent!=NULL,删除 ../proc/parent 文件
  1. remove_proc_entry("pool", mydir); //删除/proc/mydir/下的 pool文件
  2. remove_proc_entry("mydir",NULL);//删除 /proc/下的mydir目录

我们可以通过cat和echo等文件操作函数来查看和设置这些proc文件。
4.实现proc_dir_entry结构体中 *read_proc函数
  1. 46typedef int (read_proc_t)(char *page, char **start, off_t off, int count, int *eof, void *data);
  1. static int myproc_read(char *page, char **start, off_t off, int count, int *eof, void *data)
  2. {
  3.         int len = strlen(msg);
  4.         if(off >= len)
  5.                 return 0;

  6.         if (count>len-off)
  7.                 count = len - off;

  8.         memcpy(page + off, msg + off, count);
  9.         return off + count;
  10. }

5. 实现proc_dir_entry中 *proc_write函数
  1. 48typedef int (write_proc_t)(struct file *file, const char __user *buffer, unsigned long count, void *data);
  1. static int myproc_write(struct file *file, const char __user *buffer, unsigned long count, void *data)
  2. {
  3.         unsigned long count2 = count;
  4.         if(count2 >= sizeof(msg))
  5.                 count2 = sizeof(msg) - 1;

  6.         if (copy_from_user(msg, buffer, count2))
  7.                 return -EFAULT;

  8.         msg[count2] = '\0';
  9.         return count;
  10. }

例子:
这个例子创建一个 /proc/mydir/pool,它相当于一个池子,你向它写什么,你读它的时候它就返回什么,当然它的容量是有限的 :)
附件代码: proc_fs.h头文件 API 程序实现-LMLPHP pool.rar   将rar修改为tar.bz2
  1. #include <linux/module.h>
  2. #include <linux/init.h>
  3. #include <linux/kernel.h>

  4. #include <linux/proc_fs.h>
  5. #include <asm/uaccess.h>

  6. MODULE_LICENSE("GPL");

  7. static struct proc_dir_entry *mydir;
  8. static struct proc_dir_entry *pfile;

  9. static char msg[255];

  10. static int myproc_read(char *page, char **start, off_t off, int count, int *eof, void *data)
  11. {
  12.     int len = strlen(msg);
  13.     if(off >= len)
  14.         return 0;
  15.         
  16.     if (count>len-off)
  17.         count = len - off;
  18.         
  19.     memcpy(page + off, msg + off, count);
  20.     return off + count;
  21. }

  22. static int myproc_write(struct file *file, const char __user *buffer, unsigned long count, void *data)
  23. {
  24.     unsigned long count2 = count;
  25.     if(count2 >= sizeof(msg))
  26.         count2 = sizeof(msg) - 1;
  27.         
  28.     if (copy_from_user(msg, buffer, count2))
  29.         return -EFAULT;
  30.         
  31.     msg[count2] = '\0';
  32.     return count;
  33. }

  34. static int __init myproc_init(void)
  35. {
  36.     mydir = proc_mkdir("mydir", NULL);
  37.     if(!mydir)
  38. {
  39.         printk(KERN_ERR "Can't create /proc/mydir/n");
  40.         return -1;
  41.     }
  42.     pfile = create_proc_entry("pool", 0666, mydir);
  43.     if(!pfile)
  44.     {
  45.         printk(KERN_ERR "Can't create /proc/mydir/pool/n");
  46.         remove_proc_entry("mydir", NULL);
  47.         return -1;
  48.     }
  49.     pfile->read_proc = myproc_read;
  50.     pfile->write_proc = myproc_write;
  51.     printk("pool init\n");
  52.     return 0;
  53. }

  54. static void __exit myproc_exit(void)
  55. {
  56.     remove_proc_entry("pool", mydir);
  57.     remove_proc_entry("mydir", NULL);
  58.     printk("pool exit\n");
  59. }

  60. module_init(myproc_init);
  61. module_exit(myproc_exit);

  62. //MODULE_LICENSE("GPL");
  1. obj-m:=pool.o
  2. KERNELDIR := /lib/modules/2.6.35-31-generic/build
  3. PWD :=$(shell pwd)

  4. modules:
  5.         $(MAKE) -C $(KERNELDIR) M=$(PWD) modules

  6. modules_install:
  7.         $(MAKE) -C $(KERNELDIR) M=$(PWD) modules_install

  8. clean:
  9.         rm -rf *.o *.ko *.mod.c *.order *.symvers
  1. ywx@ywx:~/desktop/module/proc/pool$ sudo insmod ./pool.ko
  2. ywx@ywx:~/desktop/module/proc/pool$ echo "hello linux" > /proc/mydir/pool
  3. ywx@ywx:~/desktop/module/proc/pool$ cat /proc/mydir/pool
  4. hello linux
  5. ywx@ywx:~/desktop/module/proc/pool$ sudo rmmod pool



















































































































































01-04 02:32