Linux驅動 | procfs接口創建

上篇介紹了linux驅動中sysfs接口的創建,今天介紹procfs接口的創建。

procfs:可實現類似cat /proc/cpuinfo的操作

procfs接口創建

實現效果:

例如, 在/proc下創建一個clk節點,通過cat /proc/clk可查看內容:

Linux驅動 | procfs接口創建

代碼實現:

系統 內核版本
Linux 4.9.88

在驅動中添加以下代碼:

#include?<linux> #include?<linux> #include?<linux> #include?<linux> #include?<linux>  struct?proc_dir_entry?*my_proc_entry;  static?int?proc_clk_show(struct?seq_file?*m,?void?*v) { ????//cat顯示的內容 ????seq_printf(m, ??????????"pll0:?%u?Mhzn" ??????????"pll1:?%u?Mhzn" ??????????"pll2:?%u?Mhzn", ??????????100,?200,?300); ???return?0; }  static?int?clk_info_open(struct?inode?*inode,?struct?file?*filp) { ?????return?single_open(filp,?proc_clk_show,?NULL); }  static?struct?file_operations?myops?=? { ??????.owner?=?THIS_MODULE, ??????.open?=?clk_info_open, ??????.read?=?seq_read, ??????.llseek?=?seq_lseek, ??????.release?=?seq_release, };  static?int?__init?my_module_init(void) { ????//注冊proc接口 ???my_proc_entry?=?proc_create("clk",?0644,?NULL,?&amp;myops);  ????return?0; }  static?void?__exit?my_module_exit(void) { ????//注銷proc接口 ???proc_remove(my_proc_entry); }  module_init(my_module_init); module_exit(my_module_exit); MODULE_LICENSE("GPL");</linux></linux></linux></linux></linux>

procfs接口的創建,主要是實現struct file_operations結構體,然后通過proc_create函數進行注冊,通過proc_remove函數進行注銷。

procfs通常是用來獲取CPU、內存、進程等各種信息,例如cat /proc/cpuinfo、cat /proc/meminfo,所以我們只需要實現.open成員函數。當使用cat命令查看/proc下的信息時,會調用到.open對應的實現函數。

這里我們使用了seq_file接口,需要記住的是,procfs通常會和seq_file接口一起使用。seq_file是一個序列文件接口,當我們創建的proc數據內容由一系列數據順序組合而成或者是比較大的proc文件系統時,都建議使用seq_file接口,例如cat /proc/meminfo就會顯示很多內容。

seq_file接口主要就是解決proc接口編程存在的問題,推薦在proc接口編程時使用seq_file接口,另外.read、.llseek、.release成員函數也可以直接用seq_read、seq_lseek和seq_release。

proc新接口

注意,在較新版本的內核中,procfs的函數接口有所變化。

系統 內核版本
Linux 5.10.111

在驅動中添加以下代碼:

#include?<linux> #include?<linux> #include?<linux> #include?<linux> #include?<linux>  struct?proc_dir_entry?*my_proc_entry;  static?int?proc_clk_show(struct?seq_file?*m,?void?*v) { ?seq_printf(m, ????"pll0:?%lu?Mhzn" ????"pll1:?%lu?Mhzn" ????"pll2:?%lu?Mhzn", ????100,?200,?300); ?return?0; }  static?int?clk_info_open(struct?inode?*inode,?struct?file?*filp) { ?return?single_open(filp,?proc_clk_show,?NULL); }  static?const?struct?proc_ops?clk_stat_proc_fops?=?{ ?.proc_open?=?clk_info_open, ?.proc_read?=??seq_read, ?.proc_lseek?=?seq_lseek, ?.proc_release?=?seq_release, };  static?int?__init?my_module_init(void) { ???my_proc_entry?=?proc_create("clk",?0,?NULL,?&amp;clk_stat_proc_fops);  ????return?0; }  static?void?__exit?my_module_exit(void) { ???proc_remove(my_proc_entry); }  module_init(my_module_init); module_exit(my_module_exit); MODULE_LICENSE("GPL");</linux></linux></linux></linux></linux>

新的proc接口中,將原來的struct file_operations換成了struct proc_ops,其中成員函數也添加了對應的前綴proc,但本質還是一樣的,只是換了名字,更加規范了一些。

? 版權聲明
THE END
喜歡就支持一下吧
點贊9 分享