Chinaunix首页 | 论坛 | 博客

分类: LINUX

2012-04-24 16:46:42

    现代Linux操作系统必须满足多任务、多处理器已经中断处理这些特性,因此就有并发的情况产生,在这种状态下如果要对某个资源的访问控制,就必须要对这个共有资源进行保护,使其能保证一致性,这一篇文章索要讨论的就是这个内容。这也是后面一系列博文中都可能涉及到的基本内容,正如内存管理一样,内存管理将会在下一篇文章中详细介绍。

    对资源共享有一个硬性的规则:在单个执行线程以外共享硬件或软件资源的任何时候,由于另外一个线程可能产生对这个资源不一样的观察结果,因此必须显式的管理对该资源的访问。《LDD3》

一、信号量和互斥体

1. 信号量的实现

    在linux中支持PV原语操作,所以提供了信号量的实现,其相关定义如下:

点击(此处)折叠或打开

  1. #include <asm/semaphore.h>
  2. // 信号量的定义
  3. struct semaphore;

  4. // 动态初始化信号量的函数
  5. void sema_init(struct semaphore *sem, int val);

  6. /**
  7.  * 由于信号量常常用作互斥模式,因此为了让互斥的时候使用更加简单
  8.  * 内核提供了下面一组函数和宏来处理互斥模式
  9.  **/

  10. // 被初始化为1,即还没有调用者进入临界区,当前调用者可以进入临界区
  11. DECLARE_MUTEX(name);

  12. // 被初始化为0,即已有调用者进入临界区,当前调用者不可以进入临界区
  13. DECLARE_MUTEX_LOCKED(name);
在linux内核的实现中,获得信号量,即PV操作的P操作时,是需要调用down函数,释放信号量即V操作,是需要调用up函数,这些函数的定义如下:

点击(此处)折叠或打开

  1. // 减小信号量,并在必要时一直等待
  2. void down(struct semaphore *sem);

  3. // 减小信号量,但是操作是可中断的,这也是我们实际开发中将真正使用到的版本
  4. int down_interruptible(struct semaphore *sem);

  5. // 永远不会休眠,如果信号量在调用时无法获得,会立即返回一个非零值
  6. int down_trylock(struct semaphore *sem);

  7. // 调用up之后调用者将不会再拥有该信号量
  8. void up(struct semaphore *sem);

2. 读取者/写入者信号量
    信号量对所有调用者执行互斥,而不管调用者到底要做什么,但是往往操作可以分为两大类读取和写入,允许读取并发是可能存在的,只需要在写入的时候执行互斥,读取的时候不必要等上一个读取完了在让下一个读取。linux为这种特殊情况提供了rwsem,其定义及相关操作函数定义如下:

点击(此处)折叠或打开

  1. #include <linux/rwsem.h>

  2. // 读写信号量
  3. struct rw_semaphore;

  4. // 运行时动态初始化函数
  5. void init_rwsem(struct rw_semaphore *sem);

  6. /******* 只读访问操作函数 *******/

  7. // 只读访问,可和其他访问者并发访问,但是可能将调用者置于不可中断休眠状态
  8. void down_read(struct rw_semaphore *sem);

  9. // 不会在读访问不可获取时等待,在授予访问时返回非零
  10. int down_read_trylock(struct rw_semaphore *sem);

  11. // 由down_read获取到的rwsem对象必须由up_read释放
  12. void up_read(struct rw_semaphore *sem);

  13. /******* 只写访问操作函数 *******/

  14. // 只写访问,可和其他访问者并发写访问,但是可能将调用者置于不可中断休眠状态
  15. void down_write(struct rw_semaphore *sem);

  16. // 不会在写访问不可获取时等待,在授予访问时返回非零
  17. int down_write_trylock(struct rw_semaphore *sem);

  18. // 由down_write获取到的rwsem对象必须由up_write释放
  19. void up_write(struct rw_semaphore *sem);

  20. // 在结束修改之后调用downgrade_write,将允许其他读取者访问
  21. void downgrade_write(struct rw_semaphore *sem);
一个rwsem允许一个写入者和多个读取者拥有该信号量,写入者的优先级别更高;如果有大量写入者竞争该信号量,则可能会出现长期拒绝读取者访问,俗称饿死状态。最好在很少写入者访问且写入者只会短期拥有信号量的时候使用rwsem。

二、完成变量
未完成

三、自旋锁
未完成

四、原子变量
未完成

五、综合实例源码
未完成

六、总结
未完成
阅读(2517) | 评论(0) | 转发(1) |
给主人留下些什么吧!~~