设备驱动的概念
驱使硬件设备的行动
无操作系统的设备驱动
驱动为应用软件提供接口(单任务系统中)
下面两种是不合理的设计
第一张是应用和驱动平级,驱动里包含了业务逻辑,不符合如软件 高内聚,低耦合的要求
第二张是直接应用中操作硬件寄存器,不单独设计驱动,导致不存在可以重用的驱动代码
有操作系统的设备驱动
设备驱动设计面向操作系统内核的接口,设计的系统包含操作系统的时候,驱动变成了硬件和内核的连接桥,把单一的“驱使硬件设备行动”变成了“操作系统内与硬件交互的模块”,对外呈现为操作系统的API,不再为应用直接提供接口
驱动分类
字符设备指那些必须以串行顺序依次进行访问的设备,如触摸屏、磁带驱动器、鼠标等。块设备可以 按任意顺序进行访问,以块为单位进行操作,如硬盘、eMMC等。字符设备和块设备的驱动设计有出很大 的差异,但是对于用户而言,它们都要使用文件系统的操作接口open()、close()、read()、 write()等进行访问
在Linux系统中,网络设备面向数据包的接收和发送而设计,它并不倾向于对应于文件系统的节点。 内核与网络设备的通信与内核和字符设备、网络设备的通信方式完全不同,前者主要还是使用套接字接 口
并发与竞争
原子整型操作和原子位操作
适用于整数和位的原子操作
下面的可以对结构体等资源的同步访问
自旋锁
①、因为在等待自旋锁的时候处于“自旋”状态,因此锁的持有时间不能太长,一定要短,否则的话会降低系统性能。如果临界区比较大,运行时间比较长的话要选择其他的并发处理方式,比如稍后要讲的信号量和互斥体。
②、自旋锁保护的临界区内不能调用任何可能导致线程休眠的 API 函数,否则的话可能导致死锁。
③、不能递归申请自旋锁,因为一旦通过递归的方式申请一个你正在持有的锁,那么你就必须“自旋”,等待锁被释放,然而你正处于“自旋”状态,根本没法释放锁。结果就是自己把自己锁死了!
④、在编写驱动程序的时候我们必须考虑到驱动的可移植性,因此不管你用的是单核的还是多核的 SOC,都将其当做多核 SOC 来编写驱动程序。
大概意思就是一个cpu上跑线程A的时候需要关闭本CPU的中断,这样可以避免中断不一直自旋造成的死锁
信号量
①、因为信号量可以使等待资源线程进入休眠状态,因此适用于那些占用资源比较久的场合。
②、因此信号量不能用于中断中,因为信号量会引起休眠,中断不能休眠。
③、如果共享资源的持有时间比较短,那就不适合使用信号量了,因为频繁的休眠、切换线程引起的开销要远大于信号量带来的那点优势。
互斥量
mutex不能递归的上锁解锁
mutex和信号量都有可能导致休眠,所有在中断中只能是使用自旋锁