为什么要用到互斥,是由于cpu调度引起来的,任何一个进程或线程随时都有可能被终止, 运行另一个进程和线程,假如两个进程同时操作一个共享资源(全局变量),就可能引起问题.
驱动里的互斥主要有两种方法: 信号量 和 自旋锁
信号量: (休眠了)
void sema_init (struct semaphore *sem, int val);
void down(struct semaphore * sem); //不能在中断上下文使用
int down_interruptible(struct semaphore * sem)// 能被信号打断
void up(struct semaphore * sem);
总结: 1. 可以长期加锁
2. 只能用于进程上下文,不能用于中断
3. 持有自旋锁时不能持有信号量
自旋锁: (忙等待)
spin_lock_init(lock)
spin_lock(lock)
spin_unlock(lock)
为了防止得到锁的代码在执行时收到本地中断的影响需要用到自旋锁衍生函数
spin_lock_irqsave
spin_lock_irqrestore
总结: 1. 进程获得自旋锁后 copy_to_user copy_from_user kmalloc 这类有可能引起阻塞的函数都不能调用
2. 短期加锁
3. 系统开销大
4. 持有自旋锁时不能持有信号量 也不能第二次持有(死锁)
原子操作:
原子整数操作
int i = 7;
i++; //此操作cpu执行三个操作 获得 i的值 计算 7+1 =8 将8写回到i中
atomic.h
atomic_t u = ATOMIC_INT(4);
atomic_add (2+&u);
原子位操作:
test_and_set_bit(int nr ,void *addr)
wake_up_interruptible (wait_queue_head_t *q);
唤醒 q 指定的注册在等待队列上的进程。该函数不能直接的立即唤醒进程,而是由调度程序转换上下文,调整为可运行状态。
延时的话可以用schedule_timeout(1) 代替msleep(1);
为了防止得到锁的代码在执行时收到本地中断的影响需要用到自旋锁衍生函数
原子位操作:
test_and_set_bit(int nr ,void *addr)
同步:
wait_event(queue,condition);
wait_event_interruptible(queue,condition);
如果condition不满足继续休眠wake_up_interruptible (wait_queue_head_t *q);
延时的话可以用schedule_timeout(1) 代替msleep(1);