当前位置: 首页 > news >正文

proc_create的使用方法

proc_create的使用方法

proc文件系统是个有用的东东。
创建一个proc虚拟文件,应用层通过读写该文件,即可实现与内核的交互
proc虚拟文件是如何创建的呢?

先看看比较简单的,创建proc文件夹。
调用以下函数,即可实现proc文件夹的创建:
struct proc_dir_entry *proc_mkdir(const char *name, struct proc_dir_entry *parent);
name就是要创建的文件夹名称。
parent是要创建节点的父节点。也就是要在哪个文件夹之下创建新文件夹,需要将那个文件夹的proc_dir_entry传入。
如果是在/proc目录下创建文件夹,parent为NULL。
例如:

struct proc_dir_entry *mytest_dir = proc_mkdir("mytest", NULL);

 

然后来看看proc文件的创建。
创建方法是调用以下函数:

static inline struct proc_dir_entry *proc_create(const char *name, mode_t mode, struct proc_dir_entry *parent, const struct file_operations *proc_fops);

 


name就是要创建的文件名。
mode是文件的访问权限,以UGO的模式表示。
parent与proc_mkdir中的parent类似。也是父文件夹的proc_dir_entry对象
proc_fops就是该文件的操作函数了
例如:

struct proc_dir_entry *mytest_file = proc_create("mytest", 0x0644, mytest_dir, mytest_proc_fops);

还有一种方式:

struct proc_dir_entry *mytest_file = proc_create("mytest/mytest", 0x0644, NULL, mytest_proc_fops);

如果文件夹名称和文件名定义为常量:

#define MYTEST_PROC_DIR "mytest"
#define MYTEST_PROC_FILE "mytest"

第二种方式为:

struct proc_dir_entry *mytest_file = proc_create(MYTEST_PROC_DIR"/"MYTEST_PROC_FILE, 0x0644, NULL, mytest_proc_fops);

 

接下来看看mytest_proc_fops的定义。

static const struct file_operations mytest_proc_fops = {
 .open  = mytest_proc_open,
 .read  = seq_read,
 .write  = mytest_proc_write,
 .llseek  = seq_lseek,
 .release = single_release,
};

以seq_和single_为前缀的函数都是kernel中现成的。
可以参考文档:Documentation\filesystems\seq_file.txt
关于single_开头的函数,有以下说明:

The extra-simple version

For extremely simple virtual files, there is an even easier interface.  A
module can define only the show() function, which should create all the
output that the virtual file will contain. The file's open() method then
calls:

 int single_open(struct file *file,
                 int (*show)(struct seq_file *m, void *p),
                 void *data);

 

When output time comes, the show() function will be called once. The data
value given to single_open() can be found in the private field of the
seq_file structure. When using single_open(), the programmer should use
single_release() instead of seq_release() in the file_operations structure
to avoid a memory leak.

根据以上这段说明,在mytest_proc_open函数中,只需要调用single_open函数,并传入一个show函数即可。
例如:

static int mytest_proc_open(struct inode *inode, struct file *file)
{
 return single_open(file, mytest_proc_show, inode->i_private);
}

 


其中第三个参数,也就是single_open的data参数,内核中有些地方传入的NULL,有些地方传入的inode->i_private,也有传入其他值的。
来看看data在single_open函数中如何被使用的:
  if (!res)
   ((struct seq_file *)file->private_data)->private = data;
这与前面的英文说明一致,data是seq_file结构体的private成员。
那么data如何真正被使用的呢?
发现show函数的第一个参数为seq_file类型,在show函数中,可以将seq_file的private成员转换成对应的类型进行使用。

下面来看看mytest_proc_show函数如何实现。
传递给single_open的show函数指针,将在proc file输出时被调用。
例如,cat /proc/mytest/mytest时,mytest_proc_show函数将会被调用。
假设我们的mytest只是记录了一个标志,内核中会根据该标准执行不同的操作。
来看看mytest_proc_show的实现:

