仪陇家园分类信息网、仪陇生活网、仪陇家园网

搜索

/proc 虚拟文件系统(实例)

[复制链接]
seo 发表于 2022-5-31 13:29:31 | 显示全部楼层 |阅读模式
/proc 虚拟文件系统(实例)发布时间:2022/5/31 13:16:01
            
                                                       
                                                       
            
        
        
               
                      Linux下有一个神奇的目录/proc,经常会运行 cat /proc/cpuinfo 命令查看cpu信息,/proc下的确有cpuinfo文件,但是这个文件不是物理存在的,是软件虚拟出来的,与普通文件不同,该文件是动态的。通过/proc可以实现用户态与内核态之间的通信。在内核模式下,可以很方便的创建/proc子目录,并进行读写操作,只不过此时你需要实现文件读写接口,因为内核不知道如何处理该文件。
   下面创建/proc/test目录,并新建log文件,进行读写操作。

一.系统API
extern struct proc_dir_entry proc_mkdir(const char *dir_name,struct proc_dir_entry *parent);
新建/proc子目录,如parent为NULL,则在/proc根下建立目录
extern struct proc_dir_entry proc_create_entry(const char *name,mode_t mode,struct proc_dir_entry *parent);
在/proc下新建虚拟文件
extern void *remove_proc_entry(const char *name,struct proc_dir_entry *parent);
删除新建的文件或目录

二.编码


  
   C代码  
   

  

#ifndef __KERNEL__  #define __KERNEL__  #endif  /* __KERNEL__ */    #include   #include   #include   #include   #include   #include   #include   #include     #define MAX_COOKIE_LENGTH PAGE_SIZE    static struct proc_dir_entry *test_proc_dir;  static struct proc_dir_entry *log_proc_dir;  static char *cookie_pot;     // 内核缓冲区,用于写数据  static int tValue = 12;      // 显示值    // 读取日志文件函数  int ProcLogRead( char *buffer,                          char **start,                          off_t offset,                          int length,                          int *eof,                          void *data )  {      int len;      if( offset > 0 )      {          *eof = 1;          return 0;      }        len = sprintf(buffer, "number:%x\n",tValue);      return len;  }      // 写日志文件函数  int ProcLogWrite( struct file *filp,                              const char __user *buff,                              unsigned long len,                              void *data)  {      if( copy_from_user( cookie_pot,buff,len ) )  // 拷贝用户空间值至内核缓冲区      {          return -EFAULT;      }            sscanf(cookie_pot,"%d",&tValue);    // 保存至全局变量tValue      printk(KERN_ALERT "%s len:%lu vl:%d\n",cookie_pot,len,tValue);      return len;  }      static int __init testproc_init(void)  {      int ret = 0;        printk(KERN_ALERT "proc test init\n");        cookie_pot = (char*)vmalloc( MAX_COOKIE_LENGTH );   // 为内核缓冲区分配空间      if(!cookie_pot)      {          ret = -ENOMEM;      }      else      {          memset(cookie_pot,0,MAX_COOKIE_LENGTH);            test_proc_dir = proc_mkdir("test",init_net.proc_net);       // 新建/proc/net/test目录,注:2.6.32以上内核,用init_net.proc_net取代先前的pro_net          log_proc_dir = create_proc_entry("log",0644,test_proc_dir);     // 新建文件 /proc/net/test/log            if(test_proc_dir == NULL              || log_proc_dir == NULL)          {              ret = -ENOMEM;              vfree(cookie_pot);          }          else          {              // 注册读写函数              log_proc_dir->read_proc = ProcLogRead;              log_proc_dir->write_proc = ProcLogWrite;          }      }        return 0;  }      static void __exit testproc_exit(void)  {      printk(KERN_ALERT "clean test proc\n");        remove_proc_entry("log",test_proc_dir);     // 删除log文件      remove_proc_entry("test",init_net.proc_net);    // 删除test目录        vfree(cookie_pot);  }    module_init(testproc_init);  module_exit(testproc_exit);    MODULE_LICENSE("Dual BSD/GPL");  MODULE_AUTHOR("kettas");  MODULE_DESCRIPTION("proc test");  MODULE_VERSION("1.0.0");  MODULE_ALIAS("Proc 01");  [/ol]

三.编译运行



  
   Shell代码  
   

  

[scada@linux proc_test]$ sudo insmod proc_test.ko  [scada@linux proc_test]$ ll /proc/net/test/  总用量 0  -rw-r--r--. 1 root root 0 1月  11 22:14 log  [scada@linux proc_test]$ cat /proc/net/test/log   number:c  [/ol]


四.接口操作
    上面用cat命令直接查看log文件,既然内核提供了通用的read(),write()文件访问接口,那试试。


  
   C代码  
   

  

#include   #include   #include   #include   #include   #include   #include     int main(int argc,char **argv)  {      int fd = open("/proc/net/test/log",O_RDWR,0);      assert(fd != -1);        char *vl = "10";  // 此处为字符串         // write      int ret = write(fd,vl,strlen(vl));      printf("ret:%d\n",ret);        // read      char buff[100] = {};      ret = read(fd,buff,100);      assert(ret != -1);        printf("read:%s\n",buff);      close(fd);        return 0;  }  [/ol]

运行:


  
   Shell代码  
   

  

[scada@linux proc_test]$ sudo ./write_test  ret:2  read:number:a  [/ol]
   向/proc/net/test/log写入10后,显示了16进制结果a,测试OK
               
        
        
   
            
        
        
回复

使用道具 举报

全部回复0 显示全部楼层

发表回复

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

楼主

审核员

热门推荐

联系客服 关注微信 下载APP 返回顶部 返回列表