首页 > 代码库 > 11 Linux设备驱动的并发控制

11 Linux设备驱动的并发控制

一、并发和竟态

并发:多CPU或者单CPU多进程多线程同时执行

竟态:对共享资源的同时访问

以下4中情况出现并发:

(1)多CPU

(2)单CPU多进程多线程

(3)单CPU进程与中断

(4)单CPU中断与中断

二、进程调度

1. 进程调度是按照时间片来调度的,进程A的时间片用完了,就会调用进程B

2. 可抢占与不可抢占

抢占:打断当前进程(用户态或者内核态),执行其他进程。

用户态出现抢占的时刻:

(1)系统调用返回到用户态

(2)中断来了,打断用户态进程,然后中断返回的时刻

内核态抢占:

[1]中断返回内核态,Linux操作系统会检查是否可抢占
[2]内核态进程阻塞或自己调用了schedule()函数
[3]释放锁(spin_unlock:会将preempt_count --)

内核可以分为:可抢占与不可抢占的

三、关中断

总结:

上面4中并发的情况:2,3,4三种情况可以通过关闭中断来保证不会出现竞争。

四、自旋锁

单CPU平台:自旋锁功能只是关抢占
多CPU平台:内核空间关抢占 + 标志(V)

使用自旋锁目的?
防止多个执行者同时访问共享资源


进程与进程 ->OK
进程与中断 ->进程在使用共享资源的时候,还需要关闭对应的中断
中断与中断
A中断处理函数使用自旋锁,B中断优先级高,抢占A中断,并且也使用自旋锁,此时会出现什么情况?
此时B进程会一直自旋下去

如何避免中断之间并发?
中断处理函数执行的时候,关闭IRQ异常(等价于所有的中断都关闭)

五、信号量

特点:当进程不能获取信号量,进程就会休眠

1.定义信号量

struct semaphore sem;

2.初始化信号量

sema_init(struct semaphore *sem,int value);

3.获取信号量

void down(struct semaphore *sem);//不能获取,进程进入不可中断的等待态
int down_interrupt(strct sempaphore *sem);//不能获取,进程进入可中断等待

4.释放信号量

void up(struct semaphore *sem);//唤醒所有等待当前信号量的进程

注意:信号量不能再中断处理函数中使用

六、互斥锁

(1)信号量已经可以实现互斥,为什么使用互斥锁?
信号量主要是用来实现P,V操作,实现互斥效率比互斥锁低。

(2)互斥锁与自旋锁有什么区别?
[1]互斥锁不能获得锁的时候,进程阻塞,而自旋锁不会,它会进程自旋
[2]自旋锁关抢占,互斥锁不会关抢占

(3)使用互斥锁
[1]定义互斥锁
struct mutex_lock mlock;
[2]初始化
mutex_init(struct mutex_lock *lock);

[3]获得锁
mutex_lock(struct mutex_lock *lock);

[4]释放锁
mutex_unlock(struct mutex_lock *lock);

七、原子操作

11 Linux设备驱动的并发控制