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文件系统是如何实现的,就先不讨论了。
不然又成懒婆娘的裹脚了!

proc_create的使用方法相关推荐

  1. 在 Oracle Enterprise Linux 和 iSCSI 上构建您自己的 Oracle RAC 11g 集群

    作者:Jeffrey Hunter 了解如何以低于 2,700 美元的费用在 Oracle Enterprise Linux 上安装并配置 Oracle RAC 11g 第 2 版开发集群. 本指南中 ...

  2. Java面试题大全2021版

    一.Java 基础 JDK 和 JRE 有什么区别? JDK:Java Development Kit 的简称,java 开发工具包,提供了 java 的开发环境和运行环境. JRE:Java Run ...

  3. linux kernel内核、驱动日志调试方法(一)

    本文是对网络资料进行总结归纳,抄录其他博客资料,如有侵权,请告知,进行删除 一:通过打印调试printk printk是打印内核消息的函数,printk通过附加不同日志级别(loglevel)或者说消 ...

  4. Kotlin协程使用,协程使用注意事项,协程中的await方法使用|不使用suspend使用协程

    参见 码云 协程使用方法一 (Dispatchers调度器模式) 指定不同线程.同线程会挂起并阻塞(挂起是不影响主线程执行,阻塞是同样的IO线程会阻塞) withContext(Dispatchers ...

  5. IDEA中将代码块封装为方法,IDEA代码重构快捷键

    IDEA中将代码块封装为方法 选中要转换的代码块,快捷键: Windows快捷键:Alt + Shift + M Mac快捷键:Alt + Command + M 如图:

  6. IDEA自动生成对象所有set方法

    idea中有一款插件能够生成对象所有的set方法,GenerateAllSetter :下载地址 步骤1:将下载好的压缩包放在自己记得的文件夹中,在idea中进行导入 步骤2:在本地选中刚才的压缩包, ...

  7. List元素互换,List元素转换下标,Java Collections.swap()方法实例解析

    Java Collections.swap()方法解析 jdk源码: public static void swap(List<?> list, int i, int j) {// ins ...

  8. java1.8新增超实用Map方法——Map.getOrDefault()和Map.value()方法详解

    1. Map.getOrDefault() 翻译一下官方解释: java.util.Map<K, V> V getOrDefault(Object key, V defaultValue) ...

  9. spring boot项目 中止运行 最常用的几种方法

    spring boot项目 中止运行 最常用的几种方法: 1. 调用接口,停止应用上下文 @RestController public class ShutdownController impleme ...

最新文章

  1. windows线程同步-原子操作-Interlocked系列函数(用户模式)
  2. Java 8 Optional 类
  3. Android中关于cpu/cpuset/schedtune的应用
  4. 服务器文件上传记录,记录一下上传文件(图片)的过程上传图片到ftp服务器
  5. iOS Hacker 反注入和反反注入
  6. python中的字符串文本必须用什么括起来_Python标准库---18、文本处理服务:string 常见的字符串操作...
  7. 利尔达NB-IOT模块对接移动onenet平台步骤
  8. bootice工具修复linux,如何使用bootice工具修复引导
  9. multisim中pwl_Multisim 14电路设计与仿真
  10. QNAP 威联通 NAS的个人使用经验 篇三:#剁主计划-西安# 时隔3年,NAS使用须知
  11. oracle odac 配置,.Net項目中通過ODAC方式鏈接Oracle數據庫相關配置
  12. Python WEB 开发,什么是 WSGI ?uWSGI、Gunincorn 都是啥玩意儿?
  13. 入门3D游戏建模,有哪些建模软件可以选择?
  14. 【Banana PI Leaf S3开发板试用体验】MicroPython环境搭建
  15. js 使用百度翻译api demo
  16. php 搜索引擎包含哪些技术,浅谈三大搜索引擎爬虫性感 B-G-B
  17. 一代才女林徽因 人生若只如初见
  18. 获取QQ所有的表情包,包括emoji,动态gif
  19. 使用 Flutter 加速应用开发
  20. Java毕设项目自行车在线租赁管理系统2021(java+VUE+Mybatis+Maven+Mysql)

热门文章

  1. 个人站长怎么兼职赚钱
  2. 瞪羚优化算法Gazelle optimization algorithm附matlab代码
  3. python制作别人能使用的类_最近的工作,用python做一个微信的消息类的后台类的应用...
  4. android画图之贝塞尔曲线讲解
  5. 供给云发布AI微信群助手,赋能企业私域运营
  6. 计算机教室布线方案流程,学校计算机网络教室、多媒体教室布线及设备安装施工实施方案.docx...
  7. C语言程序设计--结构体--计算该日是在本年中是第几天
  8. 《我要好工作》读书笔记
  9. 华中科技大学计算机组成原理-单总线CPU设计(全部通关)
  10. 【For my liz】宇宙制作全纪录(如果能成功的话TT)