driver-day07 驱动中实现阻塞和软件去抖
内核中解决竞态的策略
1)中断屏蔽
关中断
访问共享资源
开中断
关中断的时间要非常短
2) 原子操作
位原子操作
整型原子操作
使用时需要一个int类型数据,用于计数
可以考虑使用原子操作实现
3)自旋锁
只能有一个持有单元
获取锁不成功原地自旋等待
保护的临界区执行速度越快越好
其中不能调用引起阻塞或者睡眠的函数
关注死锁问题
4)信号量
基于自旋锁机制实现的
可以有多个持有者
获取信号量不成功睡眠等待
其中可以调用引起阻塞或者睡眠的函数
1、等待队列
recv(...)//有数据立即接收返回
//阻塞睡眠等待,一旦有数据就接收并返回
以上功能的实现的靠驱动程序完成
驱动程序中如何实现该功能,靠的就是内核中的等待队列机制
구조체 __wait_queue_head {
spinlock_t 잠금;
struct list_head task_list;
};
使用步骤:
1) 定义一个等待队列头
struct __wait_queue_head btn_wqh;
2) 初始化等待队列头
init_waitqueue_head(&btn_wqh)
以上两步可以使用如下宏代替
DECLARE_WAIT_QUEUE_HEAD(btn_wqh)
3) 在需要阻塞睡眠等的位置使用该等待队列头
wait_event(btn_wqh, condition)
如果condition为false,调用者进程进入睡眠状态
wait_event_interruptible(btn_wqh, condition)
如果condition为fasle,调用者进程进入可中断的睡眠状态
4)当I/O准备就绪时
唤醒相应的睡眠进程
wake_up(wait_queue_head_t *queue)
wake_up_interruptible(wait_queue_head_t *queue)
注意:和wait_event或者wait_event_interruptible成对使用
实现的原理:
1)定义并初始化一个等待队列(链表中的节点)
struct task_struct:在内核中代表一个进程
进程 内核中就是一个task_struct类型的变量
学生 数据库中的一条记录
struct task_struct {
state//进程的当前状态
pid//进程PID
...
}
current:始终指向当前正在CPU中运行的进程结构体
将代表当前进程task_struct 的地址记录到等待队列
wait_queue_t name = { \
.private = current,
2)将初始化号的等待队列(包含当前进程信息的链表节点)
插入等待队列头指向的链表中去
_add_wait_queue(&btn_wqh, wait);
3)改变当前进程的状态
set_current_state(state);//TASK_INTERRUPTIBLE
4) 主动放弃CPU ,重新调度一个新的进程到CPU中来运行
schedule()
5)唤醒时
wake_up_interruptible(&btn_wqh)
将btn_wqh指向链表中处于TASK_INTERRUPTIBLE状态的
进程stat=TASK_RUNNING
该进程就有可能在执行 schedule()被重新放入cpu
继续执行。
2、软件去除抖动
1) 定时器去抖
2) 底半부 지연_작업
3、按下和释放都关注
request_irq(버튼[i].irq, btn_isr,
134 IRQF_TRIGGER_FALLING|IRQF_TRIGGER_RISING,
135 버튼[i].이름,
136 &(버튼[i]));
通过管脚的电平值判断是按下还是释放
4, 用户空间访问设备的另外一种方式
用户空间程序:
非阻塞方式访问设备
fd = 열기(/dev/xxx,O_RDONLY|O_NONBLOCK)
read(fd, buf, 1); //非阻塞方式读
구조체 파일
Reference
이 문제에 관하여(driver-day07 驱动中实现阻塞和软件去抖), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/moonxu0722/driver-day07-208l텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)