应用程序读取按键的方式
- 查询方式:实时查询
- 休眠-唤醒方式:无数据休眠,有数据唤醒
- poll方式:设置超时机制,在设置时间,有数据返回,无数据休眠,超时后直接返回无数据状态
- 初步通知方式:内核主动通知用户有数据
这几种方式没有优劣之分,在不同的场合使用不同的方式。
查询方式
- 构造一个file_operations结构体
- drv_open配置GPIO为输入模式
- drv_read返回预设状态
- APP直接通过调用读取,导致驱动中的读取函数被调用,返回初始的状态
休眠唤醒方式
- 构造一个file_operations结构体
- drv_open配置GPIO为中断模式
- drv_read有按键数据,直接返回给APP;否则内核态休眠
- 当用户点击按键时,GPIO中断被触发,导致驱动程序之前注册的中断服务程序被执行,它会记录按键数据,并唤醒休眠中的APP
- APP被唤醒后继续在内核状态运行(执行驱动代码,把按键数据返回给APP)
poll方式
上面的休眠-唤醒方式有一个缺点:如果用户一直没有操作按键,那么APP将永远休眠。我们可以给APP定个闹钟,这就是poll方式。
- 构造一个file_operations结构体,提供对应的open,read,poll函数
- 这两个函数可以设置一个超时时间,即在这段时间没有数据的话就返回错误。这会导致驱动中的poll或者选择被调用。如果有按键数据则直接返回按键数据给APP,否则APP在内核态休眠移动时间
- 当用户点击按键时,GPIO触发中断,导致驱动中的中断服务程序被执行,记录按键数据,同时唤醒休眠中的APP
- 如果用户没有按键,超时了内核也会唤醒APP
- APP得到投票/选择函数返回结果后,如果确认有数据,则在调用中读取。
异步通知
异步通知的原理:内核给APP发信号。i信号有很多种这里是SIGIO
- 构造一个file_operations结构体,提供对应的open,read,fasync函数
- APP给信号注册自己的信号处理函数
- APP调用fcntl函数,把驱动程序的标志设置为FASYNC,这会导致驱动程序的fasync函数被调用,它只是简单的记录进程PID
- 当用户点击按键后,GPIO中断触发,导致驱动中中断服务处理程序被调用,记录按键数据,然后给进程PID发送SIGIO信号
- APP收到信号后,会被打断,先执行信号处理函数:在信号处理函数中调用读取函数,读取按键值。
- 信号处理函数返回,继续执行后续的代码
总结
以上介绍了多种方式处理读取按键值,提供不同的策略,没有好坏之分。