1. 首页 > 科技

如何用linux驱动编程,通过自旋锁实现对整形变量的访问保护?(关于Linux自旋锁)

如何用linux驱动编程,通过自旋锁实现对整形变量的访问保护?(关于Linux自旋锁)

关于Linux自旋锁

既然是对一个变量进行保护,当然是一个自旋锁了,还没见过一个变量能当两个用的。

我觉得你对这段代码的理解有问题,用 spin_lock 和 spin_unlock 的目的是保证程序在对 xxx_lock 进行操作的时候,不会有其它进程改变这个值,是为了保证数据的准确性。

你可以设想一下,如果没有自旋锁,代码运行起来会有什么问题。假设 A,B两个进程同时访问 open , 没有使用自旋锁,此时 xxx_lock=0, A 进程在判断 if (xxx_count) 时,会认为设备没有被使用,那么它会继续后面的 xxx_count++ 操作,但假如这时 CPU 切换进程, A 进程还没有来得及把 xxx_count 变成 1 的时候, B 进程开始运行,那么 B 进程此时也会认为设备没有被使用,它也会进行后继操作,这样就会出现两个进程同时访问设备的错误。

open 和 release 当然可以同时访问,只不过在运行 spin_lock 的时候,后访问的进程会被阻塞而已。假设有 A 进程访问 open ,B 进程访问 release ,你可以把这种情况理解为 A , B 进程同时访问 open 函数,这样或许能更好的理解这段代码。因为 open 和 release 在使用自旋锁的时候,方法是一样的。

spin_lock 和 CPU 系统无关,不管是单 CPU 还是多 CPU ,运行结果都是一样的。

这个逻辑关系比较难解释,不知道你看懂我的意思没。

spinlock自旋锁是如何实现的

在 x86 平台上,spinlock 主要通过处理器的 lock 指令前缀实现当某个线程的一条指令访问某个内存的时候,其他的线程的指令无法访问该内存的功能。因此在 spinlock 初始化阶段,将锁变量中的值某个值 k 赋为1。在加锁的时候,使用 lock decl (%eax) 指令互斥地将该变量变成0,并且将结果是否问0 赋值给 EFLAGS寄存器 的对应位。只有加上锁的线程才会结果才是0,其他线程的结果不是0。接着通过判断该对应位判断是否加上锁。如果没有加上,则循环执行 lock decl (%eax),直到加上为止。其中 %eax 是这个变量的地址。这里用的是gcc 的AT&T语法的汇编。

在Linux中,中断处理程序可以抢占正在执行的有自旋锁保护的代码?

中断处理……你说的是GAS汇编的那个么?那个应该可以。

linux如何保护共享资源

主要有一下几种:中断屏蔽、 原子操作、自旋锁、信号量、环形缓冲区。在本文中对于这些机制的具体的实现函数,以及原理不再做任何的表述。本

一、原子变量

假设我们所需要保护的共享资源只是一个整数值,此时我们可以采用的机制有自旋锁,信号量,和原子变量,当然中断屏蔽也是可以的。但是如果选择最优的机制,我们应该选择原子变量。原因:1.对一个整数值的操作是很简单的,也就是说此对全局变量形成的临界区是很小的.如果我们采用其他的机制,例如锁的机制,信号量等就显得有些浪费.也就是说,你的锁机制的代码量可能比临界区的代码量还要多.2. 对一个缺乏经验的程序员来讲,由于思维缺乏逻辑,使用锁机制会存在很多潜在的风险.例如: 死锁.等问题;而采用原子变量的方法,可以避免锁机制产生的弊端.

二、自旋锁自旋锁机制和信号量机制都可以对资源进行互斥访问,但是从性能上讲,自旋锁的性能优于信号量。但是自旋锁机制本身在不停的自旋(也就是查询锁是否可用),导致此机制有一些缺点:1。假定我们的驱动程序获得了一个自旋锁,在临界区开始了他的工作期间,驱动程序丢掉了处理器。也许他调用了一个函数,这个函数使进程休眠。也许发生了内核的抢占。但是我们的代码拥有这个自旋锁,如果其他的进程想要获得此自旋锁,需要等很长时间,甚至造成死锁。所以我们应用自旋锁时应遵循:任何拥有自旋锁的代码必须是原子的。所以他不能休眠,所以不能调用能够引起休眠的函数。例如:copy_to_user,copy_from_user,kmalloc等。也不能因为任何原因放弃处理器,除了中断以外(有时中断也不行,可以采用禁止中断的自旋锁函数操作)。

三、信号量拥有信号量的进程是可以休眠的。这也正是他对于自旋锁的优势。

其他的暂不论述。