static int task_lifecycle_proc_show(struct seq_file *seq, void *v)
{
 seq_puts(seq, mytest_flag ? "true\n" : "false\n");
 
 return 0;        
}

 

接下来再看看mytest_proc_write函数的实现。
顾名思义,mytest_proc_write函数会在写mytest文件时被调用。
功能就是记录写入数据到mytest文件。
实现也不麻烦:

static ssize_t task_lifecycle_proc_write(struct file *file, const char __user *buffer,
        size_t count, loff_t *pos)
{
 char mode;
 
 if (count > 0) {
  if (get_user(mode, buffer))
   return -EFAULT;

   mytest_flag = (mode != '0');
 }

 return count;
}

 

至此,proc文件创建完毕。
通过读写mytest文件,即可实现对mytest_flag的控制。
更深层次的原理,即proc文件系统是如何实现的,就先不讨论了。
不然又成懒婆娘的裹脚了

转载于:https://www.cnblogs.com/Ph-one/p/5530320.html

相关文章:

  • simple_strtoul
  • linux子系统的初始化_subsys_initcall()
  • linux sed 命令,sed -i
  • linux设备驱动程序注册过程详解
  • linux下lk和kernel层通信方式[2]
  • 模拟IC
  • ubuntu使用ssh连接远程电脑的方法
  • Linux内核日志开关
  • Linux:命令gedit
  • bin/sh^M:损坏的解释器: 没有那个文件或目录
  • ubuntu 关机命令
  • 海思3518e mpp2/sample/venc makefile简析
  • 错误
  • ubuntu下7z文件的解压方法
  • ubuntu下xev
  • [PHP内核探索]PHP中的哈希表
  • 10个确保微服务与容器安全的最佳实践
  • AHK 中 = 和 == 等比较运算符的用法
  • AngularJS指令开发(1)——参数详解
  • - C#编程大幅提高OUTLOOK的邮件搜索能力!
  • MYSQL如何对数据进行自动化升级--以如果某数据表存在并且某字段不存在时则执行更新操作为例...
  • node.js
  • opencv python Meanshift 和 Camshift
  • Spring思维导图,让Spring不再难懂(mvc篇)
  • 测试如何在敏捷团队中工作?
  • 给github项目添加CI badge
  • 湖南卫视:中国白领因网络偷菜成当代最寂寞的人?
  • 基于MaxCompute打造轻盈的人人车移动端数据平台
  • 你不可错过的前端面试题(一)
  • 前端js -- this指向总结。
  • 日剧·日综资源集合(建议收藏)
  • 首页查询功能的一次实现过程
  • 学习Vue.js的五个小例子
  • 一道闭包题引发的思考
  • kubernetes资源对象--ingress
  • LevelDB 入门 —— 全面了解 LevelDB 的功能特性
  • ​二进制运算符:(与运算)、|(或运算)、~(取反运算)、^(异或运算)、位移运算符​
  • #{} 和 ${}区别
  • #FPGA(基础知识)
  • (3)(3.2) MAVLink2数据包签名(安全)
  • (pytorch进阶之路)CLIP模型 实现图像多模态检索任务
  • (附源码)springboot太原学院贫困生申请管理系统 毕业设计 101517
  • (三) prometheus + grafana + alertmanager 配置Redis监控
  • (四)c52学习之旅-流水LED灯
  • (五)网络优化与超参数选择--九五小庞
  • (转)Linux下编译安装log4cxx
  • (转)ORM
  • (转)原始图像数据和PDF中的图像数据
  • (转载)利用webkit抓取动态网页和链接
  • (转载)虚幻引擎3--【UnrealScript教程】章节一:20.location和rotation
  • . Flume面试题
  • .dat文件写入byte类型数组_用Python从Abaqus导出txt、dat数据
  • .NET 4 并行(多核)“.NET研究”编程系列之二 从Task开始
  • .NET Core WebAPI中使用swagger版本控制,添加注释
  • .NET Framework 3.5中序列化成JSON数据及JSON数据的反序列化,以及jQuery的调用JSON