块设备驱动程序

合集下载

Linux设备驱动程序原理及框架-内核模块入门篇

Linux设备驱动程序原理及框架-内核模块入门篇

Linux设备驱动程序原理及框架-内核模块入门篇内核模块介绍应用层加载模块操作过程内核如何支持可安装模块内核提供的接口及作用模块实例内核模块内核模块介绍Linux采用的是整体式的内核结构,这种结构采用的是整体式的内核结构,采用的是整体式的内核结构的内核一般不能动态的增加新的功能。

为此,的内核一般不能动态的增加新的功能。

为此,Linux提供了一种全新的机制,叫(可安装) 提供了一种全新的机制,可安装) 提供了一种全新的机制模块” )。

利用这个机制“模块”(module)。

利用这个机制,可以)。

利用这个机制,根据需要,根据需要,在不必对内核重新编译链接的条件将可安装模块动态的插入运行中的内核,下,将可安装模块动态的插入运行中的内核,成为内核的一个有机组成部分;成为内核的一个有机组成部分;或者从内核移走已经安装的模块。

正是这种机制,走已经安装的模块。

正是这种机制,使得内核的内存映像保持最小,的内存映像保持最小,但却具有很大的灵活性和可扩充性。

和可扩充性。

内核模块内核模块介绍可安装模块是可以在系统运行时动态地安装和卸载的内核软件。

严格来说,卸载的内核软件。

严格来说,这种软件的作用并不限于设备驱动,并不限于设备驱动,例如有些文件系统就是以可安装模块的形式实现的。

但是,另一方面,可安装模块的形式实现的。

但是,另一方面,它主要用来实现设备驱动程序或者与设备驱动密切相关的部分(如文件系统等)。

密切相关的部分(如文件系统等)。

课程内容内核模块介绍应用层加载模块操作过程内核如何支持可安装模块内核提供的接口及作用模块实例内核模块应用层加载模块操作过程内核引导的过程中,会识别出所有已经安装的硬件设备,内核引导的过程中,会识别出所有已经安装的硬件设备,并且创建好该系统中的硬件设备的列表树:文件系统。

且创建好该系统中的硬件设备的列表树:/sys 文件系统。

(udev 服务就是通过读取该文件系统内容来创建必要的设备文件的。

)。

块设备IO流程

块设备IO流程

1. 概述系统能够随机访问固定大小数据片的设备称为块设备,这些数据片称作块。

另一种基本的设备类型是字符设备。

字符设备按照字节流的方式被有序访问,像串口和键盘都属于字符设备。

这两种类型的设备的根本区别在于它们是否可以被随机访问,换句话说,就是能否在访问设备时随意从一个位置跳到另一个位置。

字符设备仅仅需要控制一个位置--当前位置;而块设备访问的位置必须在介质的不同区间前后移动,同时块设备对执行性能的要求很高。

如何管理块设备和如何管理队块设备的请求,该部分在内核中被称为块I/O层。

2. 解剖一个块设备块设备中最小的可寻址单元式扇区。

扇区最常见大小事512字节。

软件都会用到自己的最小逻辑可寻址单元--块。

块石文件系统的一种抽象--只能基于块来访问文件系统。

虽然物理磁盘寻址是按照扇区级来进行的,但是内核执行的所有磁盘操作都是按照块进行的。

所以,块只能数倍于扇区的大小,但大小不能超过一个页面。

扇区:设备的最小寻址单元,亦称"硬扇区"或"设备块"块:文件系统的最小寻址单元,亦称"文件块"或"I/O块"3. 缓冲区和缓冲区头当一个块被调用内存时,它要存储在一个缓冲区中。

每个缓冲区与一个块对应,它相当于是磁盘块在内存中的表示。

所有这些信息都和文件系统的控制信息密切交融,文件系统的控制信息储存在超级快中,超级块是一种包含文件系统信息的数据结构。

由于内核在处理数据需要相关的控制信息,所以每个缓冲区都有一个对应的描述符。

该描述符用buffer_head结构体表示,被称为缓冲区头,在文件<linux/buffer_head.h>中定义。

结构体中h_count域表示缓冲区的使用技术。

在操作缓冲区头之前,应该增加缓冲区头的引用计数,确保该缓冲区托不会再被分配出去,当完成对缓冲区的操作后,就减少引用计数。

缓冲区头的目的在于描述磁盘块和物理内存缓冲区之间的映射关系。

Windows下设备驱动程序的开发方法

Windows下设备驱动程序的开发方法

目录一、驱动开发环境的搭建 (1)1.1 关于DDK (1)1.2 关于驱动程序的编译 (1)1.3关于驱动程序的运行 (2)二、驱动程序的结构 (3)2.1 驱动程序的头文件 (3)2.2 驱动程序的入口点 (3)2.3 创建设备例程 (4)2.4 卸载驱动例程 (5)2.5 派遣例程 (6)三、编写驱动程序的基础知识 (6)3.1 内核模式下的字符串操作 (6)3.2 内核模式下各种开头函数的区别 (8)3.3 一个示例程序 (10)3.4 补充说明 (10)四、在驱动中使用链表 (10)4.1 内存的分配与释放 (10)4.2 使用LIST_ENTRY (12)4.3 使用自旋锁 (12)五、在驱动中读写文件 (15)5.1 使用OBJECT_ATTRIBUTES (15)5.2 创建、打开文件 (16)5.3 读写文件操作 (16)5.4 文件的其它相关操作 (18)六、在驱动中操作注册表 (18)6.1 创建、打开注册表 (19)6.2 读写注册表 (20)6.3 枚举注册表 (21)七、在驱动中获取系统时间 (21)7.1 获取启动毫秒数 (21)7.2 获取系统时间 (22)八、在驱动中创建内核线程 (23)8.1 创建内核线程 (23)8.2 关于线程同步 (24)九、初探IRP (25)9.1 IRP的概念 (25)9.2 IRP的处理 (26)9.3 IRP派遣例程示例 (27)十、驱动程序与应用层的通信 (29)10.1 使用WriteFile通信 (29)10.2 使用DeviceIoControl进行通信 (32)十二、驱动程序开发实例 (33)12.1 NT驱动程序 (33)12.2 WDM驱动程序 (35)十三、参考资料 (41)一、驱动开发环境的搭建1.1 关于DDK开发驱动程序必备的一个东西就是DDK(Device Development Kit,设备驱动开发包),它跟我们在ring3常听到的SDK差不多,只不过它们分别支持开发不同的程序而已。

linux下devicedriver

