
🎬 渡水无言 :个人主页渡水无言
❄专栏传送门 :linux专栏
⭐️流水不争先,争的是滔滔不绝
📚博主简介:第二十届中国研究生电子设计竞赛全国二等奖 |国家奖学金 | 省级三好学生
| 省级优秀毕业生获得者 | csdn新星杯TOP18 | 半导纵横专栏博主 | 211在读研究生
在这里主要分享自己学习的linux嵌入式领域知识;有分享错误或者不足的地方欢迎大佬指导,也欢迎各位大佬互相三连

目录
[二、使用 modprobe 加载模块出现的问题汇总](#二、使用 modprobe 加载模块出现的问题汇总)
[2.2提示chrdevbase: no symbol version for module_layout](#2.2提示chrdevbase: no symbol version for module_layout)
[四、chrdevbase 设备操作测试](#四、chrdevbase 设备操作测试)
[5.1、提示/dev/chrdevbase: No such file or directory](#5.1、提示/dev/chrdevbase: No such file or directory)
前言
之前几期博客完成了chrdevbase 字符设备驱动程序的编写及编译,这期博客来进行运行测试。
一、加载驱动模块
驱动模块 chrdevbase.ko 和测试软件 chrdevbaseAPP 都已经准备好了,接下来就是运行测试。为了方便测试,Linux 系统选择通过 TFTP 从网络启动,并且使用 NFS 挂载网络根文件系统。
首先设置开发板的IP信息,使用如下命令:
setenv ipaddr 192.168.10.50
setenv ethaddr 00:04:9f:04:d2:35
setenv gatewayip 192.168.10.1
setenv netmask 255.255.255.0
setenv serverip 192.168.10.100
saveenv
如下图所示:

确保 uboot 中 bootcmd 环境变量的值为:
setenv bootcmd 'tftp 80800000 zImage;tftp 83000000 imx6ull-alientek-emmc.dtb;bootz 80800000 - 83000000'
saveenv
bootargs 环境变量的值为:
setenv bootargs 'console=ttymxc0,115200 root=/dev/nfs \
nfsroot=192.168.10.100:/home/duan/linux/nfs/rootfs,proto=tcp rw \
ip=192.168.10.50:192.168.10.100:192.168.10.1:255.255.255.0::eth0:off '
saveenv
设置好以后启动 Linux 系统,进入跟文件系统如下图:

检查开发板根文件系统中有没有"/lib/modules/4.1.15 "这个目录,如果没有的话自行创建。如下图所示(博主这是有的):

通过串口也能进入查看,如下图所示:

注意: 这个目录用来存放驱动模块,使用 modprobe 命令加载驱动模块的时候,驱动模块要存放在此目录下。
" /lib/modules"是通用的,不一样的是后面的"4.1.15",这里要根据你所使用的 Linux 内核版本来设置。
我们 开发板用的就是 4.1.15 版本的 Linux 内核,所以目录就是/lib/modules/4.1.15。
再将 chrdevbase.ko 和 chrdevbaseAPP 复制到 rootfs/lib/modules/4.1.15 目录中,命令如下:
sudo cp chrdevbase.ko chrdevbaseApp /home/duan/linux/nfs/rootfs/lib/modules/4.1.15/ -f

拷贝完之后,便输入如下命令加载 chrdevbase.ko 驱动文件:
modprobe chrdevbase.ko
会发现报错,提示无法打开"modules.dep"这个文件。

这个时候我们需要输入 depmod 命令即可自动生成modules.dep,如下图所示:

重新使用 modprobe 加载 chrdevbase.ko,结果如下图所示:

从上图中可以看到"chrdevbase init!"这一行,这一行正是 chrdevbase.c 中模块入口函
数 chrdevbase_init 输出的信息,说明模块加载成功!
输入"lsmod"命令即可查看当前系统中存在的模块

从图 40.4.4.5 可以看出,当前系统只有"chrdevbase"这一个模块。输入如下命令查看当前系统中有没有 chrdevbase 这个设备:
cat /proc/devices
结果如下图 所示:

当前系统存在 chrdevbase 这个设备,主设备号为 200,跟我们设置的主设备号一致。
从上图可以看出,当前系统存在 chrdevbase 这个设备,主设备号为 200,跟我们设置的主设备号一致。
二、使用 modprobe 加载模块出现的问题汇总
2.1提示无法打开"modules.dep"
解决方案:
输入 depmod 命令即可自动生成modules.dep
2.2提示chrdevbase: no symbol version for module_layout
问题本质:出现这个错误,本质是内核模块的编译环境与运行内核的环境不匹配。
解决方案:
保证模块编译时使用的内核源码满足以下条件:
和开发板运行的内核版本完全一致。
内核源码已经编译过。
编译模块的编译器和编译内核的编译器一致。
三、创建设备节点文件
驱动加载成功需要在/dev 目录下创建一个与之对应的设备节点文件,应用程序就是通过操作这个设备节点文件来完成对具体设备的操作。输入如下命令创建/dev/chrdevbase 这个设备节点文件:
mknod /dev/chrdevbase c 200 0
注意:"mknod"是创建节点命令"c"表示这是个字符设备,"200"是设备的主设备号,"0"是设备的次设备号。
如下图所示:

这个文件,可以使用"ls /dev/chrdevbase -l"命令查看,结果如下图所示:

如果 chrdevbaseAPP 想要读写 chrdevbase 设备,直接对/dev/chrdevbase 进行读写操作即可。
相当于/dev/chrdevbase 这个文件是 chrdevbase 设备在用户空间中的实现。
所以说Linux 下一切皆文件,包括设备也是文件。
四、chrdevbase设备操作测试
一切准备就绪,使用 chrdevbaseApp 软件操作 chrdevbase 这个设备,看看读写是否正常,首先进行读操作,输入如下命令:
./chrdevbaseApp /dev/chrdevbase 1
从上图 可以看出,首先输出" kernel senddata ok! "这一行信息
这是驱动程序中 chrdevbase_read 函数输出的信息,因为 chrdevbaseAPP 使用 read 函数从 chrdevbase 设备读取数据,因此 chrdevbase_read 函数就会执行。
chrdevbase_read 函数向 chrdevbaseAPP 发送" kernel data!"数据。chrdevbaseAPP 接收到以后就打印出来。
" read data:kernel data! "就是 chrdevbaseAPP 打印出来的接收到的数据。说明对 chrdevbase 的读操作正常,接下来测试对 chrdevbase 设备的写操作,输入如下命令:
./chrdevbaseApp /dev/chrdevbase 2

只有一行"kernel recevdata:usr data!",这个是驱动程序中的 chrdevbase_write 函数输出的。
chrdevbaseAPP 使用 write 函数向 chrdevbase 设备写入数据"usr data!"。chrdevbase_write 函数接 收到以后将其打印出来。说明对 chrdevbase 的写操作正常。
五、测试出现的问题汇总
5.1、提示/dev/chrdevbase: No such file or directory
问题所在:
1、设备文件 /dev/chrdevbase 已经不存在了
2、/dev/chrdevbase 的权限不足,用 chmod 666 /dev/chrdevbase 临时赋予所有用户读写权限
所以重新创建一下设备节点文件,并赋予权限。

六、卸载驱动模块
如果不再使用某个设备的话可以将其驱动卸载掉,比如输入如下命令卸载掉 chrdevbase 这个设备:
rmmod chrdevbase.ko
卸载以后使用 lsmod 命令查看 chrdevbase 这个模块还存不存在,结果如下图 所示:

从上图 可以看出,此时系统已经没有任何模块了, chrdevbase 这个模块也不存在了, 说明模块卸载成功。
总结
本期博客完成了对虚拟的 chrdevbase 设备驱动的测试验证。
