LDD读书笔记第五章-并发和竞态(一)
linux信号量的实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | #include <asm/semaphore.h> /*信号量相关头文件*/ struct semaphore /*信号量相关结构体*/ /*初始化相关函数*/ void sema_init(struct semaphore *sem,int val); /*初始化信号量函数*/ DECLARE_MUTEX(name); /*创建互斥体并初始化为1*/ DECLARE_MUTEX_LOCKED(name); /*创建互斥体并初始化为0*/ void init_MUTEX(struct semaphore *sem); /*初始化互斥体为1*/ void init_MUTEX_LOCKED(struct semaphore *sem); /*初始化互斥体为0*/ /*down&up 相关函数*/ void down(struct semaphore *sem); /*不可中断*/ int down_interruptible(struct semaphore *sem); /*可中断*/ int down_trylock(struct semaphore *sem); /*立即退出*/ void up(struct semaphore *sem); /*释放信号量*/ |
down_trylock函数在获取信号量失败时立即退出而不会等待。成功返回0,失败返回非零值。
读取者/写入者信号量
读取者/写入者信号量允许有一个写入者和无穷多个读取者。
当只需要读取数据时使用读取者信号量,仅当需要写入数据时获得写入者信号量。
当有线程获得写入者信号量的时候读取者信号量会被阻塞。
而多个读取者可以并发的读取数据。
并且写入者拥有比读取者更高的优先级。
如果大量线程竞争写入者信号量会导致读取者“饿死”。
1 2 3 4 5 6 7 8 9 10 | #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); /*获取读取者信号量失败立即退出*/ void up_read(struct rw_semaphore *sem); /*释放读取者信号量*/ void down_write(struct rw_semaphore *sem); /*获取写入者信号量*/ int down_write_trylock(struct rw_semaphore *sem); /*获取写入者信号量失败立即退出*/ void up_write(struct rw_semaphore *sem); /*释放写入者信号量*/ void downgrade_write(struct rw_semaphore *sem);/*释放写入者权限*/ |
down_read_tryloc和down_write_trylock函数会在获取信号量失败时不会等待而立即退出。
并且和其他一般内核函数不同在成功时返回非零值失败时返回零。
completion
1 2 3 4 5 6 | #include <linux/completion.h> DECLARE_COMPLETION(my_completion); /*创建completion*/ struct completion my_completion; /*结构体*/ void wait_for_completion(struct completion *c); /*等待完成*/ void complete(struct completion *c); /*触发一个等待*/ void complete_all(struct completion *c); /*出发所有等待*/ |
用代码来说明completeion的使用
1 2 3 4 5 | .... DECLARE_COMPLETION(my_completion); start_external_task(&my_completion); void wait_for_completion(&my_completion); .... |
线程在wait_for_completion处开始等待 当start_external_task完成外部任务时调用complete线程开始继续执行
自旋锁
自旋锁核心规则
1、任何拥有自旋锁的代码必须是原子的。
2、不能休眠。
3、自旋时禁用中断。
4、不能被抢占
5、自旋锁必须在可能的最短时间内拥有。
相关函数和宏
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | /*需要的头文件和两种初始化自旋锁的方法。 使用宏在编译时直接初始化。 而使用函数是在运行时初始化*/ #include <linux/spinlock.h> spinlock_t lock = SPIN_LOCK_UNLOCKED; void spin_lock_init(spinlock_t *lock); /*分别为: 获得锁。 获得锁并禁用中断,中断状态保存你在flags中。 获得锁并禁用中断,不保存状态,必须保证没有其他代码禁用中断 获得锁并禁用软中断,硬中断工作正常。 */ void spin_lock(spinlock_t *lock); void spin_lock_irqsave(spinlock_t *lock, unsigned long flags); void spin_lock_irq(spinlock_t *lock); void spin_lock_bh(spinlock_t *lock); /*下面四个函数和上面的函数一一对应用于释放锁。*/ void spin_unlock(spinlock_t *lock); void spin_unlock_irqrestore(spinlock_t *lock, unsigned long flags); void spin_unlock_irq(spinlock_t *lock); void spin_unlock_bh(spinlock_t *lock); /* */ int spin_trylock(spinlock_t *lock); int spin_trylock_bh(spinlock_t *lock); |
读取/写入自旋锁
整体概念和读取者/写入者信号量差不多。
函数跟自旋锁汉俗话一一对应
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | rwlock_t lock = RW_LOCK_UNLOCKED rwlock_init(rwlock_t *lock); void read_lock(rwlock_t *lock); void read_lock_irqsave(rwlock_t *lock, unsigned long flags); void read_lock_irq(rwlock_t *lock); void read_lock_bh(rwlock_t *lock); void read_unlock(rwlock_t *lock); void read_unlock_irqrestore(rwlock_t *lock, unsigned long flags); void read_unlock_irq(rwlock_t *lock); void read_unlock_bh(rwlock_t *lock); void write_lock(rwlock_t *lock); void write_lock_irqsave(rwlock_t *lock, unsigned long flags); void write_lock_irq(rwlock_t *lock); void write_lock_bh(rwlock_t *lock); void write_unlock(rwlock_t *lock); void write_unlock_irqrestore(rwlock_t *lock, unsigned long flags); void write_unlock_irq(rwlock_t *lock); void write_unlock_bh(rwlock_t *lock); |
----------------- 全文结束 -----------------
© 该日志作者:Senghoo, 于2010年07月15日发表于分类"Linux Kernel"下;
© 除非另有注明本文采用知识共享署名-非商业性使用-相同方式共享 2.5 中国大陆许可协议进行许可。
© 你可以发表评论,并在保留原文地址及作者的情况下引用到你的网站或博客。
© 转载请注明: LDD读书笔记第五章-并发和竞态(一) | 转自: Senghoo's Blog
© Tag: ldd , 并发 , 自旋锁 , 静态
© 除非另有注明本文采用知识共享署名-非商业性使用-相同方式共享 2.5 中国大陆许可协议进行许可。
© 你可以发表评论,并在保留原文地址及作者的情况下引用到你的网站或博客。
© 转载请注明: LDD读书笔记第五章-并发和竞态(一) | 转自: Senghoo's Blog
© Tag: ldd , 并发 , 自旋锁 , 静态