异步操作之异步通知编程

原创 2012年03月29日 20:35:51

我们前面介绍了阻塞与非阻塞的相关操作,其中poll()函数提供了较好的解决设备访问的基址
,但是如果有了异步通知的整套基址就更加完整了。
这次我就和大家一起来探讨一下Linux驱动开发中的异步操作

 

 

异步操作的概念与作用:
 概念:一旦设备准备就绪,则主动通知应用程序,这样应用程序就不需要查询设备状态了
 ,这一点与硬件上的"中断"概念非常相似
 
 在原理上一个进程收到一个信号与处理器收到一个中断请求时一样的。而所谓
 异步通知就是指:一个进程不必通过任何操作来等待信号的到达,进程也不知道信号shi什么时候到达
 
 这与阻塞及非阻塞I/O区别很大,阻塞I/O意味着一直等待到设备可以访问,而非阻塞I/O中使用poll()意味着需要查询设备
 是否可以访问,而异步通知则意味着设备通知自身可
 
 
 
 
 
 
 
 
Linux异步通知编程:


 
Linux信号:
  Linux中异步通知通过信号来实现
  Linux信号表:见下图


  
  

除了SIGSTOP和SIGKILL两个信号外(这两个信号一定会被捕获),进程能够忽略或捕获其他的全部
  信号,一个信号被捕获的意思是当一个信号到达时有相应的代码处理它,如果一个信号没有被这个进程锁捕获,
  内核将采用默认处理
  
  
 信号的接收:
  在用户空间,为了捕获信号,可以使用signal()函数来设置对应信号的处理函数:
  void (*signal (int signum,void (*handler))(int))(int);
  
  通常把该函数原型分解为:
  typedef void (*sighandler_t)(int);
  sighandler_t signal(int signum,sighandler_t handler));

  第一个参数指定信号的值,
  第二个参数指定对前面信号值的处理函数,若为SIG_IGN,表示忽略该信号。
  若为SIG_DFL表示采用系统默认方式处理信号,若为用户自定义函数,则信号被捕捉到
  后此函数将被执行
  
  
  函数返回值:如果signal()调用成功,它返回最后一次为信号signum绑定的处理函数handler值,失败
  则返回SIG_ERR
  
  signal()捕获信号范例:
  void sigterm_handler(int signo)
  {
   printf("Have caught sig N.O. %d\n",signo);
   exit(0);
  }
  
  
  int main(void)
  {
  /*捕捉SIGINT信号(Ctrl+c)*/
   signal(SIGINT,sigterm_handler);
  /*捕捉SIGTERM信号,kill正在运行的程序将发出SIGTERM信号*/
   signal(SIGTERM,sigterm_handler);
   while(1);
   
   return 0;
  }
  
  
  
  sigaction()函数与signal()函数功能类似
  int sigaction(int signum,const struct sigaction t*act,struct sigaction *oldact)
  参数介绍:
   signum:为信号值
   act:为指向结构体sigaction的一个指针,在结构体signaction的实例中,指定对特殊信号的处理函数
    ,若为空则进程会以缺省的方式对信号进行处理
   oldact:用来保护原来的信号处理函数
   
   此函数使用的一个小技巧:把第二三个参数设为NULL,那么该函数
   可以用于检查信号的有效性
   
  在用户空间对设备释放信号的处理:
   (1).通过F_SETOWN IO控制命令设置文件的拥有者为本进程,这样从驱动发出的信号才能被本进程
    接收
    fcntl(STDIN_FILENO,F_SETOWN,getpid());
   (2).通过F_SETFLIO控制命令设置设备文件支持FASYNC,即异步通知模式
    oflags = fcntl(STDIN_FILENO,F_GETFL);//获取原有模式
    fcntl(STDIN_FILENO,F_SETEL,oflags | FASYNC);//设置异步通知模式
   (3).通过signal()函数连接信号和信号处理函数
   
   
   
  以上介绍的两个函数都是在用户空间对信号进行处理的函数,下面介绍一下信号处理的
  驱动程序设计
  
  
  
  首先介绍一下一个函数和一个结构体:
  int fasync_helper(int fd,struct file*filp,int mode,struct fasync_struct **fa)
  //此函数与用来处理FASYNC标识的变更,简单的说可以用来设置设备文件支持FASYNC模式,执行此函数后,通过
  fa就可以得知当前设备资源是否可以获得
  
  
  结构体:fasync_struct,对于此结构体的对象你不需要深入了解,这里你只需要知道,再执行上述函数
  后,一旦资源可获得,此结构体不为空,从下面的程序中你也可以看出
  
  
  
  信号的释放:
   在设备驱动和应用程序的异步通知交互中,仅仅在应用程序端捕获信号是不够的,因为信号的源头在
   设备的驱动端,应该在合适的时候让设备驱动释放信号,在设备驱动程序中增加释放信号的相关代码
   
   
   支持设备异步通知机制的驱动程序编写:
   (1) 支持F_SETOWN命令,能在这个控制命令处理中设置filp->f_owner为对应进程ID(此工作已由内核实现)
   (2) 支持F_SETEL命令的处理,每当FASYNC标识改变时,驱动程序的fasync()函数将得以执行。此函数需要在驱动程序中实现
   static int xxx_fasync(int fd,struct file *filp,int mode)
   {
    struct xxx_dev *dev = filp->private_data;
    return fasync_helper(fd,filp,mode,&dev->async_queue);
   }
   (3)在设备资源可获得时,调用kill_fasync()函数激发响应信号
   例如:
   static ss_size_t xxx_write(struct file*filp,const char __user *buf,size_t count,loff_t *f_pos)
   {
    struct xxx_dev *dev = filp->private_data;
    ...
    /*产生异步读信号*/
    if(dev->async_queue)
     kill_fasync(&dev->async_queue,SIGIO,POLL_IN);
     ...
   }

  
   //驱动程序中的这三步操作正好对应于用户空间的那三步操作
   
   具体如图所示:
   
   
   
   
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  

