在应用层中,通过异步通知的机制来处理随时发生的事件。例如用signal来俘获信号
void handler(){
.
.
}
int main(){
.
.
signal(SIGINT,handler);
}
如果想让设备文件拥有异步通知机制,那么,在主函数中是这样实现的
int main(){
int flag;
int fd=open("/dev/hello",O_RDWR);
.
signal(SIGIO,handler);
fcntl(fd,F_SETOWN,getpid()); //原型int fcntl(int fd , int cmd,.);3个或2个参数。这个函数的意思是
使fd干嘛。这里是使fd的拥有者是当前进程。
flag=fcntl(fd,F_GETFL); //获得fd的状态,
fcntl(fd,F_SETFL,flag|FASYNC);//使fd的状态在原来上加上异步状态。
.
.
}
完成了这些,在内核相对应的file结构体就会被设置成上面的样子,也就是拥有了FASYNC状态。
在驱动层,要完成的事情就是实现对F_SETOWN和F_SETFL的支持。而F_SETOWN在内核已经帮我们实现了,我们的工作
就是F_SETFL的支持了,很简单,只要完成operations结构体中的fasync方法即可。
fasync的参数是这样的
static int my_fasync(int fd, struct file * filp, int on)
第一个是要异步通知的文件描述符,第二个是file结构,目的是要他的filp->private_data,第三个是模式位,当应用层
把file设成FASYNC状态是,on会被指1,然后传给系统函数fasync_helper,在内核中的fasync_helper的原型如下
int fasync_helper(int fd, struct file * filp, int on, struct fasync_struct **fapp)
{
if (!on)
return fasync_remove_entry(filp, fapp);
return fasync_add_entry(fd, filp, fapp);
}
也就是会把设备登记到队列中。
那么 operations的fasync可以这样写
int my_fasync(int fd, struct file * filp, int on){
struct dev *dev=filp->private_data;
return fasync_helper(fd, filp, mode, &dev->async_queue);
}
相应的,在close后,也就是驱动的release函数中,要调用my_fasync函数,传递的参数是
-1,filp,0 也就是传递0给内核,让他remove掉队列。 fd传递-1是表示本设备对应的所有的进程所打开的
文件。