无法生成设备节点

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是一个配置项,通过配置这个配置项来设置上报事件过程中调用什么用户程序来创建设备节点。

  • 6
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Vold是一个用于管理外部存储设备的后台服务,它只能管理块设备节点,不能生成或管理TTY设备节点。如果需要在Android系统中生成TTY设备节点,需要进行以下步骤: 1. 在设备树中添加TTY节点。在设备树(device tree)中添加TTY节点,例如: ``` &uart1 { pinctrl-names = "default"; pinctrl-0 = <&uart1_pins>; status = "okay"; console = "ttyS1"; // 设置该节点为控制台 }; ``` 2. 为TTY节点设置属性。为TTY节点设置属性,例如设置波特率、数据位、停止位和校验位等,例如: ``` &uart1 { pinctrl-names = "default"; pinctrl-0 = <&uart1_pins>; status = "okay"; console = "ttyS1"; // 设置波特率、数据位、停止位和校验位 clock-frequency = <921600>; current-speed = <921600>; reg-shift = <2>; uart-has-rtscts; }; ``` 3. 编译设备树和内核。编译设备树和内核,并将新的设备树和内核烧录到设备中。 4. 在/dev目录下创建TTY设备节点。在设备启动时,可以通过rc.local或init.rc等脚本,在/dev目录下手动创建TTY设备节点,例如: ``` mknod /dev/ttyS1 c 204 65 chmod 666 /dev/ttyS1 ``` 其中,204是主设备号,65是次设备号,这些参数可以通过运行`ls -l /dev/ttyS1`命令获取。 需要注意的是,在创建TTY设备节点时,必须使用root权限或具有root权限的用户才能执行,否则将无法创建成功。 综上所述,要在Android系统中生成TTY设备节点,需要在设备树中添加TTY节点,并在设备启动时手动创建TTY设备节点

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值