内核异步操作
异步
异步引入
前几章节提供的休眠-唤醒,poll机制,都需要休眠等待某个事件发生。但是在实际中,我们并不会休眠等待事件的发生,
而是采用另一种方式,等外部事件发生之后,将结果通知给我们。在程序中,就是驱动程序中的数据主动上报给App,App收到信号之后,
执行对应的动作。这种机制称为“异步机制”。
异步流程
驱动程序是如何通知到App,告知App有数据产生。驱动程序发信息给App。
发信息,有以下步骤:
发送方:驱动程序法
发什么内容:发信号
发什么信号:SIGIO
驱动怎么发信号:内核中提供发送信号
接收方:App。App需要把自己告诉驱动(PID),让驱动明确自己发消息给哪个App。
接收方动作:对应的信号处理函数。
信号与信号处理函数如何对应:App注册信号与信号处理函数。
图 1 内核信号类型
异步信号与信号处理函数关联如下所示:
图 2 信号与信号关联函数
App在执行过程中,它需要来自哪个驱动(肯定不止一个驱动)的信号?
App打开驱动程序的设备节点。
驱动程序需要发信号给哪个App(不止一个App)?
App需要把自己的PID传递给驱动程序。
App可以接受信号也可不接受信号?
可以将App的设置传递给驱动。
驱动程序要做什么?发信号。
APP设置进程ID时,驱动程序要记录下进程ID;
APP还要使能驱动程序的异步通知功能,驱动中有对应的函数:
APP打开驱动程序时,内核会创建对应的file结构体,file中有f_flags;
f_flags中有一个FASYNC位,它被设置为1时表示使能异步通知功能。
当f_flags中的FASYNC位发生变化时,驱动程序的fasync函数被调用。
发生中断时,有数据时,驱动程序调用内核辅助函数发信号。
这个辅助函数名为kill_fasync。
异步处理架构
App给SIGIO信号注册信号处理函数。App收到SIGIO信号,绑定的函数自动被调用。
App将自己的PID传递给驱动程序。调用不涉及驱动程序,记录在内核文件系统中。
调用fasync_helper函数,根据FASYNC值设置flags值
当信号发生,调用App中注册的信号处理函数。在其中可以调用read函数读取底层硬件数据。