现代Linux操作系统必须满足多任务、多处理器已经中断处理这些特性,因此就有并发的情况产生,在这种状态下如果要对某个资源的访问控制,就必须要对这个共有资源进行保护,使其能保证一致性,这一篇文章索要讨论的就是这个内容。这也是后面一系列博文中都可能涉及到的基本内容,正如内存管理一样,内存管理将会在下一篇文章中详细介绍。
对资源共享有一个硬性的规则:在单个执行线程以外共享硬件或软件资源的任何时候,由于另外一个线程可能产生对这个资源不一样的观察结果,因此必须显式的管理对该资源的访问。《LDD3》
一、信号量和互斥体
1. 信号量的实现 在linux中支持PV原语操作,所以提供了信号量的实现,其相关定义如下:
- #include <asm/semaphore.h>
- // 信号量的定义
- struct semaphore;
- // 动态初始化信号量的函数
- void sema_init(struct semaphore *sem, int val);
- /**
- * 由于信号量常常用作互斥模式,因此为了让互斥的时候使用更加简单
- * 内核提供了下面一组函数和宏来处理互斥模式
- **/
- // 被初始化为1,即还没有调用者进入临界区,当前调用者可以进入临界区
- DECLARE_MUTEX(name);
- // 被初始化为0,即已有调用者进入临界区,当前调用者不可以进入临界区
- DECLARE_MUTEX_LOCKED(name);
在linux内核的实现中,获得信号量,即PV操作的P操作时,是需要调用down函数,释放信号量即V操作,是需要调用up函数,这些函数的定义如下:
- // 减小信号量,并在必要时一直等待
- void down(struct semaphore *sem);
- // 减小信号量,但是操作是可中断的,这也是我们实际开发中将真正使用到的版本
- int down_interruptible(struct semaphore *sem);
- // 永远不会休眠,如果信号量在调用时无法获得,会立即返回一个非零值
- int down_trylock(struct semaphore *sem);
- // 调用up之后调用者将不会再拥有该信号量
- void up(struct semaphore *sem);
2. 读取者/写入者信号量 信号量对所有调用者执行互斥,而不管调用者到底要做什么,但是往往操作可以分为两大类读取和写入,允许读取并发是可能存在的,只需要在写入的时候执行互斥,读取的时候不必要等上一个读取完了在让下一个读取。linux为这种特殊情况提供了rwsem,其定义及相关操作函数定义如下:
- #include <linux/rwsem.h>
- // 读写信号量
- struct rw_semaphore;
- // 运行时动态初始化函数
- void init_rwsem(struct rw_semaphore *sem);
- /******* 只读访问操作函数 *******/
- // 只读访问,可和其他访问者并发访问,但是可能将调用者置于不可中断休眠状态
- void down_read(struct rw_semaphore *sem);
- // 不会在读访问不可获取时等待,在授予访问时返回非零
- int down_read_trylock(struct rw_semaphore *sem);
- // 由down_read获取到的rwsem对象必须由up_read释放
- void up_read(struct rw_semaphore *sem);
- /******* 只写访问操作函数 *******/
- // 只写访问,可和其他访问者并发写访问,但是可能将调用者置于不可中断休眠状态
- void down_write(struct rw_semaphore *sem);
- // 不会在写访问不可获取时等待,在授予访问时返回非零
- int down_write_trylock(struct rw_semaphore *sem);
- // 由down_write获取到的rwsem对象必须由up_write释放
- void up_write(struct rw_semaphore *sem);
- // 在结束修改之后调用downgrade_write,将允许其他读取者访问
- void downgrade_write(struct rw_semaphore *sem);
一个rwsem允许一个写入者和多个读取者拥有该信号量,写入者的优先级别更高;如果有大量写入者竞争该信号量,则可能会出现长期拒绝读取者访问,俗称饿死状态。
最好在很少写入者访问且写入者只会短期拥有信号量的时候使用rwsem。二、完成变量未完成
三、自旋锁未完成
四、原子变量未完成
五、综合实例源码未完成
六、总结未完成
阅读(2568) | 评论(0) | 转发(1) |