Linux驱动学习(三),实现简单的字符设备驱动的动态装载?基于ubuntu16.04,VirtualBox6。从入门到入土


强烈建议在参照这篇博客的时候,先将整篇博客通读(瞟)一下,熟悉一下目录结构,以免浪费你人生中的几个小时
第二、三章可以选择不做,运气好的话十几分钟能做完

在这里插入图片描述

整理一下第三次作业要求

1、第一部分

制作驱动,要求驱动能实现基本的openwritereadcloseioctl

其中ioctl需要实现
输入CMD1:打印 hello ecnu;
输入CMD2:打印 ecnu hello;
输入CMD3:打印学号和姓名。
不一定非要这样,能对输入有反应就行了。
lseek和poll能实现的话更好。

第一部分在ubuntu主机或者qemu测试没有问题了,就可以准备做第二部分。

2、第二部分

静态加载,就是把驱动程序直接编译到内核里,系统启动后可以直接调用。在本篇第五、六章

这次学习会遇到很多问题:
1、gcc版本不同导致的问题
2、编译平台不同
3、我不知道什么原因的原因
4、作者是个菜鸟希望能给大家提供一些思路
5、本文qemu测试部分基于第二次作业,ubuntu16.04,linux-5.14.14

一、需要的文件

1、驱动程序源码: 某某某.c
2、Makefile:Makefile
3、应用程序代码: 某某.c

使用 make 指令 ,按照Makefile的设置编译 驱动程序源码 生成 hello.ko等文件。hello.ko就是动态加载驱动要用到的文件
在这里插入图片描述

这里附上gitee地址
https://gitee.com/steveqobs/learn-linux-driver.git
使用下面指令,可将项目克隆到任意位置。
建议在/home/你的用户名/kernel/下执行。
和我的目录保持一致
,会省去一些麻烦。

git clone https://gitee.com/steveqobs/learn-linux-driver.git

在这里插入图片描述

/learn-linux-driver/drv目录是ubuntu主机用的,
/learn-linux-driver/files/rootfs/drvqemu是后面qemu中测试用的
在这里插入图片描述


注意!!!项目下载到本地后,请看一遍drv和/learn-linux-driver/files/rootfs/drvqemu的app.c和hello.c,我已经把自己的英文名去掉写成"yourname",“yournumber”,改成自己的再继续操作!,drvqemu的Makefile也打开修改一下steve


1、驱动源代码hello.c

使用自动创建设备节点的方法,这章的测试不用每次mknod。
作业要求要有 insmod指令步骤,和mknod步骤,mknod在后面的qemu测试用到了。

调用了 __register_chrdev(major, 0, 256, name, fops) 函数: 这个函数不只帮我们注册了设备号,还帮我们做了cdev 的初始化以及cdev 的注册;

以下所有C语言都取消展示,因为放这了大家也没时间看代码,而且还占了几百行显得博客太长,有兴趣直接去我gitee码云下载了看代码吧

2、Makefile

drv文件的这个Makefile 是给Ubuntu主机测试驱动用的,内核目录选择了本机内核模块地址

KERN_DIR = /lib/modules/$(shell uname -r)/build

all:
	make -C $(KERN_DIR) M=`pwd` modules

clean:
	make -C $(KERN_DIR) M=`pwd` modules clean
	rm -rf modules.order

obj-m    += hello.o

3、应用程序app.c

课上演示的应用程序文件,代码写的很不错,用了while循环,打印 了功能菜单,可读取 操作对应的指令。大家有空可以实现一下… 我这文件只是流水线 一运行就是open、write、read、ioctl。 close忘加了。 就是打印的东西花里胡哨,而且还有bug(ioctl并没有采用常规方式实现,课堂上展示的代码才是正确的)。谨慎使用。

二、加载驱动(ubuntu主机)

在这里插入图片描述
app.c hello.c Makefile是必需的


做这步确保你的app.c和hello.c中的关键字已经修改为你的名字,然后可执行make clean 可删除我生成的文件,再继续make


1、make

先make出hello.ko文件

make

make执行成功,如下图所示
在这里插入图片描述

2、insmod

insmod命令功能: 用于将指定模块加载到内核中

 sudo insmod hello.ko

insmod成功,输出init函数打印的东东

dmesg | tail -6

-6就是显示6行printk
我把steve删了,printk的内容你们可以随意修改
在这里插入图片描述

3、查看设备

查看当前有哪些设备

cat /proc/devices

可以看到字符设备已经有hello了,我这自动分配为243号
不一定每个人都是243。
在这里插入图片描述

ls -l /dev/hello

hello.c代码已经帮我们生成好了/dev/hello
在这里插入图片描述

三、执行app(ubuntu主机)

在应用层调用ioctl的时候,当传入的cmd=2时会出现错误。
ioctl返回值为-1。错误号errno:14, bad address。
需要使用_IOWR等宏来生成cmd命令,而不能自己写。
虽然自己写也可以,但很有可能和系统的其他命令冲突。

看到老师写的代码这样写,在hello.c定义了,这才是正常的
#define HELLO_SETCHANEL 0xc000fa01
#define HELLO_SET_BIT 0xc000fa02

https://mjmwired.net/kernel/Documentation/ioctl-number.txt

1、生成可执行文件

gcc -o app app.c

2、执行

sudo ./app

在这里插入图片描述

