driver-day07 驱动中实现阻塞和软件去抖

2691 단어
답변:
内核中解决竞态的策略
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); //非阻塞方式读

구조체 파일

좋은 웹페이지 즐겨찾기