dev下无法生成节点的分析思路和解决方法及原理

您所在的位置:网站首页 查看设备节点信息的方法有 dev下无法生成节点的分析思路和解决方法及原理

dev下无法生成节点的分析思路和解决方法及原理

2024-07-13 05:45:37| 来源: 网络整理| 查看: 265

前言:本篇没有解决什么大问题,不神秘也不高深莫测,单纯记录,同时为其他碰到该问题的同仁提供思路,重点在于分析思路的整理,并使用流水帐的形式,试图讲清/dev下节点的生成原理

1.背景

为了调试方便,将之前直接编译进内核的驱动调整为module模式加载,即将驱动编译为.ko文件,通过insmod动态加载驱动。在未调整为module加载方式之前,系统启动后可以正常在dev下正常生成驱动节点 driver_test0,driver_test1 在这里插入图片描述 将驱动编译为module后,在系统完全启动后,使用insmod 加载单编的ko文件后,驱动加载未报错,init和porobe打印均有显示,整个驱动加载也未报错,驱动执行动作一切正常,只是dev目录下没有生成暴露给用户态使用的节点。而且驱动源码未动,只是单纯修改了Makefile使其编译为ko文件

2.差异分析

出现问题了,就先对比下差异项,从差异项入手,既然没有编译为模块的时候,节点正常生成,那么就有了一个好的场景,有了对比对象,这就好办了 相同点:源码相同 差异点: (1).编译方式不同,即Makefile不同 在这里插入图片描述

(2).加载方式和时机不同 有节点的是将驱动直接编译为内核,在系统启动过程中将驱动加载 无节点的是将驱动单独编译为ko文件,打包到文件系统中,等系统起来后,再通过insmod命令将ko文件注册到系统中,驱动被加载

3.分析

从2中可以看到2个差异项。makefile只是负责编译为不同的镜像形式,感觉和加载方式的不同有很大关联。但是insmod只是单纯的加载,之前也一直在用,一时半会找不到为何使用insmod加载后就没有节点的线索。 既然差异项无法突破,那么就从正面突破吧,先来搞清楚dev下节点生成的原理

4.生成dev节点的原理

dev目录下的节点不是由驱动本身生成的,它是由文件系统中的工具生成的,即busybox中的程序mdev。 具体流程是,当系统启动后,加载完内核再去加载文件系统,执行文件系统中的脚本,脚本会执行mdev -s命令。其实mdev就是一个上层可执行程序,mdev -s执行后,会去遍历/sys/class下的所有文件,寻找所有的名为dev的文件,dev文件保存了每个驱动的主设备号,次设备号,以及驱动名。mdev根据找到的dev,在/dev目录下根据dev文件中的驱动名创建节点(其实就是新建了一个文件)此时,驱动的节点就生成了。 (mdev的源码在busybox源码路径下:./util-linux/mdev.c中,接口为mdev_main,感兴趣可研究下) 根据上述原理,其关键点就2个: (1).sys/class 下必须有驱动的节点信息,即dev文件 (2).必须执行mdev -s创建/dev下的节点 根据上述结论查询系统下sys/class目录发现驱动的class节点 在这里插入图片描述 进入class_test节点 在这里插入图片描述 发现驱动的节点也已经创建好了,再进入 在这里插入图片描述 可以看到dev文件也是有的,cat dev文件可以看到该驱动的主设备号为249,次设备号为0。所以第一个要素已经具备了,此时就剩下mdev -s的执行了。查看系统脚本: 在这里插入图片描述 在这里插入图片描述 发现mdev -s在脚本中是有的,而且确定执行了。也是就说第二个要素mdev -s的执行也满足了。 定位到这里我确实也迷糊了,2个条件都满足为何/dev目录下不生成节点,难道mdev -s执行的时候出问题了?于是我尝试重新执行下mdev -s,然后再ls下dev节点 在这里插入图片描述 发现driver_test0和driver_test1节点已经出来了。。。难道真的是因为mdev -s没有执行吗,没道理啊,系统起来后会顺序执行rc脚本,这句命令会执行的啊 到这里想了会,就重新卸载再加载了几遍,突然发现,2中的差异之一就是加载时机的不同,出问题的时候是系统已经起来了,此时mdev -s已经执行过了,但是我的驱动还没有被加载,所以class下是没有启动节点节点的。所以不会创建。这下清楚了。 所以无法生成/dev下节点的原因是: 在mdev -s执行之后加载的驱动,所以无法创建/dev下的节点