linux下devicedriver

发信人: olly (剑胆琴心), 信区: Linux标题: LINUX下的设备驱动程序三、UNIX系统下的设备驱动程序3.1、UNIX下设备驱动程序的基本结构在UNIX系统里,对用户程序而言,设备驱动程序隐藏了设备的具体细节,对各种不同设备提供了一致的接口,一般来说是把设备映射为一个特殊的设备文件,用户程序可以象对其它文件一样对此设备文件进行操作。

UNIX对硬件设备支持两个标准接口:块特别设备文件和字符特别设备文件,通过块(字符)特别设备文件存取的设备称为块(字符)设备或具有块(字符)设备接口。

块设备接口仅支持面向块的I/O操作,所有I/O操作都通过在内核地址空间中的I/O缓冲区进行,它可以支持几乎任意长度和任意位置上的I/O请求,即提供随机存取的功能。

字符设备接口支持面向字符的I/O操作,它不经过系统的快速缓存,所以它们负责管理自己的缓冲区结构。

字符设备接口只支持顺序存取的功能,一般不能进行任意长度的I/O请求,而是限制I/O请求的长度必须是设备要求的基本块长的倍数。

显然,本程序所驱动的串行卡只能提供顺序存取的功能,属于是字符设备,因此后面的讨论在两种设备有所区别时都只涉及字符型设备接口。

设备由一个主设备号和一个次设备号标识。

主设备号唯一标识了设备类型,即设备驱动程序类型,它是块设备表或字符设备表中设备表项的索引。

次设备号仅由设备驱动程序解释,一般用于识别在若干可能的硬件设备中,I/O请求所涉及到的那个设备。

设备驱动程序可以分为三个主要组成部分:(1) 自动配置和初始化子程序,负责检测所要驱动的硬件设备是否存在和是否能正常工作。

如果该设备正常,则对这个设备及其相关的、设备驱动程序需要的软件状态进行初始化。

这部分驱动程序仅在初始化的时候被调用一次。

(2) 服务于I/O请求的子程序,又称为驱动程序的上半部分。

调用这部分是由于系统调用的结果。

这部分程序在执行的时候,系统仍认为是和进行调用的进程属于同一个进程,只是由用户态变成了核心态,具有进行此系统调用的用户程序的运行环境,因此可以在其中调用sleep()等与进程运行环境有关的函数。

eMMC 驱动架构分析

eMMC 驱动架构分析

void mmc_detectБайду номын сангаасchange(struct mmc_host *host, unsigned long delay) // core/core.c
{
mmc_schedule_delayed_work(&host->detect, delay);
}
static int mmc_schedule_delayed_work(struct delayed_work *work, unsigned long delay)
一.需要的基础知识: 1. LINUX 设备驱动的基本结构。 2. 块设备驱动程序的基本构架(相信研究过 LDD3 当中的 sbull 的人应该都不成问 题,如果只是走马观花的话,那可得好好再补补了)
3. LINUX 设备驱动模型。
4.
EMMC 的原理,是 Nand Flash 的基础上加上一个负责:ECC、负载均衡和坏块管
理功能的 controler。
二.驱动程序分析 首先,说明一下 EMMC 驱动涉及到的文件。另外,我们重点是分析驱动程序的基本构
架,所以不同内核版本的差异并不是很大。 MMC/SD 卡驱动程序位于 drivers/mmc 目录 下 Card/
block.c queue.c/queue.h core/ bus.c/bus.h core.c/core.h
(3) 主机控制器层
主机控制器则是依赖于不同的平台的,例如 s3c2410 的卡控制器和 atmel 的卡控制器必 定是不一样的,所以要针对不同的控制器来实现。以 s3cmci.c 为例,它首先要进行一些设 置,例如中断函数注册,全能控制器等等。然后它会向 core 层注册一个主机( host ), 用结构 mmc_host_ops 描述,这样核心层就可以拿着这个 host 来操作 s3c24xx 的卡控 制器了,而具体是 s3c24xx 的卡控制器还是 atmel 的卡控制器, core 层是不用知道的。

Rootkit技术

Rootkit技术

Rootkit技术rootkit的主要分类早期的rootkit主要为应用级rootkit,应用级rootkit主要通过替换login、ps、ls、netstat 等系统工具,或修改.rhosts等系统配置文件等实现隐藏及后门;硬件级rootkit主要指bios rootkit,可以在系统加载前获得控制权,通过向磁盘中写入文件,再由引导程序加载该文件重新获得控制权,也可以采用虚拟机技术,使整个操作系统运行在rootkit掌握之中;目前最常见的rootkit是内核级rootkit。

内核级rootkit又可分为lkm rootkit、非lkm rootkit。

lkm rootkit主要基于lkm技术,通过系统提供的接口加载到内核空间,成为内核的一部分,进而通过hook系统调用等技术实现隐藏、后门功能。

非lkm rootkit主要是指在系统不支持lkm机制时修改内核的一种方法,主要通过/dev/mem、/dev/kmem设备直接操作内存,从而对内核进行修改。

非lkm rootkit要实现对内核的修改,首先需要获得内核空间的内存,因此需要调用kmalloc分配内存,而kmalloc是内核空间的调用,无法在用户空间直接调用该函数,因此想到了通过int 0x80调用该函数的方法。

先选择一个不常见的系统调用号,在sys_call_table 中找到该项,通过写/dev/mem直接将其修改为kmalloc函数的地址,这样当我们在用户空间调用该系统调用时,就能通过int 0x80进入内核空间,执行kmalloc函数分配内存,并将分配好的内存地址由eax寄存器返回,从而我们得到了一块属于内核地址空间的内存,接着将要hack的函数写入该内存,并再次修改系统调用表,就能实现hook系统调用的功能。

rootkit的常见功能隐藏文件:通过strace ls可以发现ls命令其实是通过sys_getdents64获得文件目录的,因此可以通过修改sys_getdents64系统调用或者更底层的readdir实现隐藏文件及目录,还有对ext2文件系统直接进行修改的方法,不过实现起来不够方便,也有一些具体的限制。

如何安装和更新硬件驱动程序

如何安装和更新硬件驱动程序

如何安装和更新硬件驱动程序硬件驱动程序是与计算机硬件设备交互的关键组成部分。

通过正确安装和更新驱动程序,可以保证硬件设备正常运行,提升计算机性能和稳定性。

本文将详细介绍如何安装和更新硬件驱动程序的步骤和方法。

一、查找硬件信息在安装和更新硬件驱动程序之前,我们首先需要了解硬件设备的相关信息。