查看最近30条记录

dmesg | tail -30

在这里插入图片描述

3、卸载驱动

sudo rmmod hello.ko

在这里插入图片描述

四、在qemu中测试驱动(qemu)

因为第二次作业做的只是雏形,不适合在工程下使用,少了很多模块(我偷懒少了一些步骤)所以下面遇到一些问题不好解决。
后来我把文件系统完善了一下,能正常用了。

这章要用到的/learn-linux-driver/files/rootfs/drvqemu目录和drv目录基本一致,区别就是Makefile不一样


做这步确保你的app.c和hello.c中的关键字已经修改为你的名字,Makefile中的内核路径中的steve改成你的用户名


在这里插入图片描述

直接在files文件夹执行start.sh即可

1、生成hello.ko和app

可直接在/learn-linux-driver/files/rootfs/drvqemu/文件下执行

make

生成app应用程序

arm-linux-gnueabi-gcc -o app app.c

在这里插入图片描述

2、运行qemu

在这里插入图片描述
在files文件夹下运行start.sh
要等几秒钟,返回终端查看。

./start.sh

sudo 的指令会要求输入密码

在这里插入图片描述
等它输出一会 ,按enter进入

3、装载驱动

ls
cd drvqemu
insmod hello.ko
cat /proc/devices

在这里插入图片描述

4、mknod和运行应用程序

ls -l /dev/hello
mknod /dev/hello c 250 0
ls -l /dev/hello
./app

在这里插入图片描述

输入2,打印出来了。可以重新执行./app ,1、2、3都试一下

5、卸载驱动

rmmod hello.ko

在这里插入图片描述

关机

poweroff

五、驱动的静态加载

第五章完成make前的准备,第六章做静态加载的驱动测试
在这里插入图片描述

0、熟悉一下文件夹

learn-linux-driver是用git clone 下载来的文件夹,代码和文件系统在这里面,之后要用到。
linux-5.14.14是本次静态装载要用到内核文件夹,要修改的Makefile和Kconfig都在这里,hello.c也要放到这个文件夹的/drivers/char/里面。
/learn-linux-driver/files/的rootfs、tmpfs、a9rootfs.ext3是启动qemu模拟器要用到的。
start.sh脚本包含了几句指令,用./start.sh即可完成文件系统的装载和qemu的启动。

1、修改/drivers/char/Makefile

指令或者到对应文件夹中打开这个文件
如果用指令进入文件修改。记得改steve为你的用户名

vi /home/steve/kernel/linux-5.14.14/drivers/char/Makefile

在最下面 ,加一行

obj-$(CONFIG_DRVHELLO)          += hello.o

**$(CONFIG_DRVHELLO)**可以看作一个变量,默认值是y,hello.o就是要编译到内核要用到的文件名。
在这里插入图片描述

2、修改/drivers/tty/Kconfig

vi /home/steve/kernel/linux-5.14.14/drivers/tty/Kconfig

DRVHELLO默认值为 y
对应了本章第一节的obj-$(CONFIG_DRVHELLO)
help就是说明。

照葫芦画瓢,这些信息会出现在menuconfig图形界面

复制下面这段,一定要把下面的中文改成别的英文,内容随便你写

config DRVHELLO
	bool "这里写的会显示在menuconfig菜单项" 
	default y
	help
	  这里写的会显示这一项的help(帮助、说明)中

在这里插入图片描述编辑完成 按ctrl s 保存

下面这个图片 举个例子在这里插入图片描述

3、make menuconfig确认驱动已配置

注意我执行的路径在/home/steve/kernel/linux-5.14.14/

make menuconfig

在内核文件夹执行make menuconfig 往下翻
选择 设备驱动 Device Drivers
在这里插入图片描述
select 。再往下翻,选择字符设备Character devices
在这里插入图片描述

可以看到 hell driver 已经被打上星号*了
这就是刚才在Konfig中输入的
可选择help查看刚才写的内容

这张截图就是作业要求之一
在这里插入图片描述

在这里插入图片描述

4、复制hello.c到/char/

只把hello.c 复制到这里

cp /home/steve/kernel/learn-linux-driver/files/rootfs/drvqemu/hello.c  /home/steve/kernel/linux-5.14.14/drivers/char/hello.c

在这里插入图片描述

5、编译

返回到内核目录/home/steve/kernel/linux-5.14.14/

复制了第二次作业的两句代码

make CROSS_COMPILE=arm-linux-gnueabi- ARCH=arm vexpress_defconfig
make CROSS_COMPILE=arm-linux-gnueabi- ARCH=arm

在make过程中会有hello.o生成到/drivers/char目录,当然你第一次编译的话,打印的行数太多,你看不到它,如果在没有修改配置的情况下载再次编译,就可以看到这次更新了hello.o,我们启动qemu需要的Image文件也生成了。

第一次编译完成之后,就可以开始最后一步了,驱动静态装载的测试
在这里插入图片描述

六、静态加载的测试

1、启动qemu

这时启动的镜像已经和第四章的不一样了

./start.sh

在这里插入图片描述
能看到加载中执行了这在这里插入图片描述

2、执行app

启动成功、测试

cd drvqemu
./app

在这里插入图片描述关机…poweroff

在这里插入图片描述

linux4.4也完成了,测试也ok
在这里插入图片描述

  • 9
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 15
    评论
评论 15
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值