• Linux内核学习笔记之seq_file接口创建可读写proc文件


    转自:http://blog.csdn.net/mumufan05/article/details/45803219

    学习笔记与个人理解,如有错误,欢迎指正。

    温馨提示:建议跟着注释中的编号顺序阅读代码

    测试方法:cat /proc/abc_proc

                       echo 任意字符串 >/proc/abc_pro(需root权限)

    [cpp] view plain copy
     
    1. /************************************************* 
    2.  使用seq_file接口实现可读写proc文件的例子 
    3.  适用于3.10以后的内核 
    4.  Author: ZhangN 
    5.  Date: 2015-5-17  
    6.  *************************************************/  
    7. #include <linux/module.h>  
    8. #include <linux/sched.h>  
    9. #include <linux/uaccess.h>  
    10. #include <linux/proc_fs.h>  
    11. #include <linux/fs.h>  
    12. #include <linux/seq_file.h>  
    13. #include <linux/slab.h>  
    14.   
    15. static char *str = NULL;  
    16.   
    17. /*5,实现show函数 
    18.   作用是将内核数据输出到用户空间 
    19.   将在proc file输出时被调用*/  
    20. static int my_proc_show(struct seq_file *m, void *v)  
    21. {  
    22.     /*这里不能使用printfk之类的函数 
    23.       要使用seq_file输出的一组特殊函数 
    24.       详见ldd3的91页*/  
    25.     seq_printf(m, "current kernel time is %ld ", jiffies);  
    26.     seq_printf(m, "str is %s ", str);  
    27.     return 0;  
    28. }  
    29.   
    30.   
    31.   
    32. /*3,实现open和write函数*/  
    33. static ssize_t my_proc_write(struct file *file, const char __user *buffer,  
    34.                              size_t count, loff_t *f_pos)  
    35. {  
    36.     char *tmp = kzalloc((count+1), GFP_KERNEL);  
    37.     if(!tmp)  
    38.         return -ENOMEM;  
    39.     if(copy_from_user(tmp, buffer, count))  
    40.     {  
    41.         kfree(tmp);  
    42.         return EFAULT;  
    43.     }  
    44.     kfree(str);  
    45.     str = tmp;  
    46.     return count;  
    47. }  
    48.   
    49. static int my_proc_open(struct inode *inode, struct file *file)  
    50. {  
    51.     /*4,在open函数中调用single_open绑定seq_show函数指针 
    52.       需要说明的是,ldd3中介绍的seq接口用该调用seq_open函数 
    53.       其调用形式如下: 
    54.       return sep_open(file, &scull_seq_ops); 
    55.       scull_seq_ops为struct seq_operations结构体 
    56.       在该结构体中绑定show函数指针 
    57.       需要准备seq_operations结构体 
    58.       而调用single_open函数只需直接指定show的函数指针即可 
    59.       个人猜测可能是在single_open函数中实现了seq_operations结构体 
    60.       至于是不是就不知道了,没有查看具体实现 
    61.       有兴趣的同学可以参考文档:Documentationfilesystemsseq_file.txt 
    62.       关于第三个参数,其类型应为viod*, 
    63.       内核中有些地方传入的NULL,有些地方传入的inode->i_private,也有传入其他值的 
    64.       来看看data在single_open函数中如何被使用的: 
    65.         if (!res) 
    66.          ((struct seq_file *)file->private_data)->private = data; 
    67.       data是seq_file结构体的private成员。 
    68.       那么data如何真正被使用的呢? 
    69.       发现show函数的第一个参数为seq_file类型,在show函数中, 
    70.       可以将seq_file的private成员转换成对应的类型进行使用。 
    71.       也就是说,可以通过seq_file的private成员将data参数传递到show函数中*/  
    72.     return single_open(file, my_proc_show, NULL);  
    73. }  
    74.   
    75. /*2,填充proc_create函数中调用的flie_operations结构体 
    76.   其中my开头的函数为自己实现的函数, 
    77.   seq和single开头为内核实现好的函数,直接填充上就行 
    78.   open为必须填充函数 
    79.   这里详见ldd3的93页*/  
    80. static struct file_operations my_fops = {  
    81.     .owner   = THIS_MODULE,  
    82.     .open    = my_proc_open,  
    83.     .release = single_release,  
    84.     .read    = seq_read,  
    85.     .llseek  = seq_lseek,  
    86.     .write   = my_proc_write,  
    87. };  
    88.   
    89. static int __init my_init(void)  
    90. {  
    91.     struct proc_dri_entry *file;  
    92.     /*3.10以后内核的proc文件的新接口 
    93.       需要关联file_operations*/  
    94.     /*1,首先要调用创建proc文件的函数,需要绑定flie_operations*/  
    95.     file = proc_create("abc_proc", 0644, NULL, &my_fops);  
    96.     if(!file)  
    97.         return -ENOMEM;  
    98.     return 0;  
    99. }  
    100.   
    101. /*6,删除proc文件*/  
    102. static void __exit my_exit(void)  
    103. {  
    104.     remove_proc_entry("abc_proc", NULL);  
    105.     kfree(str);  
    106. }  
    107.   
    108. module_init(my_init);  
    109. module_exit(my_exit);  
    110. MODULE_LICENSE("GPL");  
    111. MODULE_AUTHOR("ZhangN");  
  • 相关阅读:
    从零开始学SQLSERVER-游标CURSOR(基础)
    从零开始学SQLSERVER-创建表
    从零开始学HTML-button
    从零开始学前端HTML-input标签
    专项测试实战 | 如何测试 App 流畅度(基于 FPS 和丢帧率)
    接口测试框架实战 | 流程封装与基于加密接口的测试用例设计
    软件测试之30分钟轻松搞定正则表达式基础
    Python 装饰器填坑指南 | 最常见的报错信息、原因和解决方案
    react16与react15之间的区别
    react-父子组件之间的交互传值
  • 原文地址:https://www.cnblogs.com/x_wukong/p/7489489.html
Copyright © 2020-2023  润新知