可以通过以下几种方式来查找硬件信息:1. 设备管理器:按下Win + X组合键,在弹出的菜单中选择"设备管理器",展开其中的设备列表,可以查看到已连接到计算机上的硬件设备信息。

2. 系统信息:按下Win + R组合键,打开"运行"对话框,输入"msinfo32",打开系统信息窗口。

在左侧的面板中选择"组件"下的"问题设备",可以查看到与硬件设备相关的信息。

3. 第三方软件:有许多第三方软件可以帮助我们快速查找硬件信息,例如CPU-Z、Speccy等。

通过它们,可以获得硬件设备的详细规格和型号。

二、下载驱动程序在得知硬件设备的相关信息后,我们需要找到相应的驱动程序进行下载。

以下是下载驱动程序的几种常见途径:1. 官方网站:前往硬件设备的官方网站,通常可以在其支持或下载页面找到相应的驱动程序。

在官方网站下载驱动程序可以确保其完整性和兼容性。

2. 驱动程序更新软件:许多厂商提供专门的驱动程序更新软件,例如Nvidia的GeForce Experience、Intel的驱动更新工具等。

这些软件可以自动检测并下载最新版本的驱动程序。

3. 第三方驱动程序网站:一些第三方网站收集了各种硬件设备的驱动程序,例如DriverPack Solution、Snappy Driver Installer等。

但要注意确保所下载的驱动程序来源可靠。

三、安装驱动程序在下载好驱动程序之后,我们需要进行安装。

以下是安装驱动程序的步骤:1. 解压驱动程序文件:有些驱动程序下载下来是一个压缩包文件,需要使用解压工具将其解压缩到一个文件夹中。

IO驱动

IO驱动

example
设备描述符 typedef struct ideDev { BLK_DEV blkDev; int drive; 设备号 int blkOffset; 偏移量 }xx_DEV;
块设备-驱动程序安装
n
(2)设计xxDrv()函数执行初始化。 和其他类型的设备驱动程序一样,块设 备也需要一个初始化程序.这个初始化 程序仅执行一些必要的初始化操作(例 如初始化驱动程序数据结构和分配内存 等)。但不会将驱动程序安装在IO系统 中或文件系统中.根据不同的设备,初 始化将执行不同的操作。
example
example
3、设备创建函数
n
设备创建函数xxDevCreate()的主耍作用 是创建逻辑设备。逻辑设备既可以是整 个物理设备也可以是物理设备的一部 分.在创建逻辑设备的过程中,应该初 始化相应的数据结构,并且所返回的数 据结构必须以BLK_DEV结构作为第一个成 员、文件系统里用这个返回值将文件系 统本身安装到设备上。该函数所使用的 参数根据设备的不同而不同。
数据结构
bd_bytesPerBlk:指明分块中包含的字节数. bd_lksPerTrack:指明每一个磁道包含的块的数目。 bd_nHeads:指明磁头数 bd_retry:指明遇到错误后重试的次数。 bd_mode:指明设备模式为O_RDONLY或者O_RDWR。 bd_readyChanged:这个值总是为TRUE。
块设备驱动与非块设备驱动
块设备的特点
n
Vxworks的IO系统是通过文件系统访问块设备的, 所以块设备的驱动程序函数的入口点不会安装到 驱动程序表中,块设备的描述符也不会连接到系 统的设备列表中。块设备驱动程序是由文件系统 来访问的,所以支持另外的一套驱动程序表。块 设备是以块为单位进行数据传输的,而字符设备 则是以字节为单位进行数据传输,这使块设备驱 动程序的功能也大为不同;同一个设备驱动程序 应该同时支持不同的文件系统。尽管块设备驱动 程序可以支持多种文件系统,但对于块设备本省 来说,是不用关心文件系统的存在的.

[知识]什么是驱动程序

[知识]什么是驱动程序

什么是驱动程序驱动程序一、什么是驱动程序根据百度百科:驱动程序,英文名为“Device Driver”,全称为“设备驱动程序”,是一种可以使计算机和设备通信的特殊程序,可以说相当于硬件的接口,操作系统只有通过这个接口,才能控制硬件设备的工作,假如某设备的驱动程序未能正确安装,便不能正常工作。

因此,驱动程序被誉为“ 硬件的灵魂”、“硬件的主宰”、和“硬件和系统之间的桥梁”等。

刚安装好的系统操作系统,很可能驱动程序安装得不完整。

硬件越新,这种可能性越大。

菜菜熊之前看到的“图标很大且颜色难看”就是没有安装好驱动的原因。

在软件测试中:在自底向上测试中,要编写称为测试驱动的模块调用正在测试的模块。

测试驱动模块以和将来真正模块同样的方式挂接,向处于测试的模块发送测试用例数据,接受返回结果,验证结果是否正确。

二、驱动程序的作用随着电子技术的飞速发展,电脑硬件的性能越来越强大。

驱动程序是直接工作在各种硬件设备上的软件,其“驱动”这个名称也十分形象的指明了它的功能。

正是通过驱动程序,各种硬件设备才能正常运行,达到既定的工作效果。

硬件如果缺少了驱动程序的“驱动”,那么本来性能非常强大的硬件就无法根据软件发出的指令进行工作,硬件就是空有一身本领都无从发挥,毫无用武之地。

这时候,电脑就正如古人所说的“万事俱备,只欠东风”,这“东风”的角色就落在了驱动程序身上。

如此看来,驱动程序在电脑使用上还真起着举足轻重的作用。

从理论上讲,所有的硬件设备都需要安装相应的驱动程序才能正常工作。

但像CPU、内存、主板、软驱、键盘、显示器等设备却并不需要安装驱动程序也可以正常工作,而显卡、声卡、网卡等却一定要安装驱动程序,否则便无法正常工作。

这是为什么呢?这主要是由于这些硬件对于一台个人电脑来说是必需的,所以早期的设计人员将这些硬件列为BIOS能直接支持的硬件。

换句话说,上述硬件安装后就可以被BIOS和操作系统直接支持,不再需要安装驱动程序。

第八章-嵌入式系统设计与应用—基于ARM...和Linux(第2版)-王剑-清华大学出版社

