自学记录—精通Linux 设备驱动程序开发

参考书:《精通Linux 设备驱动程序开发》
缘由:借了前辈的这本书研究一下,自学并记录
开始时间:2023.3.22 弄毕设有点闷,看这本书放松一下
说明:每个人的理解都可以不同,笔者也不一定对的,同时笔者在用国内chatgpt3.5镜像问相关问题时,发现条件不同、问法不同,答案有些也会不同,设备驱动程序开发这块也的确可以根据具体需求而设计出不同的

3/22

第1章引言,跳过
第2、3章关于内核,昨天浅看了一下,里面细节没懂,跳过了
第4章驱动程序的基本概念,这里记一下。

1、中断处理

IRQ:中断请求(Interrupt Request),硬件信号,异步
ISR:中断服务例程,代码段,立即执行,负载小
自学记录—精通Linux 设备驱动程序开发_第1张图片
ps:自己理解下的图,自学,可能会理解有失偏颇

中断上下文特点:
(1)不能停
(2)为保护临界区,用自旋锁,互斥体不得不用时才采用

临界区是指在多线程或并发编程中,访问共享资源的代码段,该代码段需要被互斥地访问以避免竞态条件(race condition)的发生。在任何时刻,只能有一个线程进入临界区执行代码,其他线程必须等待当前线程退出临界区后才能进入。

自旋锁和互斥体都是用于保护共享资源的同步机制,但它们有一些区别:
(1)等待方式不同:当一个线程尝试获取一个已经被占用的互斥体时,它会被阻塞并进入睡眠状态,直到互斥体被释放。而当一个线程尝试获取一个已经被占用的自旋锁时,它会一直循环等待,直到自旋锁被释放。
(2)实现机制不同:互斥体通常使用操作系统提供的原语来实现,因此需要从用户态切换到内核态,这种切换代价比较高。而自旋锁则是通过在用户态下不断地检查锁的状态来实现的,因此不需要切换到内核态,这使得自旋锁的效率比较高。
(3)适用场景不同:由于自旋锁需要不断地检查锁的状态,因此只适用于保护临界区比较短小的情况,否则会浪费大量的 CPU 时间。而互斥体则适用于保护临界区比较长或者需要等待时间比较长的情况。

(3)中断处理函数不能与用户空间直接交互数据

原因有2:
1、访问用户空间的数据需要通过复杂的机制进行特权级切换和内存映射等操作——>增加系统的开销和安全风险
2、调度器工作于进程之间,若中断处理函数睡眠并调度出去,无法返回运行队列

(4)中断处理函数将工作分为2部分(之后拓展)

(5)中断处理函数不必是可重用的

不必是可重用的有2方面:
1、中断函数运行时,在其返回之前,相应的IRQ都被禁止——>同一中断处理函数的不同实例不可能同时运行在同一处理器上。
2、专门为特定的硬件中断或软件中断而设计的,只有在相应的中断发生时才会被调用。由于每个中断都具有其独特的上下文和要求,因此中断处理函数通常不适合在其他中断或程序中重用。因此,编写可重用的中断处理函数可能会增加代码复杂性并降低系统性能。

(6)中断处理函数可被更高优先级IRQ的中断处理函数打断

2、IRQ号

在Linux系统中,IRQ号可以通过/proc/interrupts文件查看。该文件列出了系统中每个IRQ的统计信息和使用情况。可以使用命令行工具如cat、less或者grep来查看/proc/interrupts文件。

3、一个设备实例

不方便全打出来,而且里面有些知识参考后面章节,记录一些我个人我觉得有意思的

1、Linux中断——request_irq()(2.6.19内核开始,中断处理接口有点变化)
2、其他 free_irq() /enable_irq()…不一一列举了

3/23

4、softirq和tasklet

之前提到中断处理函数将工作分为2部分,这里细讲其中底(下)半部机制:
有篇博客关于这中断上下半部分区别总结不错: 关于Linux中断一些思考
上半部分:硬件,快,异步
下半部分
Linux2.5移除了BH(bottom half),目前使用方式是三种,softirq软中断、tasklet协程任务、工作队列

书中有个这三者详细比较的表格,挺清晰的(拍照上传侵权,个人懒得再画个表格),感觉从“使用场景”反推其它特点比较好理解,其中还有个讨论:LKML正在进行去除tasklet的讨论,比如将现存的tasklet基于其场景随机应变地转换为softirq或工作队列,具体取决于系统的需求和设计

软中断适用于需要快速响应的中断处理,延后的工作不会睡眠
tasklet适用于需要延迟处理的中断,延后的工作不会睡眠
工作队列适用于需要异步处理的任务。延后的工作会睡眠

回头又看了第2章2.7内存分配的内容。

在32位x86系统上,Linux 2.6.23环境下,物理地址空间通常被分配为以下几个部分:
1、内核空间(Kernel Space):占据高端的1GB或3GB空间,用于存储内核代码、数据和堆栈等。
2、用户空间(User Space):占据低端的2GB或1GB空间,用于存储用户进程的代码、数据和堆栈等。
3、DMA空间(Direct Memory Access Space):用于直接内存访问,可用于高速I/O设备的数据传输。
其中,内核空间和用户空间是虚拟地址空间,通过MMU映射到物理地址空间。DMA空间是物理地址空间,可以直接访问

在64位x86系统上,Linux2.6.23环境下,物理地址空间通常被分配为:
(1)用户空间:占据47位(从0到约128TB)的地址空间,用于用户进程的代码、数据和堆栈等。
(2)内核空间:占据17位(从约128TB到约256TB)的地址空间,用于内核代码、数据和堆栈等。
其中,最高的1个GB(从约255TB到约256TB)是预留给内核直接映射的设备的,称为“高端内存”(High Memory)。
------这种地址空间的划分方式被称为“经典模式”(Classic Mode),也可以使用“内核同步模式”(Kernel Same-page Merging,KSM)或“透明大页模式”(Transparent Huge Pages,THP)等技术来优化内存使用效率。

5、udev

设备管理工具

你可能感兴趣的:(Linux,linux,驱动开发)