一.对异步通知的介绍
首先明确异步通知的概念:当设备准备就绪时,主动的去通知应用程序。这样应用程序就可以不用一直的查询设备的状态,便可以节省很多资源。比较准确的可以称为“信号驱动的异步I/O”。
这里说的信号是异步的,一个进程不必通过任何操作来等待信号的到达,事实上,进程也不知道信号到底什么时候到达。
异步通知意味着设备通知用户自身可以被访问,之后用户再通过程序对设备进行IO处理。
异步通知图例:展现用户空间和内核空间之间的关系
二.linux异步通知编程
1.linux信号
异步通知使用信号来实现。在linux中有30种信号来被使用。特殊的信号:SIGSTOP和SIGKILL两个信号进程不能捕获和忽略,其余的信号都可以。
信号捕获的意思是指当一个信号到达时有相应的代码处理它。如果一个信号没有被进程所捕获,内核将采用默认的行为来处理。
2.信号的接收
信号的接收是由应用层来接收。在用户程序中,为了捕获信号,可以使用signal()函数来设置对应信号的处理函数:
void(*signal(int signum,void(*handler))(int)))(int);
可以分解为:typedef void (*sighandler_t)(int);
sighandler_t signal(int signum,sighandler_t handler);
第一个参数指的是信号的值,第二个参数是针对前面信号的值的处理函数 ,在这里当为SIG_IGN时表示忽略该信号,SIG_DFL时表示采用系统默认方式处理信号,若用户自定义处理函数则当信号到达时被调用。
信号也可以用sigaction()函数来设置。它可用于改变进程接收到特定信号的行为。函数原型:
int sigaction(int signum,const struct sigaction *act,struct sigaction *oldact);
函数第一个参数为信号的值,第二个参数是指向结构体sigaction的一个实例的指针,在sigaction的实例中指定了对特定信号的处理函数,若为空将以缺省的方式对信号进行处理。第三个参数oldact指向的对象用来保存原来对相应信号的处理函数,可指定为NULL。当第二个和第三个参数都为NULL时,可以用来检查信号的有效性。
启动信号的机制(应用程序中):
例:、
int oflags;
signal(SIGIO,button_handler); //告诉是什么信号,并设置信号处理函数
fcntl(fd,F_SETNOWN,getpid()); //告诉内核用户程序的进程号,也就是明确内核要将信号发给哪个进程
oflags=fcntl(fd,F_GETFL);
fcntl(fd,F_SETFL,oflags | FASYNC); //启用异步通知机制,对设备设置FASYNC标志。
应用程序从内核接收信号的总结:
1..F_SETNOWN 使设备驱动发出的信号只能被本进程接收到
2.F_SETFL 使设备文件支持FASYNC,即异步通知模式
3.signal()函数连接信号和信号处理函数。
3.信号的释放
仅有应用端信号的接收是不够的,信号的源头在设备端,所以要在驱动程序中添加相应的释放信号的代码。
1.支持F_SETNOWN 命令,这个是由内核完成的,驱动程序无需处理
2.支持F_SETFL命令,当FASYNC标志改变时,驱动程序中的fasync()函数将执行,所以驱动程序中应该实现fasync()函数。这个函数进行初始化。
3调用kill_fasync()函数激发相应的信号。
处理FASYNC标志变更的函数
int fasync_helper(int fd,struct file *filp,int mode,struct fasync_struct **fa);
释放信号的函数
void kill_fasync(struct fasync_struct **fa,int sig,int band);
在最后的文件关闭时,应将文件从异步通知的列表中删除。
*************************************************************************************************************************************************************************************
对异步通知的总结:
1.应用程序 注册信号处理函数
2.谁发 驱动程序发
3.怎么发 kill_fasync()也需要一个fasync()函数 当应用程序执行时,驱动程序先执行这个fasync()函数
4.发给谁 信号发给应用程序,而且应用程序需要告诉内核程序进程号
**************************************************************************************************************************************************************************************
***本文中用户程序和应用程序指的是同一个