操作系统设备驱动实验实验报告

华中农业大学 学生实验报告

日期: 2019 年 12 月 20 日 成绩
课程名称 计算机操作系统 实验名称 设备驱动实验 实验类型 验证 设计
综合 创新
【实验目的】
实验目的:熟悉Linux下驱动程序设计
编译内核

实验要求:在Linux系统下,编译内核,并在该内核下完成实验;
自主设计驱动程序,完成驱动程序的安装
【实验内容】
1.编译内核
2. ubantu14.04 32位下第一个hello world驱动程序
3. ubantu14.04第二个memory驱动程序
4. ubantu14.04第三个使用文件私有数据的globalmem的设备
5. Linux设备驱动中的阻塞与非阻塞I/O
【实验环境】(含主要设计设备、器材、软件等)
Pc电脑一台
【实验步骤、过程】(含原理图、流程图、关键代码,或实验过程中的记录、数据等)
内容:
编译内核过程:

编译内核代码截图:

第一个hello world驱动程序:

  1. uname -r 查看内核版本
  2. apt-cache search linux-source
  3. sudo apt-get install linux-source-4.15.0
  4. 执行:make oldconfig
  5. 执行:make bzImage
  6. 执行:make modules 和 make modules_install

编写hello. c程序并写Makefile文件;
之后通过make指令,生成hello.ko等其他文件;
执行sudo insmod hello.ko,在lsmod即可验证模块是否已装载,最后rmmod移出模块;
通过cat /var/log/syslog | grep world来观察其输出。
注意:版本号要改
由于用到printk,相关输出信息可以cat/var/log/syslog | grep world查看。

第二个memory驱动程序
首先编写程序,根据设备号,从内核空间将数据取出,写入相应的设备空间内;
再通过程序创建主从设备,将数据写入,再通过模块功能读出,观察其输出。

  1. 到包含 Makefile 和 mydm1.c 的目录下执行 make,生成 mydm1.ko;
  2. 执行 sudo insmod mydm1.ko;
  3. 验证:lsmod | grep mydm1
  4. 需要创建一个文件(该设备文件用于和设备驱动操作) mknod /dev/fgj c 224 0 c 代表字符设备 224 为主设备号,0 为从设备号
  5. gcc test.c,然后执行:sudo ./a.out 输出如下:
    执行结果:

使用文件私有数据的globalmem的设备驱动:

Linux设备驱动中的阻塞与非阻塞I/O:
阻塞和非阻塞 I/O 是设备访问的两种不同模式,驱动程序可以灵活的支持用户空间对设备的这两种访问方式。
本例子讲述了这两者的区别 并实现 I/O 的等 待队列机制, 并进行了用户空间的验证
基本概念: 1> 阻塞操作 是指 在执行设备操作时,若不能获得资源,则挂起进程直到满足操作条件后再进行操作。被挂起的进程进入休眠,被从调度器移走,直到条件满足。
2> 非阻塞操作在不能进行设备操作时,并不挂起,它或者放弃,或者不停地查询,直到可以进行操作。非阻塞应用程序通常使用 select 系统调用查询是否可以对设备进行无阻塞的访问终会引发设备驱动中 poll 函数执行。

通过Up和down获取信号量以及释放信号量。

加入轮询方式,判断FIFO空和满。
结果截图:
指令跟上面几个类似。

【实验结果或总结】(对实验结果进行相应分析,或总结实验的心得体会,并提出实验的改进意见)
1.编译内核的时候,大致了解了编译内核的指令以及对目录树的了解。
2. uname -r 查看内核的版本号,自己采用ubantu的版本号是4.15.0
3. 编写 hello world 程序以及加载驱动的时候,module_init(hello_init); module_exit(hello_exit); 这两个是函数的入口地址和出口地址。
Makefile文件记得更给KERNELDIR := /lib/modules/3.13.0-32-generic/build的版本号包括32也需要改成自己电脑相匹配的。
4. $(MAKE) -C ( K E R N E L D I R ) M = (KERNELDIR) M= (PWD) modules 这句是 Makefile 的规则:这里的KaTeX parse error: Expected 'EOF', got '&' at position 229: …vMajor,"mydm1",&̲simple_fops); …(shell uname -r)/build 则是用脚本的方法获取 uname -r 即可不用对代码进行修改,动态获取内核的版本信息。 clean: rm *.o *.ko *.mod.c *.order *.symvers 清除 这些文件。
8。需要创建一个文件(该设备文件用于和设备驱动操作) mknod /dev/fgj c 224 0 c 代表字符设备 224 为主设备号,0 为从设备号
9. 使用文件私有数据的globalmem的设备驱动 :用到了内核区的字符设备,将输入的字符存储到全局内存区域,再从用户空间中访问这个区域,获取到其中的数据。struct globalmem_dev { struct cdev cdev; //cdev 结构体 unsigned char mem[GLOBALMEM_SIZE]; //全局内存 }; globalmem 的设备结构体:包含了对应于 globalmem 字符设备的 cdev 和 使用内存 mem[GLOBALMEM_SIZE],其他与上一个实验类似。增加了一个ioctl函数:ioctl()函数接受的 MEM_CLEAR 命令,这个命令将全局内存的有效数据长度 清零,对于设备不支持的命令,ioctl()函数应该返回-EINVAL。,mknod /dev/globalmem c 354 0, echo ‘good nihao’ > /dev/globalmem, cat /dev/globalmem 即可验证输出 ,cat是读出,echo是写入。
10. Linux设备驱动中的阻塞和非阻塞驱动,理解了阻塞和非阻塞驱动的区别,引入并发信号量的控制,其他的大致相同;利用存储区的FIFO特性,实现用户对内核存储区的阻塞和非阻塞两种访问方式,可以为其提供灵活的支持。而这里的测试程序,则是向设备区的文件中写入一定量的数据,在FIFO区空时,会不断输出“can be written”,在FIFO区满后,会不断输出“can be read”,而在FIFO去不空不满时,则会交替输出。运行时由于会出现设备被占用的情况,需要更改设备号。但自己写入数据的时候,并没有出现read.
11.通过这次实验体会到了用户态和内核态编译的差异,初步掌握了设备驱动的基本原理,对于阻塞和非阻塞,异步方式有了初步的了解,这对于自己的学习有很大帮助。

发布了38 篇原创文章 · 获赞 7 · 访问量 2762

猜你喜欢

转载自blog.csdn.net/zzyzzylalala/article/details/104047985
今日推荐