学习ldd3--proc文件系统(第七章与第四章)

来源:互联网 发布:linux重命名文件的命令 编辑:程序博客网 时间:2024/05/19 05:33
作者:张伟AreS
/******************************************************************************/ 
  /proc文件系统,使用/proc的模块必须包含<linux/proc_fs.h>
  /proc文件系统是一种在用户态检查内核状态的机制。
  /proc文件子目录/文件名:apm高级电源管理信息,bus总线以及总线上的设备
                         devices可用的设备信息,driver已经启用的驱动
                         interrupts中断信息,ioports端口使用信息 version内核版本
  /proc特点:每个文件都规定严格的权限:可读,可写,哪个用户可读,哪个用户可写
             可以用文本编辑程序读取(more,cat,vi等待)                      
             不仅可以有文件,还可以有子目录
             可以自己编写程序添加一个/proc目录下的文件
             文件内容都是动态创建,并不存在于磁盘上
  一个/proc的文件的内核描述:
     struct proc_dir_entry{
     ...
     read_proc_t *read_proc;
     write_proc_t *write_proc;
     ...
     ...
     };
  创建一个proc文件:
     struct proc_dir_entry *creat_proc_entry(const char *name,mode_t mode,struct proc_dir_entry *parent);
     参数:name:要创建的文件名
           mode:要创建的文件的属性,默认是0755
           parent:这个文件的父目录  
  创建一个/proc目录:
     struct proc_dir_entry *proc_mkdir(const char *name,struct proc_dir_entry *parent)
     参数:name:要创建的目录名
           parent:这个目录的父目录
  删除一个/proc目录或文件:
     void remove_proc_entry(const char *name,
          struct proc_dir_entry *parent)
     参数:name:要删除的目录名
           parent:所在的父目录
  
   读写:为让用户读写所添加的proc文件,需要挂接读写回调函数:
   read_proc,write_proc
   读操作:
     int (*read_proc)(char *page,char **start,off_t offset,int count, int *eof,void *data);       
     参数:
          page:把要返回给用户的信息写在page里,最大不能超过PAGE_SIZE
          start:函数应使用start返回实际的数据写到内存页的哪个位置,一般不适用
          offset:偏移量,从文件哪开始读
          count;用户要读取的字节数
          eof:读到文件尾时,需要把*eof置1
          data:一般不使用
   写操作:
     int (*write_proc)(struct file *file,const char *buff,unsigned long count,void *data);
      参数:
          file:该proc文件对应的file结构,一般忽略
          buffer:待写的数据所在的位置
          count:代写数据的大小
          data:一般不使用 
         
   实例:《国嵌 /proc文件系统》代码:D:\学习\国嵌视频\国嵌代码\4-5-2
#include <linux/module.h>
#include <linux/proc_fs.h>
#include <asm/uaccess.h>
static struct proc_dir_entry *mydir;
static struct proc_dir_entry *pfile;
static char msg[255];
static int myproc_read(char *page, char **start, off_t off, int count, int *eof, void *data)
{     //用户需要读取的数据被内核写在了char *page中
        int len = strlen(msg);
        if (off >= len)//文件中读取位置超过文件(在写操作中,msg被写入)大小
                return 0;
        if (count > len - off)
                count = len - off;
        memcpy(page + off, msg + off, count);//从msg+off处读取数据到page+off
        return off + count;
}
static int myproc_write(struct file *file, const char __user *buffer, unsigned long count, void *data)
{
        unsigned long count2 = count;//count是用户要写入的数据量,写入的数据保存在msg中
        if (count2 >= sizeof(msg))//写入的数据量超过msg容量,就限制
                count2 = sizeof(msg) - 1;
        if (copy_from_user(msg, buffer, count2))//数据在buff中,写入到msg中
                return -EFAULT;
        msg[count2] = '\0';
        return count;
}
static int __init myproc_init(void)//_init表明此函数在代码段的子段->初始化代码段,
                                   //此段中的函数运行一次之后,内存就会被回收
{
        mydir = proc_mkdir("mydir", NULL);
        if (!mydir) {
                printk(KERN_ERR "Can't create /proc/mydir\n");
                return -1;
        }
        pfile = create_proc_entry("pool", 0666, mydir);
        if (!pfile) {
                printk(KERN_ERR "Can't create /proc/mydir/pool\n");
                remove_proc_entry("mydir", NULL);
                return -1;
        }
        pfile->read_proc = myproc_read;
        pfile->write_proc = myproc_write;
        return 0;
}
static void __exit myproc_exit(void)
{
        remove_proc_entry("pool", mydir);
        remove_proc_entry("mydir", NULL);
}
module_init(myproc_init);
module_exit(myproc_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("David Xie");
      
LDD3第四章使用另一种创建/proc文件方法:使用creat_proc_read_entry创建/proc文件并与read_proc绑定起来:
   
  struct proc_dir_entry *creat_proc_read_entry(consr char *name,mode_t mode,struct proc_dir_entry *base,read_proc_t *read_proc,void *data);
      
    参数:name:要创建的文件名称
          mode:要创建的文件的属性  
          base:父目录
          read_proc:实现该文件的read_proc函数
          data:传递给read_proc的参数
实例:代码:ldd3的jit.c   (D:\学习\个人学习笔记及网络经典文章\学习LDD3笔记\ldd3_examples\misc-modules\jit.c)
int __init jit_init(void)
{
 create_proc_read_entry("currentime", 0, NULL, jit_currentime, NULL);
 
 create_proc_read_entry("jitbusy", 0, NULL, jit_fn, (void *)JIT_BUSY);
 create_proc_read_entry("jitsched",0, NULL, jit_fn, (void *)JIT_SCHED);
 create_proc_read_entry("jitqueue",0, NULL, jit_fn, (void *)JIT_QUEUE);
 create_proc_read_entry("jitschedto", 0, NULL, jit_fn, (void *)JIT_SCHEDTO);
 create_proc_read_entry("jitimer", 0, NULL, jit_timer, NULL);
 create_proc_read_entry("jitasklet", 0, NULL, jit_tasklet, NULL);
 create_proc_read_entry("jitasklethi", 0, NULL, jit_tasklet, (void *)1);
jit_init创建了8个/proc入口项,文件名、read_proc函数以及传递给read_proc函数的参数的如下:
  入口项的文件名             read_proc              传递给read_proc的参数                       
/proc/currentime          jit_currentime              NULL
/proc/jitbusy             jit_fn                      JIT_BUSY
/proc/jitsched            jit_fn                      JIT_SCHED
/proc/jitqueue            jit_fn                      JIT_QUEUE
/proc/jitschedto          jit_fn                      JIT_SCHEDTO
/proc/jitimer             jit_timer                   NULL
/proc/jitasklet           jit_tasklet                 NULL
/proc/jitasklethi         jit_tasklet                  1
/***************************************************************************************/