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

来源:互联网 发布:淘宝轮毂能买吗 编辑:程序博客网 时间:2024/06/06 00:02

操作系统中存在竞态问题,就是同时访问共享资源(包括程序,数据),引起竞态的原因有: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
0 0
原创粉丝点击