fasync的总结

来源:互联网 发布:比价神器软件 编辑:程序博客网 时间:2024/05/03 22:03

 

fasync这个东西就是为了使驱动的读写和application的读写分开,使得application可以在驱动读写时去做别的事,通过kill_fasync

(kill_fasync(&async, SIGIO, POLL_IN);)SIGIO信号给应用,应用通过fcntl把自己这个SIGIO的信号换成自己的响应函数,当驱动发

(kill_fasync(&async, SIGIO, POLL_IN);)给应用时应用就调用了自己的handler去处理。fasync_helper作用就是初始化fasync这个东西,包括分配内存和设置属性。最后记得在驱动的release里把fasync_helper初始化的东西free掉。

POLL_IN POLL_OUT

=================================================================================

驱动程序向用户程序发信号
---------------------------------------------

    当设备有IO事件发生,就有机制保证向应用进程发送信号,显然设备驱动程序扮演重要角色,实际终端tty、网络socket等的标准实现已经包括了实时信号驱动的支持,所以,在Linux中它们可以如上直接使用。但有些设备的驱动程序还并没有支持,所以需要定制设备驱动程序。以下两个API应该是可以屏蔽所有相关琐碎操作(类似send_sig())的标准接口:
    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);
   

    如果需要支持异步通知机制,如下设备结构中需要有异步事件通知队列(它应该与睡眠队列类似),并且增加fasync()接口的实现(该函数将本进程登记到async_queue上去) 当一个打开的文件FASYNC标志变化时(调用fcntl()函数,设置FASYNC文件标志时)fasync()接口将被调用。


   
struct kpp_dev {
       
struct cdev cdev;
       
struct fasync_struct *async_queue;
   
};
    

   
static int kpp_fasync(int fd, struct file *filp, int mode)
   
{
       
struct kpp_dev *dev = filp->private_data;
       
return fasync_helper(fd, filp, mode, &dev->async_queue);
   
}

    事件发生的时机,就是中断服务程序或相应的软中断中调用
kill_fasync():
   
if (dev->async_queue)
       
kill_fasync(&dev->async_queue, SIGIO, POLL_IN);
    如果是写操作,就是POLL_OUT。注意,无论用户进程设定了什么期望的信号,在这个环节,发送的一般就是SIGIO。注意在设备文件关闭(release方法)时,注意执行fasync(),使得本文件的操作从上述的设备异步事件等待链表中剥离。


    static int kpp_release(struct inode *inode, struct file *filp)
   
{
       
kpp_fasync(-1, filp, 0);
       
return 0;
    }