第八章-嵌入式系统设计与应用—基于ARM...和Linux(第2版)-王剑-清华大学出版社
int __check_region(struct resource *, resource_size_t, resource_size_t); 该函数的作用是查看系统I/O表,看是否有别的驱动程序占用 某一段I/O口。
struct resource * __request_region(struct resource *, resource_size_t start, resource_size_t n, const char *name, int
这两种方式在硬件实现上的差异对软件来说是完全可见的。
2. 并发控制 在驱动程序中经常会出现多个进程同时访问相同的 资源时可能会出现竞态(race condition),即竞争资 源状态,因此必须对共享资料进行并发控制。Linux 内核中解决并发控制最常用的方法是自旋锁 (spinlocks)和信号量(semaphores)。
1. 内存与 I/O 端口 编写驱动程序大多数情况下其本质都是对内存和 I/O 端口的操 作。 (1) 内存
Linux通常有以下几种地址 类型: 用户虚拟地址 物理地址 总线地址 内核逻辑地址 内核虚拟地址
(2)I/O 端口
有两个重要的内核调用可以保证驱动程序使用正确的端口,它 们定义在 include/linux/ioport.h 中。
8.1.1 Linux 设备驱动程序分类
1. 字符设备 字符设备是传输数据以字符为单位进行的设备,字符设备驱动 程序通常实现open、close、read和write等系统调用函数,常见 的字符设备有键盘、串口、控制台等。通过文件系统节点可以 访问字符设备,例如/dev/tty1和/dev/lp1。字符设备和普通文件 系统之间唯一的区别是普通文件允许往复读写,而大多数字符 设备驱动仅是数据通道,只能顺序读写。此外,字符设备驱动 程序不需要缓冲且不以固定大小进行操作,它与用户进程之间 直接相互传输数据。

嵌入式Linux网络编程和嵌入式Linux设备驱动开发

嵌入式Linux网络编程和嵌入式Linux设备驱动开发

结构字段常见值:sa_family:
(2)数据存储优先顺序
两种字节顺序:高位字节优先和低位字节优先,四个函数:htons,
ntohs,htonl,ntohl,分别实现网络字节序和主机字节序的转化, h—host, n—network, s—short, l--long
(3)地址格式转化
(4)名字地址转化
实现主机名和IP地址的转化,gethostbyname,gethostbyaddr,
getaddrinfo.实现IPv4和IPv6的地址好主机名之间的转化, gethostbyname是将主机名转化为IP地址,gethostbyaddr把IP地 址转化为主机名,getaddrinfo可自动识别IPv4和IPv6的地址。
3、设备驱动程序的主要组成 (1)设备注册:register_chrdev,调用该函数后向系统申请主设



备号,调用成功,设备名会出现在/proc/devices文件里。 关闭设备时,要解除设备注册unregister_chrdev (2)打开设备open主要完成: 递增计数器(用于设备计数,设备可能会被打开多次,可能由不 同进程打开,若想关闭此设备,就要保证其他进程或设备没有 使用该设备,用计数器实现此功能管理,有三个宏来实现操作)、 检查特殊设备的特殊情况、初始化设备、识别次设备号。 (3)释放设备release,与关闭设备不同,主要完成: 递减计数器和最后一次释放设备操作时关闭设备 (4)读写设备read write,即把内核空间的数据复制到用户空间, 或相反的操作。注意:用户空间的内存是可以被换出的,可能 出项页面失效,不能用memcpy函数,要用copy_to_user (5)获取内存:在设备驱动程序中动态开辟内存有两类:基于内 存地址(kmalloc返回物理地址),基于页面(3个函数) (6)打印信息:内核空间printk,不能用printf 4、proc文件系统:是内核和内核模块向进程发送信息的机制,让 用户可以与内核内部数据结构进行交互,获取进程的有用信息 p363 LCD驱动编写实例。

操作系统课程设计 内核模块编程和设备驱动程序

操作系统课程设计 内核模块编程和设备驱动程序

课程设计题目内核模块编程和设备驱动程序学生姓名朱小波学号**********专业计算机科学与技术班级20091121指导教师张莉莉完成日期2012年1月5日Linux内核模块编程与设备驱动程序摘要:本文给出了一个linux字符设备驱动程序的例子,其包括了内核模块编程.其主要功能是:在内存虚拟一个字符设备,并由编写的驱动程序加载到系统,完成字符的输入与输出功能.此设备驱动程序可以用作linux实践教学的实例.关键词:字符设备驱动;内核模块编程;虚拟;模拟1 前言驱动程序是应用程序和硬件设备的一个接口,linux设备驱动程序属于内核的一部分,熟练驱动程序和内核模块开发需要硬件知识,了解操作系统的实现,需要了解内核基础知识,了解内核中的并发控制和同步以及复杂的软件结构框架.本文论述了如何在linux下实现一个简单的字符设备驱动程序,主要完成了内核树的建立、内核的编译、字符设备的模拟、字符设备的驱动、字符设备驱动程序的测试等.本文首先阐述了设备驱动程序和内核模块编程的基础知识,然后给出了实现一个设备驱动程序的总体框架,最后根据框架一步步详细完成了一个字符设备驱动程序,包括终端命令和源程序的编写.做好设备驱动程序可以更好的了解硬件和操作系统,本设备驱动程序可以作为操作系统实验课程的实例.2 设备驱动程序和内核模块编程相关基础知识linux内核是一个整体是结构.因此向内核添加任何东西.或者删除某些功能,都十分困难.为了解决这个问题. 引入了内核机制.从而可以可以动态的想内核中添加或者删除模块.模块不被编译在内核中,因而控制了内核的大小.然而模块一旦被插入内核,它就和内核其他部分一样.这样一来就会增加一部分系统开销.同时,假如模块出现问题.,也许会带来系统的崩溃.2.1模块的实现机制:启动时,由函数 void inti_modules 来初始化模块,.因为启动事很多时候没有模块.这个函数往往把内核自身当作一个虚模块.如由系统需要,则调用一系列以sys 开头的函数,对模块进行操作. 如:sys_creat_modules,sys_inti_modules , sys_deldte_modules等等.这里会用到一些模块的数据就结构,在/usr/scr/linux/include/linux/module.h 中.块的加入有两种方法:一是手动加入:如:insmod modulename.另一种是根据需要,动态的加载模块.如你执行命令:$mount -t msdos /dev/hdd /mnt/d 时.系统便自动加载 FAT模块,以支持MSDOS 的文件系统.2.2 模块编程写一个模块,必须有一定的多进程编程基础.因为编的程序不是以一个独立的程序的来运行的.另外,因为,模块需要在内核模式下运行,会碰到内核空间和用户空间数据交换的问题.一般的数据复制函数无法完成这一个过程.因此系统已入了一些非凡的函数以用来完成内核空间和用户空间数据的交换. 这些函数有:void put _user、memcpy_tofs 等等,需要说明的是.模块编程和内核的版本有很大的关系. 假如版本不通可能造成,内核模块不能编译,或者.在运行这个模块时,出现不可测结果.如:系统崩溃等.对于每一个内核模块来说.必定包含两个函数:int init_module :这个函数在插入内核时启动,在内核中注册一定的功能函数,或者用它的代码代替内核中某些函数的内容.因此,内核可以安全的卸载.int cleanup_module:当内核模块卸载时调用.将模块从内核中清除.2.3内核模块与应用程序对比应用程序是一个进程,编程从主函数main()开始,主函数main返回即是进程结束,使用glibc的库.驱动程序是一系列内核函数,函数入口和出口不一样,使用Linux内核的函数,这些函数由内核在适当的时候来调用,这些函数可以用来完成硬件访问等操作.2.4设备的分类设备一般分为字符设备(char device)、块设备(block device)、网络设备(network device).图1:设备的分类i字符设备特点:像字节流一样来存取的设备( 如同文件 )通过/dev下的文件系统结点来访问通常至少需要实现 open, close, read, 和 write 等系统调用只能顺序访问的数据通道,不能前后移动访问指针.特例:比如framebuffer设备就是这样的设备,应用程序可以使用mmap或lseek访问图像的各个区域ii块设备特点:块设备通过位于 /dev 目录的文件系统结点来存取块设备和字符设备的区别仅仅在于内核内部管理数据的方式块设备有专门的接口,块设备的接口必须支持挂装(mount)文件系统.应用程序一般通过文件系统来访问块设备上的内容图2:块设备驱动图3:网络设备驱动linux中的大部分驱动程序,是以模块的形式编写的.这些驱动程序源码可以修改到内核中,也可以把他们编译成模块形式,在需要的时候动态加载.一个典型的驱动程序,大体上可以分为这么几个部分:1,注册设备在系统初启,或者模块加载时候,必须将设备登记到相应的设备数组,并返回设备的主驱动号,例如:对快设备来说调用 refister_blkdec将设备添加到数组blkdev中.并且获得该设备号.并利用这些设备号对此数组进行索引.对于字符驱动设备来说,要使用 module_register_chrdev来获得祝设备的驱动号.然后对这个设备的所有调用都用这个设备号来实现.图4:内核模块调用过程2,定义功能函数对于每一个驱动函数来说.都有一些和此设备密切相关的功能函数.那最常用的块设备或者字符设备来说.都存在着诸如 open read write ioctrol这一类的操作.当系统社用这些调用时.将自动的使用驱动函数中特定的模块.来实现具体的操作.而对于特定的设备.上面的系统调用对应的函数是一定的. 如:在块驱动设备中.当系统试图读取这个设备时),就会运行驱动程序中的block_read 这个函数. 打开新设备时会调用这个设备驱动程序的device_open 这个函数.3,卸载模块在不用这个设备时,可以将它卸载.主要是从/proc 中取消这个设备的文件.可用特定的函数实现.3 设备驱动程序实现框架4 数据结构设计与主要功能函数(1)字符设备描述结构体:struct cdev {struct kobject kobj; /*内嵌的kobject对象*/struct module *owner; /*所属模块*/const struct file_operations *ops; /*文件操作结构体*/struct list_head list; /*双向循环链表*/dev_t dev; /*设备号32位高12位为主设备号,低20位为次设备号*/unsigned int count; /*设备数量*/};(2) 设备描述结构体struct mem_dev{char *data; /*数据*/unsigned long size; /*长度*/};表1 主要功能函数列表主要函数列表功能说明int mem_open(struct inode *inode, struct file *filp) 文件打开int mem_release(struct inode *inode, struct file *filp) 文件释放读文件static ssize_t mem_read(struct file *filp, char __user *buf, size_tsize, loff_t *ppos)写文件static ssize_t mem_write(struct file *filp, const char __user *buf,size_t size, loff_t *ppos)static loff_t mem_llseek(struct file *filp, loff_t offset, int whence) 文件定位static int memdev_init(void) 设备驱动模块加载static void memdev_exit(void) 卸载设备5 字符设备驱动程序的实现下载安装LINUX内核,需要下载和本机一样版本的内核源码.本设备驱动程序是在linux-3.0.12内核下进行的.5.1 安装编译内核所需要的软件并编译内核.使用以下命令安装需要的软件:sudo apt-get install build-essential autoconf automake cvs subversion kernel-package libncurses5-dev图5:安装所需软件在/pub/linux/kernel/v3.0/ 下载内核linux-3.0.12.tar.bz2将内核放置/usr/src目录下使用命令tar解压sudo tar jxvf linux-3.0.12.tar.bz2图6:解压内核使用以下命令配置系统cd linux-3.0.12cp /boot/config-`uname -r` ./.config #拷贝目前系统的配置文件make menuconfig终端会弹出一个配置界面最后有两项:load a kernel configuration... (.config)、save a kernel configuration... (.config) 选择load a kernel configuration保存,然后在选择save akernel configuration再保存退出,并退出配置环境.图7:配置系统参数make #这步需要比较长时间make bzImage #执行结束后,可以看到在当前目录下生成了一个新的文件: vmlinux, 其属性为-rwxr-xr-x.make modules #/* 编译模块*/make modules_install #这条命令能在/lib/modules目录下产生一个目录图8:make内核图9:make bzImage图10:make modules图11:make modules_installcd /usr/includerm -rf asm linux scsiln -s /usr/src/linux-3.0.12/include/asm-generic asmln -s /usr/src/linux-3.0.12/include/linux linuxln -s /usr/src/linux-3.0.12/include/scsi scsi5.2 编写字符设备驱动程序并调试编译.cd /rootmkdir firstdrivertouch memdev.c #建立驱动程序文件touch memdev.h #头文件touch Makefile #编写Makefile编译驱动程序模块make -C /lib/modules/3.0.0-12-generic/build M=/root/firstdriver modules图12:make 驱动程序ls查看当前目录的内容root@cloudswave-VirtualBox:~/firstdriver# lsMakefile memdev.h memdev.mod.c memdev.o Module.symversmemdev.c memdev.ko memdev.mod.o modules.order这里的memdev.ko就是生成的驱动程序模块.通过insmod命令把该模块插入到内核root@cloudswave-VirtualBox:~/firstdriver# insmod memdev.ko查看插入的memdev.ko驱动图13:查看插入的memdev.ko驱动可以看到memdev驱动程序被正确的插入到内核当中,主设备号为88,该设备号为如果这里定义的主设备号与系统正在使用的主设备号冲突,比如主设备号定义如下:#define MEMDEV_MAJOR 254,那么在执行insmod命令时,就会出现如下的错误:root@cloudswave-VirtualBox:~/firstdriver# insmod memdev.koinsmod: error inserting 'memdev.ko': -1 Device or resource busy5.3.测试驱动程序1,首先应该在/dev/目录下创建与该驱动程序相对应的文件节点,使用如下命令创建:root@cloudswave-VirtualBox:/dev# mknod memdev0 c 88 0使用ls查看创建好的驱动程序节点文件root@cloudswave-VirtualBox:/dev# ls -al memdev0图14:驱动程序节点文件2,编写如下应用程序memtest.c,来对驱动程序进行测试.编译并执行该程序root@cloudswave-VirtualBox:~/firstdriver# gcc -o memtest memtest.croot@cloudswave-VirtualBox:~/firstdriver# ./memtest图15:程序测试驱动手动测试驱动的方法:root@cloudswave-VirtualBox:~/firstdriver# echo 'haha shi wo' > /dev/memdev0root@cloudswave-VirtualBox:~/firstdriver# cat /dev/memdev06.小结:LINUX使用make编译驱动程序模块的过程.Linux内核是一种单体内核,但是通过动态加载模块的方式,使它的开发非常灵活、方便.那么,它是如何编译内核的呢?我们可以通过分析它的Makefile入手.以下是一个当我们写完一个hello模块,编写类似以上的Makefile.然后用命令make编译.假设我们把hello模块的源代码放在/home/examples/hello/下.当我们在这个目录运行make时,make是怎么执行的呢?首先,由于make后面没有目标,所以make会在Makefile中的第一个不是以.开头的目标作为默认的目标执行.于是default成为make的目标.make会执行make-C/lib/modules/3.0.0-12-generic/build M=/home/examples/hello/modules是一个指向内核源代码/usr/src/linux的符号链接.可见,make执行了两次.第一次执行时是读hello模块的源代码所在目录/home/examples/hello/下的Makefile.第二次执行时是执/usr/src/linux/下的Makefile.7 结束语本文给出了一个字符设备驱动与内核模块编程的完整实例,可以从中掌握内核编译、内核编程基础、设备驱动程序开发基础,优点是比较详细的给出了驱动开发的流程,并且把每一步的操作进行了详细的说明包括要执行的终端命令.最后还分析了驱动编译的过程.这样有利于初学者了解学习设备驱动的开发.有待进一步改进之处在于:此设备驱动程序针对的是字符设备,实现的功能比较简单,以后有时间可根据这次的开发流程,参考api编写块设备和网络设备的驱动程序.参考文献[1]Abraham Silberschatz 操作系统概念(第七版)影印版高等教育出版社,2007 [2]费翔林Linux操作系统实验教程高等教育出版社,2009[3](美)博韦等(DanielP. Bovet) 编著深入理解LINUX内核北京:中国电力出版社,2008 [4]Jonahan Corbet编著Linux设备驱动程序北京:中国电力出版社,2005附录。

