Linux设备驱动程序第三版学习(8)- 高级字符驱动程序操作(续3)- 异步通知

第六章:高级字符驱动程序操作(续3)
以下为第四部分:异步通知

使用poll轮询方式的时候,相当于应用程序在需要的时候询问设备“准备好了吗?”,如果有这样一种情况,一个进程在低优先级正在执行长的循环计算,但又需要“尽可能快”的处理输入数据,如果采用poll的方式,那么需要这个应用程序周期性的调用poll来检测数据,也就是周期性的询问设备“准备好了吗?” 显然这种情况下poll并不是最佳的方法。更好的方法应该是一旦设备准备好了就发出一个“我准备好了”的信号给应用程序,然后应用程序再去处理。这样显然更高效。这种方法就是:异步通知。
通过上面的描述,显然如果想要异步通知,首先设备就要有发信号的功能,这就要启动文件的异步通知机制。为了启动这个机制,用户程序需要进行两个步骤:
1.指定一个进程作为文件的owner(“所有者”或者“属主”),用来接收“我准备好了”这个信号。该进程的ID好被保存到filp->f_owner中。通过调用fcntl执行F_SETOWN来完成这一步。
2.在设备中设置FASYNC标志来真正启动异步通知机制。通过调用fcntl执行F_SETFL命令完成这一步。
执行完这两个步骤以后,当有新数据到达时设备文件会发送一个SIGIO信号(“我准备好了”),该信号被发送到存放在file->f_owner中的进程。
注:显然进程如果只接受到“我准备好了”这个信号,它就会问“那个‘我’是谁阿?”(突然想起《鬼子来了》,淡定...),所以如果有多于一个文件可以异步通知输入的进程,那么当应用程序接收到信号时还是要借助poll轮询一次,以便真正确定输入的来源。

下面分别从驱动程序角度和应用程序角度分别总结一下我们应该进行哪些工作。
一、 驱动方面:
1. 在设备抽象的数据结构中增加一个struct fasync_struct的指针
2. 实现设备操作中的fasync函数,其主体就是调用内核的fasync_helper函数。
3. 在需要向用户空间通知的地方(例如scullpipe的write中)调用内核的kill_fasync函数。
4. 在驱动的release方法中调用前面定义的fasync函数, 例如scull_p_fasync(-1, filp, 0);
看一下驱动方面的源码:
    //对应上边的第1步
     
    //对应上面的第2步
     
    
    //对应上面的第3步,由于新数据是由于进程调用了write而产生的,所以在这里发送SIGIO信号
 
    
    //对应上面第4步
   

二、 应用层方面
1. 利用signal或者sigaction设置SIGIO信号的处理函数,关于signal的使用参照本博客转载的一篇“signal”
2. fcntl的F_SETOWN指令设置当前进程为设备文件owner
3. fcntl的F_SETFL指令设置FASYNC标志
看一下应用层方面的源代码,来自asynctest.c文件
   

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值