设备驱动中的并发控制笔记 --笔记结构基于《linux驱动开发入门与实战》

来源:互联网 发布:linux 倒序 编辑:程序博客网 时间:2024/06/10 05:51

无论在学习还是在生活中,做一件事情都有一个理由。

学习的时候要明白为什么要学这个

为什么 ,这个是为什么存在,存在的目的是什么? 

怎么做, 这个怎么做可以达到要解决的问题。有哪些方法可以做

1 为什么要进行并发控制?

现代处理器有三大特性: 中断处理,多任务处理和多处理器--导致的多个进程,线程,CPU同时访问一个资源会发生错误,所以并发控制的目的是:对共用资源进行保护。

       并发控制的方法
1 原子变量操作:不会在执行完毕前辈其他任务中断和打断.

其中API和原子类型定义在:include/asm/atomic.h;原子操作定义在内存中而不是寄存器中。
原子变量的操作方法:
i,  原子整形操作
存在目的:可能有时候共享的资源只是一个简单地整型数值。
定义方法: atomic_t xxxx ; 
操作方法: atomic_t类型只能通过linux内核定义的专门的函数操作。
1,定义宏变量 #define ATOMIC_INIT(i) { (i) } .
2,设置atomic_t变量的值 atomic_set(v,i) ;
3,读取atomic_t的值   atomic_read(v); 
4, 变量的加减法        atomic_add(int i,volatile atomic_t *v)  / atomic_sub(int i,volatile atomic_t *v);
5,变量自加自减 atomic_inc(volatile atomic *v)  /  atomic_dec(int i,volatile atomic_t *v) ; 
6,加减法测试  atomic_dec_and_test(volatile atomic_t *v) ;
ii, 原子位操作
存在的目的:根据bit位进行单独的操作一个数据
 操作方法 : 定义某个数据的指针
设置位:static inline void set_bit(int nr ,bolatile unsigned long *addr) ; //addr变量的第nr位置设置为1 
清除位:static inline void clear_bit(int nr ,bolatile unsigned long *addr) ; 
反转位:static inline void change_bit(int nr ,bolatile unsigned long *addr) ; 
设置并且返回之前的值:static inline int test_and_set_bit(int nr ,bolatile unsigned long *addr) ; 
static inline int test_and_clear_bit(int nr ,bolatile unsigned long *addr) ; 
static inline int test_and_change_bit(int nr ,bolatile unsigned long *addr) ; 
非原子操作:在这个函数之前增加__表示非原子操作。
设置位:static inline void __set_bit(int nr ,bolatile unsigned long *addr) ; //addr变量的第nr位置设置为1 
清除位:static inline void __clear_bit(int nr ,bolatile unsigned long *addr) ; 
反转位:static inline void __change_bit(int nr ,bolatile unsigned long *addr) ; 
设置并且返回之前的值:static inline int __test_and_set_bit(int nr ,bolatile unsigned long *addr) ; 
static inline int __test_and_clear_bit(int nr ,bolatile unsigned long *addr) ; 
static inline int __test_and_change_bit(int nr ,bolatile unsigned long *addr) ; 

2自旋锁
存在的目的:解决原子操作在多个函数来回运行不能处理的时候。
类型:struct spinlock_t xxx ; 
使用方法: 
定义和初始化自旋锁:struct spinlock_t lock =SPIN_LOCK_UNLOCKED ;
   void spin_lock_init(&lock) ;
锁定自旋锁:#define spin_lock(&lock) ;
******需要保护的临界资源******
释放自旋锁:   #define spin_unlock(&lock)       

注意事项:自旋锁是一种忙等待
自旋锁不能被递归调用函数。

3信号量

存在的目的: 进程等待的时候会在等待列队中睡眠,唤醒后再从唤醒的地方开始执行
(只有能睡眠的进程才能使用信号量,而中断不能睡眠就不能使用信号量)
信号量操作:
类型: struct semaphore{
spinlock_t lock ; 
unsigned int count ;
struct list_head wait_list ; 
}

4完成量 

 struct completion {
unsigned int done ; 
wait_queue_head_t wait ; 

}


0 0
原创粉丝点击