计算机操作系统课后答案第9章习题解答

计算机操作系统课后答案第9章习题解答

第9章习题解答一、填空1.MS-DOS操作系统由BOOT、IO.SYS、MSDOS.SYS以及 所组成。

2.MS-DOS的一个进程,由程序(包括代码、数据和堆栈)、程序段前缀以及环境块三部分组成。

3.MS-DOS向用户提供了两种控制作业运行的方式,一种是批处理方式,一种是命令处理方式。

4.MS-DOS存储管理规定,从地址0开始每16个字节为一个“节”,它是进行存储分配的单位。

5.MS-DOS在每个内存分区的前面都开辟一个16个字节的区域,在它里面存放该分区的尺寸和使用信息。

这个区域被称为是一个内存分区所对应的内存控制块。

6.MS-DOS有4个存储区域,它们是:常规内存区、上位内存区、高端内存区和扩充内存区。

7.“簇”是MS-DOS进行磁盘存储空间分配的单位,它所含扇区数必须是2的整数次方。

8.当一个目录表里仅包含“.”和“..”时,意味该目录表为空。

9.在MS-DOS里,用文件名打开文件,随后就通过句柄来访问该文件了。

10.在MS-DOS里,把字符设备视为设备文件。

二、选择1.下面对DOS的说法中,B 是正确的。

