了解并学习Linux设备驱动的基础知识

网友投稿 277 2022-10-25

了解并学习Linux设备驱动的基础知识

设备驱动与硬件的关系

设备分类

Linux对将外设分为3类:

字符设备指那些必须以串行顺序依次进行访问的设备,如触摸屏、磁带驱动器、鼠标等。

块设备

块设备可以用任意顺序进行访问,以块为单位进行操作,如硬盘、软驱等。

网络设备

网络设备面向数据包的接收和发送而设计,它并不对应于文件系统的节点。

总体框图

机制与策略

机制强调“提供什么能力”,而策略旨在“如何使用这些能力”。因此驱动开发需要遵守的是驱动程序的角色是提供机制, 而不是策略。 编写内核代码来存取硬件, 但是不能强加特别的策略给用户, 因为不同的用户有不同的需求。驱动应当做到使硬件可用, 将所有关于如何使用硬件的事情留给应用程序。

内核模块

Linux 提供了一种代码动态地加载到内核中机制,这种机制被称为模块(Module)。具有如下特点:

模块本身不被编译入内核映像, 从而控制了内核的大小。

模块一旦被加载,它就和内核中的其他部分完全一样。

可动态加载与移除,不需重启系统,节约开发时间。

模块放在用户空间,这部分代码可以不开源。

因此驱动多数情况以内核模块的形式加载到内核。

组成

一个 Linux 内核模块主要由如下几个部分组成:

模块加载函数(一般需要)

模块卸载函数(一般需要)

当通过 rmmod 命令卸载某模块时,模块的卸载函数会自动被内核执行,完成与模块卸载函数相反的功能。static void __exit cleanup_function(void){ /* 释放代码 */}module_exit(cleanup_function);

模块参数(可选)

模块导出符号(可选)

内核模块可以导出符号( symbol,对应于函数或变量),这样其他模块可以使用本模块中的变量或函数。EXPORT_SYMBOL(符号名);EXPORT_SYMBOL_GPL(符号名);

编译

重要的数据结构

大部分的基础性的驱动操作包括3个重要的内核数据结构, 称为 file_operations, file, 和 inode。

file_operations

file_operations 结构体中的成员函数是设备驱动程序设计的主体内容,这些函数实际会在应用程序进行 Linux 的 open()、 write()、 read()、 close()等系统调用时最终被调用。

file

file 结构体代表一个打开的文件(设备对应于设备文件),系统中每个打开的文件在内核空间都有一个关联的 struct file。它由内核在打开文件时创建,并传递给在文件上进行操作的任何函数。在文件的所有实例都关闭后,内核释放这个数据结构。

struct file { const struct file_operations *f_op; /* 和文件关联的操作*/ unsigned int f_flags; /*文件标志,如 O_RDONLY、 O_NONBLOCK、 O_SYNC*/ fmode_t f_mode; /*文件读/写模式, FMODE_READ 和 FMODE_WRITE*/ loff_t f_pos; /* 当前读写位置*/ void *private_data; /*文件私有数据,可存储自定义数据的指针*/ ...};

inode

VFS inode 包含文件访问权限、属主、组、大小、生成时间、访问时间、最后修改时间等信息。它是 Linux 管理文件系统的最基本单位,也是文件系统连接任何子目录、文件的桥梁。

struct inode { umode_t i_mode; /* inode 的权限 */ uid_t i_uid; /* inode 拥有者的 id */ gid_t i_gid; /* inode 所属的群组 id */ dev_t i_rdev; /* 若是设备文件,此字段将记录设备的设备号 */ loff_t i_size; /* inode 所代表的文件大小 */ struct timespec i_atime; /* inode 最近一次的存取时间 */ struct timespec i_mtime; /* inode 最近一次的修改时间 */ struct timespec i_ctime; /* inode 的产生时间 */ unsigned long i_blksize; /* inode 在做 I/O 时的区块大小 */ unsigned long i_blocks; /* inode 所使用的 block 数,一个 block 为 512 byte*/ struct block_device *i_bdev; /*若是块设备,为其对应的 block_device 结构体指针*/ struct cdev *i_cdev; /*若是字符设备,为其对应的 cdev 结构体指针*/ ...};

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:关于ARM 架构处理器的产品特点介绍
下一篇:太拼了!腾讯T4大佬凌晨4点还在熬夜,竟然是在整理这份Docker
相关文章

 发表评论

暂时没有评论,来抢沙发吧~