04clock
1 内核的并发控制 2 linux 内核中竞争发生的情况 3 1. 进程与抢占它的进程 4 2. 进程和中断 5 3. smp 多处理器 6 7 访问共享资源的代码区域一般称之为临界区, 8 临界区需要被以某种互斥的机制加以保护 9 10 上锁 11 临界区 12 解锁 13 14 1.中断屏蔽 15 local_irq_enable(); //使能中断 16 local_irq_disable(); //屏蔽中断 17 18 19 2.原子操作 atomic.h 20 include/asm-generic/atomic.h 21 保护变量 22 类型: atomic_t v 23 24 对于原子操作,所有v操作必须调用其中函数,才能达到原子操作目的 25 atomic_t v = ATOMIC_INIT(0); //初始化v 为0; 26 atomic_read(v) 获取原子操作的值 27 28 static inline void atomic_add(int i, atomic_t *v) 29 把原子操作v 加上i 30 31 static inline void atomic_sub(int i, atomic_t *v) 32 v 减 i 33 34 static inline void atomic_inc(atomic_t *v) 自增 35 static inline void atomic_dec(atomic_t *v) 自减 36 37 atomic_dec_and_test 自减 和 0比较 38 39 3.自旋锁 40 spinlock.h 41 当获取不了资源时候,CPU会在原地打转 42 spinlock_t lock定义自旋锁 43 spin_lock_init(&lock) 自旋锁的初始化 44 spin_lock(&lock) 上锁 45 46 spin_unlock(&lock) 解锁 47 48 spin_trylock(&lock) 该函数立即返回 49 如果获取成功返回非0 失败返回0 50 51 52 53 读写自旋锁 rwlock.h 54 当访问一块共享区域,读的操作并不会影响到共享区域,所以读和读之间没有必要互斥 55 56 读和读 不互斥 57 写和写 互斥 58 读和写 互斥 59 60 前提: 临界区 一定要严格区分 读和写 61 62 rwlock_t 读写自旋锁的类型 63 64 rwlock_init(&lock) 初始化 65 66 读 67 read_lock(&lock) 上读锁 68 read_unlock(&lock) 解读锁 69 70 写 71 write_lock(&lock) 上写锁 72 write_unlock(&lock) 解写锁 73 74 读锁和写锁 必须指向同一个 lock 75 76 顺序锁 77 seqlock_t 类型 78 针对 读写锁一个改进,在读写锁基础上,让读和写 不再互斥 79 这种锁 适用如下场景: 80 1.能够严格区分 读 和 写 81 2. 读的操作要远大于写操作,反之有可能会造成死锁 82 83 seqlock_init(&lock); 读写的初始化 84 85 write_seqlock(&lock) 上写锁 86 xxxxx 87 write_unseqlock(&lock) 解写锁 88 89 90 读锁 91 read_seqbegin(); 92 read_seqretry(); 93 do { 94 seq = read_seqbegin(&lock); 95 xxxxxx; 临界区 96 }while(read_seqretry(&lock, seq)) 97 98 99 100 101 4.信号量 102 semaphore.h 103 信号量会引发进程间的调度 104 105 semaphore ; 106 sema_init(&sema, 1); //初始化为1 用于互斥 107 108 down(&sem) 获取信号量 109 down_trylock(&sema); 立即返回,无论有没有获得锁, 110 111 up(&sem) 释放信号量 112 113 114 读写信号量 同读写自旋锁 115 rwsem.h 116 rw_semaphore 类型 117 init_rwsem(&rwsem) 初始化 118 119 down_read(&rwsem) 上读锁 120 up_read(&rwsem) 解读锁 121 122 down_write(&rwsem) 上写锁 123 up_write(&rwsem) 解写锁 124 125 总结: 126 1.关闭中断尽量不要用 127 2.原子操作针对是变量,自旋锁和信号量保护代码段 128 3.由于信号量会引发进程间的调度,进程间切换是需要消耗事件, 129 所以如果保护代码段比较小,适合用自旋锁,如果保护的代码段比较大, 130 适合用信号量. 131 4.自旋锁是忙等,不会引发进程的切换,如果中断需要互斥,用spinlock 132 spinlock_trylock 133 5.会引起阻塞的代码段,不要用spinlock,用信号量 134 135 136 互斥体 137 简化版的信号量 信号量值为1,简化版 138 139 mutex 140 141 mutex_init(&mutex) //初始化信号量 142 mutex_lock(&mutex) 上锁 143 mutex_unlock(&mutex) 解锁