1前言
内核中有三个常用的伪文件系统:procfs,debugfs和sysfs。
procfs — the proc filesystem is a pseudo-filesystem which provides an interface to kernel data structures.
sysfs —thefilesystem for exporting kernel objects.
debugfs — debugfs exists as a simple way for kernel developers to make information available to user space.
它们都用于linux内核和用户空间的数据交换,但是适用的场景有所差异:
procfs 历史最早,最初就是用来跟内核交互的唯一方式,用来获取处理器、内存、设备驱动、进程等各种信息。
sysfs 跟 kobject 框架紧密联系,而 kobject 是为设备驱动模型而存在的,所以 sysfs 是为设备驱动服务的。
debugfs 从名字来看就是为debug而生,所以更加灵活。
它们仨的挂载方式类似,做个实验:
$ sudo mkdir/tmp/{proc,sys,debug}
$ sudo mount-t proc nondev/tmp/proc/
$ sudo mount-t sys nondev/tmp/sys/
$ sudo mount-t debugfs nondev/tmp/debug/
不过,默认情况下,它们分别挂载在/proc,/sys/,/sys/kernel/debug/。
下面简单介绍这三个文件系统的用法。在介绍之前,请记下他们的官方文档:
procfs — documentation/filesystems/proc.txt
sysfs — documentation/filesystems/sysfs.txt
debugfs — documentation/filesystems/debugfs.txt
2debugfs
api说明
structdentry*debugfs_create_dir(constchar*name,structdentry*parent)
structdentry*debugfs_create_file(constchar*name,umode_tmode,
structdentry*parent,void*data,
conststructfile_operations*fops)
参考实例
drivers/base/power/wakeup.c:
/**
* wakeup_sources_stats_show - print wakeup sources statistics information.
* @m: seq_file to print the statistics into.
*/
staticintwakeup_sources_stats_show(structseq_file*m,void*unused)
{
structwakeup_source*ws;
seq_puts(m,name active_count event_count wakeup_count
expire_count active_since total_time max_time
last_change prevent_suspend_time);
rcu_read_lock();
list_for_each_entry_rcu(ws,&wakeup_sources,entry)
print_wakeup_source_stats(m,ws);
rcu_read_unlock();
return0;
}
staticintwakeup_sources_stats_open(structinode*inode,structfile*file)
{
returnsingle_open(file,wakeup_sources_stats_show,null);
}
staticconststructfile_operations wakeup_sources_stats_fops={
.owner=this_module,
.open=wakeup_sources_stats_open,
.read=seq_read,
.llseek=seq_lseek,
.release=single_release,
};
staticint__init wakeup_sources_debugfs_init(void)
{
wakeup_sources_stats_dentry=debugfs_create_file(wakeup_sources,
s_irugo,null,null,&wakeup_sources_stats_fops);
return0;
}
创建完的接口
/sys/kernel/debug/wakup_sources
给接口添加多级目录
上述接口直接创建在debugfs根目录(/sys/kernel/debug)下,所以debugfs_create_file的parent参数被设置成了null,如果要加一级目录,则可以先用debugfs_create_dir创建一级目录,例如,要创建:/sys/kernel/debug/power/wakeup_sources的话,则需要:
structdentry*power;
interr=-enomem;
power=debugfs_create_dir(clock,null);
if(!power)
returnerr;
wakeup_sources_stats_dentry=debugfs_create_file(wakeup_sources,
s_irugo,power,null,&wakeup_sources_stats_fops);
3procfs
proc_mkdir用法跟debugfs_create_dir几无差异。
api说明
staticinlinestructproc_dir_entry*proc_mkdir(constchar*name,structproc_dir_entry*parent)
staticinlinestructproc_dir_entry*proc_create(constchar*name,umode_tmode,
structproc_dir_entry*parent,conststructfile_operations*proc_fops)
参考实例
在上面例子的基础上,可以添加如下语句:
staticint__init wakeup_sources_debugfs_init(void)
{
proc_create(wakelocks,s_ifreg|s_irugo,null,&wakeup_sources_stats_fops);
return0;
}
创建后的接口
/proc/wakelocks
给接口添加多级目录
这样创建的接口用起来跟/sys/kernel/debug/wakeup_sources没有任何差异,类似地,如果要加一级目录,例如/proc/power/wakelocks,则可以:
structproc_dir_entry*power;
interr=-enomem;
power=proc_mkdir(power,null);
if(!power)
returnerr;
proc_create(wakelocks,s_ifreg|s_irugo,power,&wakeup_sources_stats_fops);
4sysfs
在sysfs中,有另外一个常见用法,那就是在一个 kobject 对应的目录下创建一个符号(属性文件)指向另外一个 kobject 对应的目录,通常这个是为了方便记忆和访问。这个api是sysfs_create_link。
这种创建符号链接方法其实有一个很特殊的实例,那就是在驱动模型里头,有一个class的概念,它把挂在不同总线上,但是实现类似功能的设备进行归类,比如说input类,backlight类等。
如果设备属于一个现存的类,比如backlight,那么可以用backlight_device_register创建,如果是i2c设备,会先在i2c下创建sysfs访问节点,并创建一个符号链接到backlight类所属的目录下。
当然,如果没有找到设备能挂的直观的类,也可以用class_create创建类,设备类通常会有一组默认的设备操作接口,例如backlight类有bl_device_attributes,如果要创建更多的设备特定的节点,可以用device_create_file或者device_add_groups创建节点或者节点群。
api说明
structkobject*kobject_create_and_add(constchar*name,structkobject*parent)
intsysfs_create_file(structkobject*kobj,conststructattribute*attr)
staticinlineintsysfs_create_link(structkobject*kobj,structkobject*target,constchar*name)
intdevice_create_file(structdevice*dev,conststructdevice_attribute*attr)
参考实例
在/sys/power下创建一个 wakelocks 节点,用于读/写一个字符串。
staticchartest_str[11];
staticssize_tshow_wakelocks(structkobject*kobj,structattribute*attr,char*buf)
{
intret;
ret=snprintf(buf,10,%s,test_str);
returnret;
}
staticssize_tstore_wakelocks(structkobject*kobj,structattribute*attr,
constchar*buf,size_tcount)
{
inttmp;
ret=sscanf(buf,%10s,test_str);
if(ret!=1)
return-einval;
returncount;
}
define_one_global_rw(wakelocks);
staticint__init wakelocks_init(void)
{
intret;
ret=sysfs_create_file(power_kobj,&wakelocks.attr);
}
创建后的节点
/sys/power/test_node
给接口添加多级目录
咱们上面其实已经把 test_node 创建在/sys/power目录下,而非根目录/sys下,而参数 power_kobj 为内核已经在kernel/power/main.c创建的kobject对象。
structkobject*power_kobj;
power_kobj=kobject_create_and_add(power,null);
if(!power_kobj)
return-enomem;
5小结
通过比较发现,上述三个文件系统的 api 用法类似,而其中debugfs和procfs几乎有相同的参数,用的主要结构体是struct file_operations,蛮多操作可以用seq_*家族的函数来实现。而sysfs则用到比较简单一些的struct global_attr结构体。对于提供给用户空间的节点,都可以轻松实现读写操作。
在创建目录方面,debugfs和procfs类似,且比较简单。而sysfs要创建一级目录,需要先创建一个 kobject 对象。
为了简化设备模型依据总线创建的访问节点路径,sysfs提供了api用于创建更简易的符号链接,可以创建到自己指定的目录下,也可以用设备类(class)提供的api创建到设备类所属的目录下。
对于sysfs,由于kobject与device的一对一依存关系,也可以直接用device_create_file来创建节点。
LT8311SX是一款高性能的USB2.0扩展器
ICBE杭州站:出海企业到底需要一个什么样的数据智能工具?
李彦宏:人工智能带来时代的变革 比如未来医疗
modbus入门教程 Modbus协议节点讲解之【EsDA应用】Modbus应用详解
SpringSoft发布最新版一贯式定制IC版图流程设计平台
学会使用Linux 文件系统:procfs, sysfs, debugfs
联网车有安全隐患吗?车联网离安全还有多远?
SPICE仿真的典型应用案例及应用挑战
视频监控服务器无法通过浏览器访问的原因
人工智能在医疗行业的应用分析
以下五点 是2019年企业级存储厂商业务增长的基础
联发科5G Soc被三大手机厂商采用 有望斩获更多5G芯片订单
汽车电瓶的更换标准以及更换步骤
捷豹路虎与Connected Energy合作,推进电池再利用计划
大米外观品质分析仪的功能特点
清剂产生液体颗粒污染主要原因及管控办法
面向新数据、新应用、新韧性持续创新,加速行业数字化转型
压电式加速度传感器技术参数及选择
vivo S7t手机详细规格参数一览
坚持iOS10.1.1越狱?你可能要付出这个代价!