5.新问题

无法创建/dev下节点的原因找到了,但是又有一个新问题,难道对于insmod加载驱动这种方式,必须在insmod以后,再执行一遍mdev -s吗,这个命令谁执行,每次都手动执行吗,显然对于牛逼的linux这不太可能,肯定有更好的方式。 我想了一下,目的其实就是在insmod以后,系统必须通知一下让某个“人”去执行下mdev -s,从而达成一直自动化的效果,我相信一定是这样的,是个人都要这样设计。。。。 所以这里的问题变为了谁去通知呢?我也不会,百度了下,看了几篇帖子,上报通知的动作在device_create操作中。 device_create 操作就是创建class下节点的函数接口 代码中是这样用的: 在这里插入图片描述 执行device_create后,在sys/class中就可以看到class_test的calss类 在这里插入图片描述 查看class_create的源码

struct device *device_create_vargs(struct class *class, struct device *parent, dev_t devt, void *drvdata, const char *fmt, va_list args) { return device_create_groups_vargs(class, parent, devt, drvdata, NULL, fmt, args); } => device_add 在device中看到了熟悉的这个操作:kobject_uevent,熟悉linux代码知道这就是上报的接口了,继续跟进 int kobject_uevent(struct kobject *kobj, enum kobject_action action) { return kobject_uevent_env(kobj, action, NULL); } kobject_uevent_env 中有如下的操作: #ifdef CONFIG_UEVENT_HELPER /* call uevent_helper, usually only enabled during early boot */ if (uevent_helper[0] && !kobj_usermode_filter(kobj)) { struct subprocess_info *info; retval = add_uevent_var(env, "HOME=/"); if (retval) goto exit; retval = add_uevent_var(env, "PATH=/sbin:/bin:/usr/sbin:/usr/bin"); if (retval) goto exit; retval = init_uevent_argv(env, subsystem); if (retval) goto exit; retval = -ENOMEM; info = call_usermodehelper_setup(env->argv[0], env->argv, env->envp, GFP_KERNEL, NULL, cleanup_uevent_env, env);这句操作是重点, env->argv[0]保存的是一段路径,该调用的作用是 通知用户态调用env->argv[0]中的路径存放的应用程序, env->envp是给该程序带的参数,注意这句调用是重点和精髓。 if (info) { retval = call_usermodehelper_exec(info, UMH_NO_WAIT); env = NULL; /* freed by cleanup_uevent_env */ } } #endif

所以重点是env->argv[0]中的赋值,代码中为:

