本文是分别重应用程序层面、驱动程序层面讲解linux异步通知I/O的机制,希望给读者带来帮助。由于本人知识有限,如有错误请大家指出,谢谢!
/******************************
author:徐福成
date :2011.01.01
******************************/
1)应用程序层面:
linux异步通知I/O 就是我们应用程序中经常用到的信号的处理方法,如:signal(),和sigaction()两个函数用来注册一个信号的处理方法。
如:
#include ... //接收到异步读信号的动作 void input_handler(int signum) { printf("Receive a signal from globalfifo,signalnum:%d/n",signum); } int main() { int fd, oflags; fd = open("/dev/globalfifo", O_RDWR, S_IRUSR | S_IWUSR); if (fd != - 1) { //启动信号驱动机制 signal(SIGIO, input_handler); //让input_handler()处理SIGIO信号 fcntl(fd, F_SETOWN, getpid()); oflags = fcntl(fd, F_GETFL); fcntl(fd, F_SETFL, oflags | FASYNC); while(1) { sleep(100); } } else { printf("device open failure/n"); } }
上面就是一个简单的异步通知I/O 的例子,当该程序收到SIGIO信号的时候,就调用input_handler()函数。
说明:什么时候收到SIGIO信号该进程是不知道的,只要收到该信号,就会调用上面的信号处理函数,这就是异步通知I/O的应用原理。
2)设备驱动层面
1.异步通知I/O的组成
异步通知I/O故名思议就需要一个信号的发送者,和一个信号的接受者;
发送者:往往是一个外围设备,当该外围设备资源可用的时候会给对应需要获得该资源的进程发送一个可用的信号,提醒这个进程
接受者:就是我们的应用程序,也就是一个进程;
2.驱动程序中涉及到的三个工作
(1)支持F_SETOWN命令,能在这个控制命令处理中设置filp->f_owner为对应进程ID。此工作已由内核完成,设备驱动程序不需要来处理。
(2)支持F_SETFL命令,每当FASYNC标志状态改变时,linux设备驱动程序中的fasync()函数将得以执行。(前提linux设备驱动程序需要实现这个函数,否则一切都是空谈)
(3)在设备资源可获得时,调用kill_fasync()函数激发相应的信号
3.主要用的API
(1)fasync_helper()
说明:该函数处理FASYNC标志更改的函数,fasync()函数中调用;
(2)kill_fasync()
说明:该函数用来释放信号,往往在读写函数中调用,相应的资源可用;
当然要在release函数中释放异步通知这个标志,fasync(-1,filp,0)
希望本文对大家有帮助,谢谢!