A.内、外部命令都常驻内存B.内部命令常驻内存,外部命令非常驻内存C.内、外部命令都非常驻内存D.内部命令非常驻内存,外部命令常驻内存2.DOS进程的程序,在内存里 D 存放在一起。

A.总是和程序段前缀以及环境块B.和谁都不C.总是和进程的环境块D.总是和程序段前缀3.MS-DOS启动时能够自动执行的批处理文件名是: C 。

A.CONFIG.SYS B.MSDOS.SYSC.AUTOEXEC.BAT D.4.下面所列的内存分配算法, D 不是MS-DOS采用的。

A.最佳适应法B.最先适应法C.最后适应法D.最坏适应法5.在MS-DOS里,从1024K到1088K的存储区域被称为 D 区。

A.上位内存B.扩展内存C.扩充内存D.高端内存6.MS-DOS的存储管理是对A的管理。

A.常规内存B.常规内存和上位内存C.常规内存和扩展内存D.常规内存和扩充内存7.在下面给出的MS-DOS常用扩展名中,B 不表示一个可执行文件。

基于RTLinux的运动控制器MC400D驱动程序设计

基于RTLinux的运动控制器MC400D驱动程序设计

文章编号:1006-1576(2005)01-0084-02基于RTLinux的运动控制器MC400D驱动程序设计晏密英,刘刚,李慧霸(中南林学院电子与信息工程学院,湖南长沙 410004)摘要:基于RTLinux的MC400D运动控制卡PCI接口,采用DSP和CPLD相结合的结构。

控制程序包括系统设置函数,伺服控制、轴、运动和极限等参数函数,位置捕获及中断处理和参数更新函数等。

设备驱动程序设计为块设备驱动程序,用函数直接访问卡上的原有资源,通过设定运动控制参数完成设备驱动,实现对电机控制。