static int init_uevent_argv(struct kobj_uevent_env *env, const char *subsystem) { env->argv[0] = uevent_helper; env->argv[1] = &env->buf[env->buflen]; env->argv[2] = NULL; uevent_helper 定义在: #ifdef CONFIG_UEVENT_HELPER char uevent_helper[UEVENT_HELPER_PATH_LEN] = CONFIG_UEVENT_HELPER_PATH; #endif

那么CONFIG_UEVENT_HELPER_PATH又是啥?不知道就搜么,反正内核代码都看得见,大不了就全局搜,只要电脑扛得住。。 在这里插入图片描述 按照搜索的结果,.config中已经默认指定了为/sbin/hotplug,所以应该就是调用sbin/hotplug这个命令或者可执行程序了。 但是在sbin目录下并没有找到hotplug这个命令或者可执行程序 在这里插入图片描述 而且CONFIG_UEVENT_HELPER_PATH这个值不应该市"sbin/mdev "么,如果是"sbin/mdev"那么就可以串起来了,整个过程就很合理,先验证下这个猜测,既然可以在config中可以配置,那么就简单了,重新配置config 在这里插入图片描述 在这里插入图片描述

生成新配置 在这里插入图片描述

重新编译内核,启动看下效果 在这里插入图片描述 在这里插入图片描述 可以看到节点出来了。。。到这里一切就都串起来了,串起来了。。 所以解决方案是: 修改config中的CONFIG_UEVENT_HELPER_PATH配置为/sbin/mdev

6.总结

总结下:dev下自动需要生成节点的必要条件: 条件1:驱动需要调用device_create接口生成sys/class下的class类和dev文件,供mdev程序扫描生成/dev下的节点 在这里插入图片描述 条件2:需要执行/sbin/mdev -s 去扫描1中创建的节点,谁来执行呢,答案在条件3中 2.1前提你的busybox中也要有mdev这个可执行程序

条件3:需要使能CONFIG_UEVENT_HELPER 机制,使能后,在条件1中,调用device_create创建好sys/class下的节点文件后,会通知用户态调用CONFIG_UEVENT_HELPER_PATH中的应用程序。这个应用程序就是/sbin/mdev

条件4:需要配置CONFIG_UEVENT_HELPER_PATH为sbin/mdev

上述4个条件满足后,当你的驱动调用device_create后,/dev目录下就会创建暴露给用户态的驱动节点。

所以dev下生成节点的流程为:

1.驱动调用device_create 创建sys/class/xxx节点 2.接着device_create中会调用call_usermodehelper_exec去执行CONFIG_UEVENT_HELPER_PATH路径中的用户态程序,传入参数s 3.该程序为/sbin/mdev,mdev -s 会去遍历/sys/class下的所有文件,寻找所有的名为dev的文件, dev文件保存了每个驱动的主设备号,次设备号,以及驱动名。 mdev根据找到的dev,在/dev目录下根据dev文件中的驱动名创建节点(其实就是新建了一个文件) 此时,驱动的节点就生成了 7.后记

还有一种修改CONFIG_UEVENT_HELPER_PATH的方法: 在脚本中执行 echo /sbin/mdev > /proc/sys/kernel/hotplug即可将CONFIG_UEVENT_HELPER_PATH中的内容重写为/sbin/mdev 在这里插入图片描述



【本文地址】

公司简介

联系我们

今日新闻


点击排行

实验室常用的仪器、试剂和
说到实验室常用到的东西,主要就分为仪器、试剂和耗
不用再找了,全球10大实验
01、赛默飞世尔科技(热电)Thermo Fisher Scientif
三代水柜的量产巅峰T-72坦
作者:寞寒最近,西边闹腾挺大,本来小寞以为忙完这
通风柜跟实验室通风系统有
说到通风柜跟实验室通风,不少人都纠结二者到底是不
集消毒杀菌、烘干收纳为一
厨房是家里细菌较多的地方,潮湿的环境、没有完全密
实验室设备之全钢实验台如
全钢实验台是实验室家具中较为重要的家具之一,很多

推荐新闻


图片新闻

实验室药品柜的特性有哪些
实验室药品柜是实验室家具的重要组成部分之一,主要
小学科学实验中有哪些教学
计算机 计算器 一般 打孔器 打气筒 仪器车 显微镜
实验室各种仪器原理动图讲
1.紫外分光光谱UV分析原理:吸收紫外光能量,引起分
高中化学常见仪器及实验装
1、可加热仪器:2、计量仪器:(1)仪器A的名称:量
微生物操作主要设备和器具
今天盘点一下微生物操作主要设备和器具,别嫌我啰嗦
浅谈通风柜使用基本常识
 众所周知,通风柜功能中最主要的就是排气功能。在

专题文章

    CopyRight 2018-2019 实验室设备网 版权所有 win10的实时保护怎么永久关闭