完整实验报告及源码截图:
(因上传文章需要一个个上传图片,太过麻烦,所以将完整报告直接上传成资源方便各位下载,下面的报告不含图片,可以粗略的阅读或自行配图),测试文档在文章最后
XDU嵌入式驱动程序设计实验一简单字符设备驱动资源-CSDN文库
XDU嵌入式驱动程序设计实验二模块参数及Proc文件系统资源-CSDN文库
XDU嵌入式驱动程序设计实验三Tasklet和工作队列资源-CSDN文库
XDU嵌入式驱动程序设计实验四内存分配和内存映射资源-CSDN文库
实验题目: 简单字符设备驱动
一、实验目的
1.掌握简单字符设备驱动程序编写方法。
2.编写应用程序对驱动程序进行测试,学习应用程序与驱动程序之间的调用过程。
二、实验环境
Linux 3.14.0 嵌入式开发板
三、实验内容及实验原理
1. 实验要求:
①定义一个全局结构指针,初始值为NULL,该数据结构中包含一个大小为1024的buffer和一个count整形变量
②在open中对该全局结构进行NULL判断,为NULL则为其分配内存,并将buffer初始化为0,将count自加
③在release中如果count为0,则释放,否则进行count自减
④在read里面对该buffer进行读取
⑤在write里面对该buffer进行赋值(任意赋值即可)
⑥写测试程序进行测试
2. 实现过程:
实现代码:
字符驱动设备的open接口:
字符驱动设备的read接口:
字符驱动设备的write接口
字符驱动设备的关闭接口
file operation:
系统初始化的函数:
系统卸载的函数:
其他相关信息:
测试函数:
实验中遇到的问题:
1、测试函数中调用open打开设备文件时,返回值一直为-1,无法打开,解决:在mknod为设备创建节点时,自己设定的设备号需要与驱动程序中预设的设备号保持一致。
2、使用insmod导入问题时报错:insmod: error inserting 'demo_driver.ko': -1 Device or resource busy ,运行命令: cat /proc/devices可以查看到原因是设备号已被占用。
四、实验结果及其分析
实验结果截图:
insmod来加载设备,初始化设备驱动程序的过程。通过lsmod命令查看,确认模块已加载
在后续过程中,向buf中输入一床字符 hello world ,输入完成后通过打印的信息,确认读取的字符串已经放入buf中。
五、心得体会与建议
实验题目: 模块参数及Proc文件系统
一、实验目的
1.掌握简单字符设备驱动程序中模块参数及Proc文件系统的编写方法。
2.学习利用模块参数进行驱动程序参数传递,学习利用Proc文件系统进行数据读写。
二、实验环境
Linux 3.14.0 嵌入式开发板
三、实验内容及实验原理
写一个简单的字符驱动设备,要求:
①定义一个全局结构指针,初始值为NULL,该数据结构中包含一个大小为N的buffer; ②在open中对该全局结构进行NULL判断,为NULL则为其分配内存,并将buffer初始化为0;
③在release中释放buffer;
④通过读proc文件系统对该buffer进行读取;
⑤通过写proc文件系统对该buffer进行赋值;
⑥Buffer的大小N是模块参数,在加载过程中指定。
实现代码:
该实验的代码主要分为两部分:模块参数和proc文件系统的读写
模块参数的传递:
初始化,buf中存储的字符串为default
通过proc_open打开,proc_show打印写入的字符串,再通过proc_write进行写操作
定义的file_operation
初始化和卸载函数:
其他相关信息
实现过程中遇到的问题:
1、创建文件函数proc_create_data()不存在,在新版本中被 函数proc_create()代替。
2、测试函数open无法打开proc字符驱动设备,排除了设备号不一致、设备节点是否创建、file_operations结构体是否定义等原因,问题依旧无法解决,最终通过insmod导入设备时传入参数代替测试函数,实现相同的实验效果。
四、实验结果及其分析
通过以下命令加载模块并传递参数:
insmod proc2.ko N=10 str=hello
通过以下命令查看传入的字符信息:
cat /proc/abc_rw
cat命令后的结果为传入的字符串hello
五、心得体会与建议
实验题目: Tasklet和工作队列
一、实验目的
1.掌握字符设备驱动程序中Tasklet和工作队列的编写和调用方法。
2.分析对比Tasklet和工作队列的差异。
二、实验环境
Linux 3.14.0 嵌入式开发板
三、实验内容及实验原理
写一个简单的驱动程序,要求:
①定义一个Tasklet和一个工作队列,实现打印输出
②定义两个定时器,定时器周期分别为T1和T2
③T1周期到时调度Tasklet,T2周期到时调度工作队列
④在加载驱动模块时注册Tasklet和工作队列
⑤在卸载驱动模块时销毁Tasklet和工作队列
实现代码
主要实现三个部分,两个计时器、tasklet、workqueue:
tasklet实现(分别是处理函数和调度函数)
workqueue实现
初始化过程:
卸载驱动设备的过程:
其他相关信息
实现过程中遇到的问题
1、tasklets和工作队列都是允许内核代码请求在将来某个时间调用一个函数。Tasklet的使用比较简单,只需要定义tasklet及其处理函数并将两者关联;工作队列则是通过INIT_WORK可以初始化这个工作队列并将工作队列与处理函数绑定,通过Schedule_work调度工作队列,两个的使用比较简单易懂,但是对两个机制的区别和适合的情形理解不够深入。
四、实验结果及其分析
实验结果截图:
前几行实在编写驱动函数时使用打印函数表明的Tasklet、工作队列和计时器进行初始化。
五、心得体会与建议
在编译内核时,通过精简内核并生成zImage文件,使我学会了如何配置内核、移植内核和精简内核,加深了我对内核移植的理解。
实验题目: 内存分配和内存映射
一、实验目的
1.掌握字符设备驱动程序中利用nopage进行内存映射的方法。
2.掌握利用get_free_pages进行连续物理地址空间申请的方法
二、实验环境
Linux 3.14.0 嵌入式开发板
三、实验内容及实验原理
写一个简单的驱动程序,要求:
①在加载驱动程序时利用get_free_pages函数申请一片64KB的连续物理地址空间;
②利用nopage机制实现对申请到的64KB地址空间进行内存映射;
③编写应用程序利用mmap进行内存映射,读写映射内存区域,通过打印输出观察具体每个页面实际进行内存映射的时机;
④在卸载驱动程序时利用free_pages释放申请到的64KB空间
实现代码:
用fault函数代替nopage函数实现内存映射:
建立页表:
file_operation
初始化过程
卸载过程:
其他相关信息:
测试函数:
实现过程遇到的问题:
1、nopage函数分页报错,解决:fault函数代替nopage实现内存分页。
2、get_free_pages第二个参数order值的获取,使用get_order函数获取。
3在试图释放和申请分配的页数不同的页数时, 内存图可能会变乱。__get_free_pages 和其他的函数可以在任何时候调用,遵循我们看到的 kmalloc 的相同规则. 这些函数不能在某些情况下分配内存, 特别当使用 GFP_ATOMIC 时. 因此, 调用这些分配函数的程序必须准备处理分配失败的情况
四、实验结果及其分析
初始化分配内存时,打印的信息
五、心得体会与建议
test
ifconfig eth0 192.168.100.191
sudo mount -t nfs 192.168.100.192:/source/rootfs /mnt/
mount -t nfs -o nolock 192.168.100.192:/source/rootfs /mnt/
arm-none-linux-gnueabi-gcc -o test test.c
mkdir /lib/modules/3.14.0
实验1:
test_driver.c
实验2:
insmod proc2.ko N=10 str=hello
cat /proc/abc_rw
实验3:
insmod tasklet
实验4:
mknod /dev/mmapnopage c 240 0
insmod
./test