Chinaunix首页 | 论坛 | 博客
  • 博客访问: 4568705
  • 博文数量: 385
  • 博客积分: 21208
  • 博客等级: 上将
  • 技术积分: 4393
  • 用 户 组: 普通用户
  • 注册时间: 2006-09-30 13:40
文章分类

全部博文(385)

文章存档

2015年(1)

2014年(3)

2012年(16)

2011年(42)

2010年(1)

2009年(2)

2008年(34)

2007年(188)

2006年(110)

分类: LINUX

2007-01-01 15:21:36

自旋锁与互斥锁有点类似,只是自旋锁不会引起调用者睡眠,可在不能休眠的代码中使用,例如中断处理例程

如果自旋锁已经被别的执行单元保持,调用者就一直循环在那里看是否该自旋锁的保持者已经释放了锁, "自旋"一词就是因此而得名。由于自旋锁使用者一般保持锁时间非常短,因此选择自旋而不是睡眠是非常必要的,自旋锁的效率远高于互斥锁。


自旋锁保持期间是抢占失效的,而信号量和读写信号量保持期间是可以被抢占的。
自旋锁只有在内核可抢占或SMP的情况下才真正需要,在单CPU且不可抢占的内核下,
自旋锁的所有操作都是空操作,但改变IRQ掩码状态的例程是个例外。

在驱动程序中,当多个线程同时访问相同的资源时(驱动程序中的全局变量是一种典型的共享资源),可能会引发"竞态",因此我们必须对共享资源进行并发控制。Linux内核中解决并发控制的最常用方法是自旋锁与信号量(绝大多数时候作为互斥锁使用)。

  自旋锁与信号量"类似而不类",类似说的是它们功能上的相似性,"不类"指代它们在本质和实现机理上完全不一样,不属于一类。

  自旋锁不会引起调用者睡眠,如果自旋锁已经被别的执行单元保持,调用者就一直循环查看是否该自旋锁的保持者已经释放了锁,"自旋"就是"在原地打转"。而信号量则引起调用者睡眠,它把进程从运行队列上拖出去,除非获得锁。这就是它们的"不类"。

  但是,无论是信号量,还是自旋锁,在任何时刻,最多只能有一个保持者,即在任何时刻最多只能有一个执行单元获得锁。这就是它们的"类似"。

   鉴于自旋锁与信号量的上述特点,一般而言,自旋锁适合于保持时间非常短的情况,它可以在任何上下文使用;信号量适合于保持时间较长的情况,会只能在进程 上下文使用。如果被保护的共享资源只在进程上下文访问,则可以以信号量来保护该共享资源,如果对共享资源的访问时间非常短,自旋锁也是好的选择。但是,如 果被保护的共享资源需要在中断上下文访问(包括底半部即中断处理句柄和顶半部即软中断),就必须使用自旋锁。

  与信号量相关的API主要有:

  定义信号量

struct semaphore sem;


  初始化信号量

void sema_init (struct semaphore *sem, int val);


  该函数初始化信号量,并设置信号量sem的值为val

void init_MUTEX (struct semaphore *sem);


  该函数用于初始化一个互斥锁,即它把信号量sem的值设置为1,等同于sema_init (struct semaphore *sem, 1);

void init_MUTEX_LOCKED (struct semaphore *sem);


  该函数也用于初始化一个互斥锁,但它把信号量sem的值设置为0,等同于sema_init (struct semaphore *sem, 0);

  获得信号量

void down(struct semaphore * sem);


  该函数用于获得信号量sem,它会导致睡眠,因此不能在中断上下文使用;

int down_interruptible(struct semaphore * sem);


  该函数功能与down类似,不同之处为,down不能被信号打断,但down_interruptible能被信号打断;

int down_trylock(struct semaphore * sem);


  该函数尝试获得信号量sem,如果能够立刻获得,它就获得该信号量并返回0,否则,返回非0值。它不会导致调用者睡眠,可以在中断上下文使用。

  释放信号量

void up(struct semaphore * sem);


  该函数释放信号量sem,唤醒等待者。

  与自旋锁相关的API主要有:

  定义自旋锁

spinlock_t spin;


  初始化自旋锁

spin_lock_init(lock)


  该宏用于动态初始化自旋锁lock

  获得自旋锁

spin_lock(lock)


  该宏用于获得自旋锁lock,如果能够立即获得锁,它就马上返回,否则,它将自旋在那里,直到该自旋锁的保持者释放;

spin_trylock(lock)


  该宏尝试获得自旋锁lock,如果能立即获得锁,它获得锁并返回真,否则立即返回假,实际上不再"在原地打转";

  释放自旋锁

spin_unlock(lock)


  该宏释放自旋锁lock,它与spin_trylock或spin_lock配对使用;

参考资料:
http://www-128.ibm.com/developerworks/cn/linux/l-synch/part1/



阅读(1362) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~