无法生成设备节点

Posted 四季帆

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了无法生成设备节点相关的知识,希望对你有一定的参考价值。

1. 背景

将驱动代码编译进内核,/dev目录下正常生成设备节点 driver_test0 和 driver_test1;

将驱动代码编译为 module,在系统完全启动之后,使用 insmod 加载单编的 ko 文件后,驱动加载未报错,init 和 probe 打印均有显示,这个驱动加载也未报错,驱动执行动作一切正常,只是 /dev 目录下没有生成暴露给用户态使用的设备节点。

2. 第一次分析

两种方式相同点:代码相同

两种方式不同点:驱动加载的时机不同、编译方式不同;

但是依旧无法确认问题出在哪儿,就从dev节点的生成原理入手好了。

 

3. 生成dev节点的原理

dev目录下的节点不是由驱动本身生成的,是由文件系统中的工具mdev生成的;

当系统启动后,加载完内核再去加载文件系统,执行文件系统中的脚本,脚本会执行mdev -s命令(即执行mdev程序,在博文《设备模型》中有说到,此处不赘述),该命令会去遍历/sys/class下的所有文件,寻找所有名为dev的文件,dev文件保存了每个驱动的主设备号、次设备号,以及驱动名。

 

4. 第二次分析

由上面的原理可知,生成设备节点的关键点有两个:

1)/sys/class下必须有驱动的节点信息,即dev文件
2)必须执行mdev -s创建 /dev 下的节点

查看/sys/class/class_test/driver_test0/目录,其下已经存在dev文件,cat dev可以看到该驱动对应的主次设备号;

搜索字符串“mdev -s”可知,在/etc/init.d/rcS脚本中有使用"mdev -s"命令。

 

5. 尝试

在终端下执行mdev -s命令,然后查看/dev目录,发现出现了设备节点driver_test0和driver_test1。

由结果反推,应该是因为脚本执行完了“mdev -s”命令之后,我们才insmod驱动模块,此时才生成模块相关的信息dev文件(/sys/class),而这个时候mdev -s命令已经执行完了,所以此时不会生成设备节点。

 

6. 解决办法

方法一:insmod之后手动执行mdev -s;

方法二:修改内核配置,正确配置设备热插拔的功能,将CONFIG_UEVENT_HELPER_PATH宏配置成“/sbin/mdev”。

 

7. 附录

方法二中为什么要修改这个宏呢?

7.1 自动生成设备节点的重要接口device_create,从这个接口进行入手分析。

device_create()
    device_create_groups_vargs();
        device_add();       //设备模型提供的接口
            kobject_uevent();  //上报事件的接口
                //通知用户态调用env->argv[0]中的路径存放的应用程序,env->envp是给该程序带的参数
                call_usermodehelper_setup(env->argv[0], env->argv, env->envp, GFP_KERNEL, NULL, c,leanup_uevent_env, env);
                call_usermodehelper_exec(info, UMH_NO_WAIT);   //在内核态执行应用程序

7.2 由device_create接口可知,它调用了设备模型接口,根据博文《设备模型》可知,设备模型中提供了一个热插拔功能,关键就在于调用了一个应用程序来创建设备节点,从此处的分析可以看出这个应用程序由这里的env->argv[0]参数指定。故而,当前的关键点就是确认env->argv[0]是在哪里赋值的?通过在kobject_uevent()函数所在文件搜索argv[0]可知其初始化位置。

static int init_uevent_argv(struct kobj_uevent_env *env, const char *subsystem)
{
	env->argv[0] = uevent_helper;
	······
}

7.3 搜索 uevent_helper 可知其定义

#ifdef CONFIG_UEVENT_HELPER
char uevent_helper[UEVENT_HELPER_PATH_LEN] = CONFIG_UEVENT_HELPER_PATH;
#endif

7.4 搜索 CONFIG_UEVENT_HELPER_PATH 可知其定义

config UEVENT_HELPER_PATH
	string "path to uevent helper"
	depends on UEVENT_HELPER
	default ""
	help
	  To disable user space helper program execution at by default
	  specify an empty string here. This setting can still be altered
	  via /proc/sys/kernel/hotplug or via /sys/kernel/uevent_helper
	  later at runtime.

7.5 由此可知,UEVENT_HELPER_PATH是一个配置项,去配置文件 .config中搜索发现,该配置项并未被设置未mdev,所以这里并没有调用到应用程序mdev,搞了半天是内核没配置好!!!淦······

7.6 总结:UEVENT_HELPER_PATH是一个配置项,通过配置这个配置项来设置上报事件过程中调用什么用户程序来创建设备节点。

以上是关于无法生成设备节点的主要内容,如果未能解决你的问题,请参考以下文章

当我将片段添加到我的视图寻呼机时(在嵌套滚动视图中),我无法从具有设备后退按钮的应用程序退出

在 Groovy 中将字符串 XML 片段转换为文档节点

无法将数据添加到 Firebase 中的不同节点

javascript 用于在节点#nodejs #javascript内设置react app的代码片段

从零开始配置vim(27)——代码片段

postman 自动生成 curl 代码片段