Linux中的同步问题(Linux驱动1)

    xiaoxiao2021-03-25  82

    操作系统中存在竞态问题,就是同时访问共享资源(包括程序,数据),引起竞态的原因有:smp,抢占式内核,中断(硬中断,软中断等). 抢占式内核竞态问题的图示: 假如代码如下: write(resource); write_count++;

    A进程 B进程 C进程 ------------------------------------------------------ 写 ------------------------------------------------------ 写 ----------------------------------------------------- 计数 =1 ------------------------------------------------ 读计数(这时,就有问题) ----------------------------------------------------- 计数=2 ---------------------------------------------------

    问题:进程c读计数时,实际写了两次,可是这里读计数只有1次,问题产生的原因就在于写和计数不是原子操作)。

    保护共享资源的方法有:中断屏蔽,原子操作,锁,信号量.

    1 中断屏蔽

    变量 函数 local_irq_enable local_irq_disable 用法 local_irq_disable .... local_irq_enable 扩展: local_irq_save(flags) local_irq_restore(flags) local_bh_enable local_bh_disable

    2原子操作

    说明:原子操作,不会被打断 变量: atomic_t ATOMIT_INIT(i) 初始化值 函数 atomic_inc(atomic_t*) atomic_dec(atomic_t*) atomic_add(int,atomic_t*) atomic_sub(int,atomic_t*) atomic_read(atomic_t*) atomic_inc_and_test(atomic_t*) atomic_dec_and_test(atomic_t*) atomic_sub_and_test(int,atomic_t*) 注意,没有加 atomic_inc_return(atomic_t*) atomic_dec_return(atomic_t*) atomic_add_return(int,atomic_t*) atomic_sub_return(int,atomic_t*) bit操作 set_bit(nr,void*) clear_bit(nr,void*) change_bit(nr,void*) test_bit(nr,void*) test_and_set(nr,void*) 先测试,再操作 test_and_clear(nr,void*) test_and_change(nr,void*)

    3 自旋锁

    说明: 自旋锁会在原地打转,所以临界区尽可能短,不能阻塞. 变量: spinlock_t lock 函数 spin_lock_init(spinlock_t*) spin_lock(spinlock_t*) spin_unlock(spinlock_t*) 用法 spinlock_t lock spin_lock_init(&lock) spin_lock(&lock) ... spin_unlock(&lock) 扩展 spin_trylock(&lock) spin_lock_irq(&lock) spin_unlock_irq(&lock) spin_lock_irqsave(&lock,flags) spin_unlock_irqrestore(&lock,flags) spin_lock_bh(&lock) spin_unlock_bh(&lock) 读写自旋锁

    说明:读写锁是比自旋锁粒度更小的锁,自旋锁对于读写不加区分,而实际上对于读操作是可以并发的,读写锁就是解决这个问题。当然,读和写也是不能同时进行的。

    变量: rwlock_t lock=RW_LOCK_UNLOCKED;静态初始化 函数 rwlock_init(rwlock_t*)动态初始化 read_lock(rwlock_t*) read_unlock(rwlock_t*) write_lock(rwlock_t*) write_unlock(rwlock_t*) 用法 rwlock_t lock; rwlock_init(&lock) 读自旋锁 read_lock(&lock) ... read_unlock(&lock) 写自旋锁 write_lock(&lock) ... write_unlock(&lock) 扩展 read_lock_irq(&lock) read_unlock_irq(&lock) read_lock_irqsave(&lock,flags) read_unlock_irqrestore(&lock,flags) read_lock_bh(&lock) read_unlock_bh(&lock) write_lock_irq(&lock) write_unlock_irq(&lock) write_lock_irqsave(&lock,flags) write_unlock_irqrestore(&lock,flags) write_lock_bh(&lock) write_unlock_bh(&lock)

    4 顺序锁

    说明:顺序锁是读写锁的优化,读单元不会被写单元阻塞,写单元也不会被读单元阻塞。但是写单元之间仍然是互斥的。顺序锁有一个限制就是不能在其中使用指针,因为在保护的写单元中可能会使指针失效,而读单元此时使用指针就会失效。

    变量: seqlock_t lock; 函数: write_seqlock(&lock) write_sequnlock(&lock) write_seqtrylock(&lock) read_seqbegin(&lock) read_seqretry(&lock,iv) 用法: 写操作 write_seqlock ... write_sequnlock 读操作 do{ seqnum=read_seqbegin(&lock); .... }while(read_seqretry(&lock,sequm)) 扩展: write_seqlock_irq(&lock) write_sequnlock_irq(&lock) write_seqlock_irqsave(&lock,falgs) write_sequnlock_irqrestore(&lock,falgs) write_seqlock_bh(&lock) write_sequnlock_bh(&lock) read_seqbegin_irqsave(&lock,falgs) read_seqretry_irqrestore(&lock,iv,flags)

    6 RCU

    说明:rcu是read copy update的意思,可以看做是读写锁的高级版本,可以对保护单元同时进行读写.

    变量:rcu_head head 函数: read_lock_rcu() read_unlock_rcu() call_rcu(struct rcu_head*,void(*fun)(struct rcu_head*)) 用法: read_lock_rcu ... read_unlock_rcu 扩展 list_add_rcu list_add_tail_rcu list_del_rcu list_replace_rcu list_for_each_rcu list_for_each_safe_rcu list_for_each_entry_rcu hlist_add_head_rcu hlist_del_rcu hlist_for_each_rcu hlost_for_each_entry_rcu

    7 信号量

    说明: 信号量与自旋锁不同,信号量会进入休眠状态,而自旋锁会在原地打转. 变量: semaphore sem; 函数: sema_init(struct semaphore *,int val) DECLARE_MUTEX(name) DECLARE_MUTEX_LOCKED(name) init_MUTEX(&sem) init_MUTEX_LOCKED(&sem) down(&sem) up(&sem) 用法: down .... up 扩展:

    down_interruptible(&sem) 进入浅睡眠状态,可被打断.当调用此函数时需要检查其返回值如果返回非0,应当返回-ERESTARTSYS down_trylock 尝试获得信号量,如果获得则立即返回0,否则返回非零值,此函数不会引起睡眠.

    8 读写信号量

    说明: 读写信号量与信号量的关系与读写锁与自旋锁的关系是一样的. 变量: rw_semaphore sem 函数: init_rwsem(&sem) down_read up_read down_read_trylock down_write up_write down_write_trylock 完成量 说明: 完成量是为了同步两个进程. 变量: completion comp; 函数: init_completion(&comp); DECLARE_COMPLETION(name) wait_for_completion complete complete_all 用法: 进程A 进程B wait_for_completion complete

    10 互斥体

    说明: 互斥体与信号量是一样的. 变量: mutex mux; 函数: mutex_init(&mux) mutex_lock mutex_unlock mutex_trylock mutex_lock_interruptible 用法: mutex_lock ... mutex_unlock
    转载请注明原文地址: https://ju.6miu.com/read-32415.html

    最新回复(0)