《深入浅出+Linux字符设备驱动程序解析》由会员分享,可在线阅读,更多相关《深入浅出+Linux字符设备驱动程序解析(8页珍藏版)》请在金锄头文库上搜索。
1、深入浅出 符设备驱动程序解析的设备驱动程序被组织为一组完成不同任务的函数的集合,通过这些函数使得设备操作犹如文件一般。在应用程序看来,硬件设备只是一个设备文件,应用程序可以象操作普通文件一样对硬件设备进行操作,如 。要将设备分为二类:字符设备和块设备。字符设备是指设备发送和接收数据以字符的形式进行;而块设备则以整个数据缓冲区的形式进行。字符设备的驱动相对比较简单。下面我们来假设一个非常简单的虚拟字符设备:这个设备中只有一个 4 个字节的全局变量这个设备的名字叫做 对备的读写等操作即是对其中全局变量 操作。驱动程序是内核的一部分,因此我们需要给其添加模块初始化函数,该函数用来完成对所控设备的初始
2、化工作,并调用 数注册字符设备:_ , &/注册失败注册成功 其中,数中的参数 主设备号 , 设备名,包含基本函数入口点的结构体,类型为 块被加载时,执行,它将调用内核函数 驱动程序的基本入口点指针存放在内核的字符设备地址表中,在用户进程对该设备执行系统调用时提供入口地址。 与模块初始化函数对应的就是模块卸载函数,需要调用 反函数 _ )/卸载失败卸载成功 随着内核不断增加新的功能,构体已逐渐变得越来越大,但是大多数的驱动程序只是利用了其中的一部分。对于字符设备来说,要提供的主要入口有:。 数对设备特殊文件进行 统调用时,将调用驱动程序的 数: * ,); 其中参数 设备特殊文件的 索引结点)
3、 结构的指针,参数 指向这一设备的文件结构的指针。主要任务是确定硬件处在就绪状态、验证次设备号的合法性(次设备号可以用 i - 取得) 、控制使用设备的进程数、根据执行情况返回状态码(0 表示成功,负数表示存在错误) 等; 数当最后一个打开设备的用户进程执行 统调用时,内核将调用驱动程序的 数: *( ,) ; 数的主要任务是清理未结束的输入/输出操作、释放资源、用户自定义排他标志的复位等。 数当对设备特殊文件进行 统调用时,将调用驱动程序 数: *(, , ); 用来从设备中读取数据。当该函数指针被赋为 时,将导致 统调用出错并返回法参数 ) 。函数返回非负值表示成功读取的字节数(返回值为据
4、类型,通常就是目标平台上的固有整数类型) 。 数中内核空间与用户空间的内存交互需要借助第 2 节所介绍的函数: &; ) 函数当设备特殊文件进行 统调用时,将调用驱动程序的 数: *(, , ); 向设备发送数据。如果没有这个函数,系统调用会向调用程序返回一个果返回值非负,则表示成功写入的字节数。 数中内核空间与用户空间的内存交互需要借助第 2 节所介绍的函数: ; 数该函数是特殊的控制函数,可以通过它向设备传递控制信息或从设备取得状态信息,函数原型为: *( , , 数为设备驱动程序要执行的命令的代码,由用户自定义,数为相应的命令提供参数,类型可以是整型、指针等。如果设备不提供 口点,则对于
5、任何内核未预先定义的请求,系统调用将返回错误(No 设备无此 令 ) 。如果该设备方法返回一个非负值,那么该值会被返回给调用程序以表示调用成功。 数 该函数用来修改文件的当前读写位置,并将新位置作为(正的)返回值返回,原型为: *(, 数 法是 两个系统调用的后端实现,用来查询设备是否可读或可写,或是否处于某种特殊状态,原型为: *(, ); 我们将在 设备的阻塞与非阻塞操作 一节对该函数进行更深入的介绍。 设备驱动程序的这些函数应分别命名为 因此设备基本入口点结构变量 值如下: ; 上述代码中对 初始化方法并不是标准 C 所支持的,属于 展语法。 完整的 件源代码如下: #;#54 /主设备号, , ;, , ;/初始化字符设备驱动的 构体; 0; /备的全局变量_( &;_(;/将 内核空间复制到用户空间&) ( ) 运行:I /,运行:载 块,再运行:现其中多出了254 行,如下图:接着我们可以运行:c 254 0 创建设备节点,用户进程通过/个路径就可以访问到这个全局变量虚拟设备了。我们写一个用户态的程序 验证上述设备:#/