当前位置: 首页 > 科技观察

Linux驱动技术(四)_异步通知技术

时间:2023-03-13 17:56:28 科技观察

异步通知的全称是“signal-drivenasynchronousIO”。通过“信号”方式,当需要的资源可用时,驱动程序会主动通知指定的应用程序。对应应用层的“信号”,这里用到信号“SIGIO”。操作步骤是应用层程序将自己注册为进程驱动程序,从设备文件接收SIGIO信号,并实现相应的接口,以具备向所有注册接收SIGIO的应用程序发送SIGIO信号的能力来自设备驱动程序的信号。驱动程序在合适的位置调用发送函数,应用程序可以接收到SIGIO信号。整个机制的框架:应用层和其他信号一样接收SIGIO,应用层需要注册一个信号处理函数,注册方式还是使用signal()或者sigaction()另外,应用层还需要将自己添加到驱动的通知列表中,添加的代码如下同时(1);完成以上工作,应用层程序就可以等待SIGIO的到来了。驱动发送SIGIO,应用层注册。最后发送取决于设备驱动程序的处理方式。为使设备支持异步通知机制,参考应用层接口,驱动涉及3个任务。支持F_SETOWN命令,可以在该命令中设置filp->f_owner为对应进程的ID,这部分内核已经对F_SETFL做了支持,每当FASYNC标志改变时,驱动中的fasync()就会已执行,因此,驱动程序必须实现fasync()。当设备资源可用时,通过kill_fasync()发送SIGIO为了在内核中实现以上三个功能,驱动需要使用1个结构体+2个API,结构体为structfasync_struct,函数为fasync_helper()和kill_fasync()structfasync_struct{spinlock_tfa_lock;intmagic;intfa_fd;structfasync_struct*fa_next;/*singlylinkedlist*/structfile*fa_file;structrcu_headfa_rcu;};fasync_helper()的作用是注册一个fasync_struct对象到内核中,应用层执行fcntl(dev_fd,F_SETFL,oflags|FASY)会回调驱动的fops.fasync(),所以通常把fasync_helper()放在fasync()的实现。/***fasync_helper-在内核中注册一个fasync_struct对象*@fd:文件描述符,fasync传入*@filp:文件指针,fasync传入*@sig:信号类型,常用的是SIGIO*@dev_fasync:指向事先准备好的fasync_struct对象指针*/intfasync_helper(intfd,structfile*filp,intsig,structfasync_struct**dev_fasync);下面的API是释放SIGIO,根据不同的需求放在不同的位置。/***kill_fasync-释放一个信号*@dev_fasync:使用fasync_helper预先在内核中注册fasync_struct对象指针的指针*@filp:文件指针,由fasync传入*@sig:信号类型,通常使用的是SIGIO*@flag:flag,通常,如果资源可读,则使用POLLIN,如果资源可写,则使用POLLOUT*/voidkill_fasync(structfasync_struct**dev_fasync,intsig,intflag);下面的驱动模板是针对硬件中断到达时(资源可用)向应用层发出信号,实际操作中还是有很多情况是资源可用的。*filp,intmode){returnfasync_helper(fd,filp,mode,&fasync);}structfile_operationsfops={....fasync=demo_fasync,...}staticint__initdemo_init(void){...request_irq(irq,handler,IRQF_TRIGGER_RISING,"演示",NULL);...}