linux设备驱动学习笔记——重要的一些概念

引用书中原话:

close和release

  并不是每一个close系统调用都会引起对release方法的调用。只有那些真正释放设备数据结构的close调用才会调用这个方法。内核对每个file结构维护其被使用多少次的计数器。无论是fork还是dup,都不会创建新的数据结构(仅有open创建),它们只是增加已有结构中的计数。只有在file结构的计数归0时,close系统调用才会执行release方法,这只在删除这个结构时才会发生。release和close系统调用间的关系保证了每次open驱动程序只会看到对应的一次release调用。

信号量和自旋锁

简单的说,自旋锁在内核中主要用来防止多处理器中并发访问临界区,防止内核抢占造成的竞争。另外自旋锁不允许任务睡眠(持有自旋锁的任务睡眠会造成自死锁——因为睡眠有可能造成持有锁的内核任务被重新调度,而再次申请自己已持有的锁),它能够在中断上下文中使用。

 

信号量和自旋锁区别

  从严格意义上讲,信号量和自旋锁属于不同层次的互斥手段,前者的实现有赖于后者。

注意以下原则:

      如果代码需要睡眠——这往往是发生在和用户空间同步时——使用信号量是唯一的选择。由于不受睡眠的限制,使用信号量通常来说更加简单一些。如果需要在自旋锁和信号量中作选择,应该取决于锁被持有的时间长短。理想情况是所有的锁都应该尽可能短的被持有,但是如果锁的持有时间较长的话,使用信号量是更好的选择。另外,信号量不同于自旋锁,它不会关闭内核抢占,所以持有信号量的代码可以被抢占。这意味者信号量不会对影响调度反应时间带来负面影响。

 

自旋锁对信号量

需求              建议的加锁方法

低开销加锁           优先使用自旋锁

短期锁定            优先使用自旋锁

长期加锁            优先使用信号量

中断上下文中加锁        使用自旋锁

持有锁是需要睡眠、调度     使用信号量

 

除了锁之外的方法

免锁算法————循环缓冲区

原子变量

位操作

seqlock

RCU(read-copy-update)


内存屏障

为了防止编译器和硬件的不正确优化,使得对存储器的访问顺序(其实就是变量)和书写程序时的访问顺序不一致而提出的一种解决办法。

#define barrier() __asm__ __volatile__("": : :"memory")

1. 保证编译器不会对代码做优化,打乱指令的执行顺序。
2. 向CPU发一条指令,保证硬件不会打乱在barrier两边的内存访问指令不会被打乱。

3.memory 强制 gcc 编译器假设 RAM 所有内存单元均被汇编指令修改,这样 cpu 中的 registers 和 cache 中已缓存的内存单元中的数据将作废。cpu 将不得不在需要
的时候重新读取内存中的数据。这就阻止了 cpu 又将 registers,cache 中的数据用于去优化指令,而避免去访问内存。




阅读更多
个人分类: ARM-Linux
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭
关闭