异步通知处理
1、使用场景
使用休眠-唤醒、POLL 机制时,都需要休眠等待某个事件发生时,它们的差别在于后者可以指定休眠的
时长。
如果 APP 不想休眠怎么办?也有类似的方法:驱动程序有数据时主动通知 APP,APP 收到信号后执行信
息处理函数。
2、使用流程
驱动程序怎么通知 APP:发信号,这只有 3 个字,却可以引发很多问题:
① 谁发:驱动程序发
② 发什么:信号
③ 发什么信号:SIGIO
④ 怎么发:内核里提供有函数
⑤ 发给谁:APP,APP 要把自己告诉驱动
⑥ APP 收到后做什么:执行信号处理函数
⑦ 信号处理函数和信号,之间怎么挂钩:APP 注册信号处理函数
小孩通知妈妈的事情有很多:饿了、渴了、想找人玩。
Linux 系统中也有很多信号,在 Linux 内核源文件 include\uapi\asm-generic\signal.h 中,有很多信
号的宏定义:
②APP 给 SIGIO 这个信号注册信号处理函数 func,以后 APP 收到 SIGIO 信号时,这个函数会被自动调用;
③ 把 APP 的 PID(进程 ID)告诉驱动程序
④ 读取驱动程序文件 Flag;
⑤ 设置 Flag 里面的 FASYNC 位为 1:当 FASYNC 位发生变化时,会导致驱动程序的 fasync 被调用;
⑥⑦ 调用 faync_helper,它会根据 FAYSNC 的值决定是否设置 button_async->fa_file=驱动文件 filp:
驱动文件 filp 结构体里面含有之前设置的 PID。
⑧ APP 可以做其他事;
⑨⑩ 按下按键,发生中断,驱动程序的中断服务程序被调用,里面调用 kill_fasync 发信号;
⑪⑫⑬ APP 收到信号后,它的信号处理函数被自动调用,可以在里面调用 read 函数读取按键。
3、驱动编程
使用异步通知时,驱动程序的核心有 2:
① 提供对应的 drv_fasync 函数; ->fasync_helper
② 并在合适的时机发信号 ->怎么发信号呢?代码如下:
kill_fasync (&button_async, SIGIO, POLL_IN)
4、应用编程
应用程序要做的事情有这几件:
① 编写信号处理函数:
② 注册信号处理函数:
③ 打开驱动:
④ 把进程 ID 告诉驱动:
⑤ 使能驱动的 FASYNC 功能: