字符设备
对字符设备发出读/写请求时,实际的硬件I/O操作一般紧接着发生
块设备
块设备与之相反,它利用系统内存作为缓冲区
网络设备
网络设备是一类特殊的设备,它不像字符设备或块设备那样通过对应的设备文件节点访问,也不能直接通过read或write进行数据访问请求
主设备号和从设备号
Ø 在设备管理中,除了设备类型外,内核还需要一对被称为主从设备号的参数,才能唯一标识一个设备
Ø 主设备号相同的设备使用相同的驱动程序
Ø 从设备号用于区分具体设备的实例
Ø cat /proc/devices可以查看系统中所有设备对应的主设备号
设备文件
Ø 设备类型、主从设备号是内核与设备驱动程序通信时使用的Ø 应用程序使用设备文件节点访问对应设备Ø 每个主从设备号确定的设备都对应一个文件节点Ø 每个设备文件都有其文件属性(c或者b)Ø 每个设备文件都有2个设备号(主,从)Ø 设备文件的主设备号必须与设备驱动程序在登记时申请的主设备号一致Ø 系统调用是内核与应用程序之间的接口Ø 设备驱动程序是内核与硬件之间的接口
驱动程序与应用程序的区别
Ø 应用程序以main开始Ø 驱动程序没有main,它以一个模块初始化函数作为入口Ø 应用程序从头到尾执行一个任务Ø 驱动程序完成初始化之后不再运行,等待系统调用Ø 应用程序可以使用GLIBC等标准C函数库Ø 驱动程序不能使用标准C库
用户态与内核态
驱动程序是内核的一部分,工作在内核态应用程序工作在用户态
数据空间访问问题
无法通过指针直接将二者的数据地址进行传递
系统提供一系列函数帮助完成数据空间转换 copy_from_user
copy_to_user
Linux驱动程序功能
Ø对设备初始化和释放Ø把数据从内核传送到硬件和从硬件读取数据Ø读取应用程序传送给设备文件的数据和回送应用程序请求的数据Ø检测和处理设备出现的错误
Linux字符设备驱动框架
file_opera
tions结构体
规定了驱动程序向应用程序提供的操作接口
实现函数:
open 当应用程序打开设备时对设备进行初始化release关闭设备时处理关闭操作
read 从硬件读取数据并交给应用程序
write 从应用程序接收数据送到硬件
ioctl 为应用程序提供对硬件行为的控制
驱动初始化:
Linux在加载内核模块时会调用初始化函数
static int __intXXXX_init(void)
使用register_chrdev向内核注册驱动程序
驱动退出:
Linux在卸载内核模块时会调用退出函数
static void __exit XXXX_exit(void)
使用unregister_chrdev从内核中卸载驱动程序
将驱动程序模块注册到内核
内核需要知道模块的初始化函数和退出函数,才能将模块放入自己的管理队列中
module_init(XXXX_init)
向内核声明当前模块的初始化函数
module_exit(XXXX_exit)
向内核声明当前模块的退出函数
中断处理
申请中断: request_irq()
释放中断: free_irq()
禁止单个中断: disable_irq()
允许单个中断: enable_irq()
禁止所有中断: local_irq_disable()
允许所有中断: local_irq_enable()
同步机制
当多个进程、线程同时访问一个资源时,可能导致错误。
内核需要提供并发控制机制,对公共资源的访问进行同步控制,确保共享资源的安全访问。
Linux同步机制:自旋锁(spinlock),信号量(semaphore),读写锁(rwlock),
顺序锁(seqlock),RCU(Read-CopyUpdate)