版权声明:本文为博主原创文章,未经博主允许不得转载。

使用信号实现异步通知机制的例子

include #include #include #include #include #include #define MAX_LEN 100 //信号SIGIO的处理函数 void...
  • buaa_shang
  • buaa_shang
  • 2013年06月15日 21:20
  • 1848

linux下使用异步通知

阻塞式I/O是一直等待直到设备可以访问,非阻塞式I/O是定期轮询设备是否可以访问。 异步通知则是当设备可以访问时才主动通知应用程序,有点像设备的硬中断。   并不是所有的设备都支持异步通知,应用程序通...
  • zhangskd
  • zhangskd
  • 2015年05月23日 22:47
  • 4791

嵌入式软件异步编程(1):冥想

异步编程可以编写出速度快、资源省的高效程序,可以在单线程环境下实现高并发,可以在没有操作系统的情况下实现TCP/IP等协议栈。又快又省可以将功耗控制在最低水平,因此异步编程是低功耗设计的最佳编程模型。...
  • zoomdy
  • zoomdy
  • 2017年03月03日 21:06
  • 523

微信支付,异步通知

微信公众号配置共五个地方: 1、设置key:微信商户平台——账户设置——API安全——密钥设置 2、页面授权域名:用来过的openID,公众号设置——功能设置——设置【网页授权域名】(【js安全域名】...
  • myfmyfmyfmyf
  • myfmyfmyfmyf
  • 2016年12月05日 10:20
  • 4997

支付宝异步通知处理

支付宝异步通知是为防止网络不稳定,订单出现丢失的情况进行的处理,同时当交易成功的时候就异步处理本程序的业务...
  • u012603567
  • u012603567
  • 2015年01月28日 17:14
  • 1747

【java web spring mvc】服务端 微信支付+微信异步通知【精】

首先 这个微信支付 官网的demo 是有bug的 研究了好几天 吸取了一些大神的指点才成功,还有csdn一些人发的代码都不全太坑,资源还少,今天我就整合一下,把我的一些心得分享给大家 。 之前遇...
  • qq_29739821
  • qq_29739821
  • 2016年12月05日 16:29
  • 7225

关于支付宝异步通知的状态

关于支付宝异步通知的状态 刚开始接入支付宝支付的时候,就看到支付宝有几个异步通知的状态,其他的状态还理解,但是有两个状态的作用我感觉好像是有点重复,分别是TRADE_SUCCESS(交易成功)、TRA...
  • mrsbai
  • mrsbai
  • 2016年01月07日 19:47
  • 2208

Linux异步通知编程

原文: http://mozhengpeng.blog.163.com/blog/static/2309019720106283558329/ 1.Linux信号 http://www.ibm....
  • chj90220
  • chj90220
  • 2013年03月21日 21:02
  • 668

关于java支付宝接口的异步通知的问题

在做java版本的支付宝接口的时候,最初是遇到了这样的问题,就是说,在直接的扫码支付,或者是直接的登录账号支付,是没有问题的, 但是,在这样的一种情况下是出现了一个问题, 我web端调用支...
  • xyw591238
  • xyw591238
  • 2015年12月24日 16:24
  • 4799

第三方支付异步通知的陷阱

用户下单后调用第三方支付付款,然后接收第三方支付的异步通知,以便确认支付是否成功。 如下图   但异步通知可能由于网络原因,或者应用服务崩溃没有接收到。为了应对这种情况需要后台创建一个定时任务去调...
  • j16421881
  • j16421881
  • 2017年12月03日 20:16
  • 141
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:异步操作之异步通知编程
举报原因:
原因补充:

(最多只允许输入30个字)