关键词:RTLinux;运动控制器;驱动程序中图分类号:TP311.11; TP391.8 文献标识码:ADesign of Driver for Motion Controller MC400D Based on RTLinuxYAN Mi-ying, LIU Gang, LI Hui-ba(College of Electronic & Information Engineering, Central-South Forestry University, Changsha 410004, China) Abstract: The structure combined DSP and CPLD was applied in PIC interface card of MC400D (motion controller) based on RTLinux. The device driver of MC400D includes setting functions, parameter of servo control, axis parameter, movement and margin parameter, and parameter of captured position, interrupt processing parameter and the function of updating parameter. The driver of device is a module driver, and the original source in PIC interface card is accessed with functions. The drive of device was completed through setting parameters of the motion controller, and then the control of motor was realized.Keywords: RTLinux; Motion controller; Driver program1 引言90年代后,实时多任务操作系统(RTOS)已逐步成为嵌入式系统的主流[1][2]。

Linux系统分析——devicedrivers

Linux系统分析——devicedrivers

kfree_s()
设备号由主、次设备号拼接而成。
#define MAJOR(dev) ((dev)>>8) #define MINOR(dev) ((dev)&0xff)
辅助函数——设备的注册和注销
int register_chrdev(unsigned int major, const char *name,
ISA VESA EISA PCI
驱动程序基础——命名空间
并行设备:lp
软盘:fd SCSI盘:sd IDE硬盘:hda1, hda2, hdb等 网络设备:ethn, slipn, pppn等 在写驱动程序的时候,需要给函数名加 上选择的前缀来避免任何混淆。如: foo_read(),foo_write()等。
驱动程序基础——中断vs轮询
工作机制的区别
编程上的区别:
UNIX的系统调用:执行模式的改变 内核模式下的进程访问进程原来所在的用户空间的存 储:get_fs_*()和memcpy_fromfs()读用户空间, put_fs_*()和memcpy_tofs()写入用户空间内存。在进程 运行时调用,不需要考虑地址的问题。 在中断发生时,这些宏不能使用。因为它们可能覆盖 其他运行着的进程的随机空间。必须提供临时空间存 放信息。 对于块设备,由cache缓冲机制自动提供;字符设备需 要驱动程序分配。
ioctl()函数:处理ioctl调用。
结构:首先差错检查,然后用一个大的switch语句来处
理所有可能的ioct。
参数:
Struct inode *inode Struct file *file Unsigned int cmd :ioctl命令。一般用于做case语句的 switch参数。 Unsigned int arg 这是此命令的参数,由用户定义。

块设备读写流程

块设备读写流程

1、用户态程序通过open()打开指定的块设备,通过systemcall机制陷入内核,执行blkdev_open()函数,该函数注册到文件系统方法(file_operations)中的open上。

在blkdev_open函数中调用bd_acquire()函数,bd_acquire函数完成文件系统inode到块设备bdev的转换,具体的转换方法通过hash查找实现。

得到具体块设备的bdev之后,调用do_open()函数完成设备打开的操作。

在do_open函数中会调用到块设备驱动注册的open 方法,具体调用如下:gendisk->fops->open(bdev->bd_inode, file)。

2、用户程序通过read、write函数对设备进行读写,文件系统会调用相应的方法,通常会调用如下两个函数:generic_file_read和blkdev_file_write。

在读写过程中采用了多种策略,首先分析读过程。

3、用户态调用了read函数,内核执行generic_file_read,如果不是direct io方式,那么直接调用do_generic_file_read->do_generic_mapping_read()函数,在do_generic_mapping_read(函数位于filemap.c)函数中,首先查找数据是否命中Cache,如果命中,那么直接将数据返回给用户态;否则通过address_space->a_ops->readpage函数发起一个真实的读请求。

在readpage函数中,构造一个buffer_head,设置bh回调函数end_buffer_async_read,然后调用submit_bh发起请求。

在submit_bh函数中,根据buffer_head构造bio,设置bio的回调函数end_bio_bh_io_sync,最后通过submit_bio 将bio请求发送给指定的快设备。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

18.5.1 数据从内存到磁盘的过程
内存是一个线性的结构,Linux系统将内存分为页。一页 最大可以是64K,但是目前主流的系统页的大小都是4K。现在 假设数据存储在内存的相邻几页中,希望将这些数据写到磁盘 上。那么每一页的数据会被先封装为一个段,用bio_vec表示。 多个页会被封装成多个段,这些段被组成以一个bio_vec为元素 的数组,这个数组用bio_io_vec表示。
queue_head
request request
rq_disk
queuelist
bio bio_tail
request request
rq_disk
queuelist
bio bio_tail
bio bio bi_next bi_idx bio_io_vec
bio_vec bio_vec
page bv_len bv_offset
磁盘/硬盘等
18.1.2 块设备的结构
在写块设备驱动程序之前,了解典型块设备的结构是非 常重要的。图显示的是磁盘的一个盘面,一些重要的概念将 在下面讲述。
磁道
扇区
10% 101%011%010%011%%001%%0111%0001%%%011%0011%%010%01%%01%0% 101%011%010%011%%001%%0111%0001%%%011%0011%%010%01%%01%0%
18.5.5 请求队列、请求结构、bio等之间的关系
可能读者对请求队列request_queue、请求结构request、 bio、bio_vec、gendisk等结构的关系还并不清楚,除了建议读者 查阅内核源码外,认真查看图也是不错的方法。块设备Βιβλιοθήκη gendisk gendisk
queue
request_queue request_queue
page bv_len bv_offset
系统调用
虚拟文件系统
通用磁盘(gendisk) 请求结构体(request) 请求队列request_queue
块设备IO(bio) 分区表(hd_struct)
...
磁盘文件系统 通用块层 I/O调度器
块设备驱动程序
预期算法(Anticipatory) 最后期限算法(Deadline)
完全公平算法(CFQ) Noop算法(No Operation)
18.5.2 块I/O请求(bio)
数据从内存到磁盘或者从磁盘到内存的过程,叫做I/O操 作。内核使用一个核心数据结构bio来描述I/O操作。
1.bio结构体 bio结构体包含一个块设备完成一次I/O操作所需要的一切 信息。 2.bio_vec结构体 bio中的段用bio_vec结构体来表示。 3.bio结构体的相关宏 为了程序的可移植性,在写驱动程序时,不应该直接的操 作bio结构和bi_io_vec数组,而应该使用内核开发者提供的一 系列宏。由于在驱动中会使用这些宏,这里对其主要的宏进行 介绍。
18.5 I/O调度器
Linux内核中,I/O调度器涉及到很多复杂的数据结构,而 结构之间的关系又非常复杂。要精通这些知识,远非一章一节 知识所能够达到。但本节力图给读者一个清晰的概念,随着内 核的升级,这些概念可能有所细微的变化,但是其主要的原理 是基本不会变化的。在详细讲解I/O调度器之前,需要知道数 据是怎样从内存到达磁盘的。
18.3.3 块设备的注册和注销
为了使内核知道块设备的存在,需要使用块设备注册函 数。在不使用块设备时,也需要注销块设备。块设备的注册 和注销如下所述:
1.注册块设备函数register_blkdev() 2.注销块设备函数unregister_blkdev()
18.3.4 请求队列
简单的讲,一个块设备的请求队列就是包含块设备I/O请求的一 个队列。这个队列使用链表线性的排列。请求队列中存储未完成的块 设备I/O请求,并不是所有的I/O块请求都可以顺利的加入请求队列中 。请求队列中定义了自己能处理的块设备请求限制。这些限制包括: 请求的最大尺寸、一个请求能够包含的独立段数、硬盘扇区大小等。
分配磁盘 alloc_disk()
注册设备 register_blkdev()(可选)
不使用请求队列 blk_init_queue()
使用请求队列 blk_alloc_queue()
磁盘gendisk属性设置
激活磁盘add_disk()
18.2.2 块设备卸载过程
在块设备驱动的卸载模块中完成与模块加载函数相反的工作 。
18.3 通用块层
通用块层是块设备驱动的核心部分,这部分主要包含块 设备驱动程序的通用代码部分。本节将介绍通用块层的主要 函数和数据结构。
18.3.1 通用块层
通用块层是一个内核组件,它处理来自系统其他组件发出的块设
备请求。换句话说,通用块层包含了块设备操作的一些通用函数和数
据结构。图是块设备加载函数中用到的一些重要数据结构,如通用磁 盘结构gendisk、请求队列结构request_queue、请求结构request、块 设备I/O操作结构bio、块设备操作结构block_device_operations等。这 些结构将在下面的几小节详细简述。
18.1 块设备简介
本节对块设备的相关概念进行了简要的分析。理解这些 概念对写块设备驱动程序具有十分重要的意义。
18.1.1 块设备总体概述
Linux内核中,I/O设备大致分为两类:块设备和字符设备。块 设备将信息存储在固定大小的块中,每个块都有自己的地址。数据块 的大小通常在512字节到4K字节之间。块设备的基本特征是每个块都 能独立于其它块而读写。磁盘就是最常见的块设备。在Linux内核中 ,块设备与内核其他模块的关系如图所示:
第18章 块设备驱动程序
除了字符设备、网络设备外,Linux系统中还有块设备。字符 设备和块设备在内核中的结构有很大的不同,总体来说,块设备要 比字符设备复杂很多。块设备主要包含磁盘设备、SD卡等,这些设 备是Linux系统中不可缺少的存储设备。计算机中都需要这样的设 备来存储数据,所以学会块设备驱动程序的写法是非常重要的。
18.4 不使用请求队列的块设备驱动
这里,有两个原因需要向读者介绍不使用请求队列的块 设备驱动程序。第一个原因是,希望尽快的向读者展现一个 完整的块设备驱动程序;第二个原因是,不使用请求队列的 块设备驱动程序相对来说,比较简单。
18.4.1 不使用请求队列的块设备驱动程序的 组成
块设备函数驱动程序主要有一个加载函数、卸载函数和 一个自定义的请求处理函数组成。本节将写一个虚拟的块设备 驱动程序Virtual_blkdev。这个驱动程序在内存中开辟了一个 8M的内存空间来模拟实际的物理块设备。这个块设备驱动程 序代码比较简单,但功能却非常强大。对实际物理设备的操作 命令同样可以应用在Virtual_blkdev这个块设备上,例如 mkdir、mkesfs等命令。
18.4.2 宏定义和全局变量
Virtual_blkdev块设备驱动中定义了一些重要的宏和全 局指针,包括主设备号、设备名、设备的大小等。
18.4.3 加载函数
Virtual_blkdev设备的加载函数主要完成分配磁盘、初 始化请求队列、设置磁盘属性和激活磁盘的工作。
18.4.4 卸载函数
Virtual_blkdev设备的卸载函数中主要完成与设备加载 函数中相反的工作:
18.3.5 设置gendisk属性中的 block_device_operations结构体
在块设备中有一个和字符设备中file_operations对应的结 构体block_device_operations。其也是一个对块设备操作的函 数集合。
下面对这个结构体的主要成员进行分析。 1.打开和释放函数 2.I/O控制函数 3.介质改变函数 4.使介质有效函数 5.获得驱动器信息的函数 6.模块指针
(1)使用del_gendisk()函数删除gendisk设备。 (2)使用put_disk()函数清楚gendisk的引用计数。 (3)使用blk_cleanup_queue()函数清除请求队列。
18.4.5 自定义请求处理函数
内核将I/O读写请求放入请求结构request中,并连接到请 求队列request_queue中。因为Virtual_blkdev设备是一个基于 内存的设备,可以随机读取数据,并不需要复杂的I/O调度( I/O调度的作用是对请求结构request进行排序,最大限度的提 高读写速率)。所以当请求到来时,将直接使用 blk_init_queue()函数中注册的请求处理函数 Virtual_blkdev_do_request()函数,对请求进行实际的操作。这 里的操作就是将数据赋值的Virtual_blkdev设备或者从 Virtual_blkdev设备中读取数据。
(1)使用del_gendisk()函数删除gendisk设备,并使用 put_disk()函数删除对gendisk设备的引用。
(2)使用blk_cleanup_queue()函数清除请求队列,并释放 请求队列所占用的资源。
(3)如果在模块加载函数中使用了register_blkdev()注册设 备,那么需要在模块卸载函数中使用unregister_blkdev()函数注 销块设备,并释放对块设备的引用。
18.5.3 请求结构(request)
几个连续的页面会组成一个bio结构,几个相邻的bio结 构就会组成一个请求结构request。这样当磁盘在接收一个与 request对应的命令,就不需要大幅度的移动磁头,这样就节 省了I/O操作的时间。
18.5.4 请求队列(request_queue)
每个块设备驱动程序都维护着自己的请求队列 request_queue,其包含设备将要处理的请求链表。请求队列 主要用来连接对同一个块设备的多个request请求结构。同时 请求队列中的一些字段还保存了块设备所支持的请求类型信息 、请求的个数、段的大小、硬件扇区数等与设备相关的信息。 总之,内核负责对请求队列的正确配置,使请求队列不会给块 设备发送一个不能处理的请求。
相关文档
最新文档