异步通知:很简单,一旦设备准备好,就主动通知应用程序,这种情况下应用程序就不需要查询设备状态,这是不是特像硬件上常提的“中断的概念”。上边比较准确的说法其实应该叫做“信号驱动的异步I/O”,信号是在软件层次上对中断机制的一种模拟。

阻塞I/O意味着一直等待设备可访问再访问,非阻塞I/O意味着使用poll()来查询是否可访问,而异步通知则意味着设备通知应用程序自身可访问。

上面三种方式,其实本身是没有优劣的,应该根据不同的应用场景合理选择罢了。

说到信号,在应用程序中,为了捕获信号(还捕获呢,不就是一个处理吗)可以使用signal()函数来设置对应的信号的处理函数。函数原型是void (*signal(int signo,void (*func)(int))) (int) 这个看起来费劲吧,不光你,我看着也费劲,没关系,给你来个例子:

void sigterm_handler(int signo) { char data[MAX_LEN]; int len; len=read(STDIN_FILENO, &data,MAX_LEN); data[len]=0; printf("Input available:%s\n",data); exit(0); } intmain(void) { int oflags; //启动信号驱动机制 signal(SIGIO, sigterm_handler);fcntl(STDIN_FILENO, F_SETOWN, getpid()); oflags = fcntl(STDIN_FILENO, F_GETFL);fcntl(STDIN_FILENO, F_SETFL, oflags | FASYNC); //建立一个死循环,防止程序结束 while(1);return 0; }
看了这段代码明白啥意思了吧,我也不多少了,咱们继续往下走..为了一个用户在用户空间中能处理一个设备释放的信号,它必须完成一下3份工作:
1)通过F_SETOWN控制指令设置设备文件的拥有者为本进程,这样从设备驱动中发出的信号才能被本进程收到。
2)通过F_SETFLIO控制命令设置设备文件支持FASYNC,即异步通知模式。
3)通过signal()链接信号和信号处理函数。
有了信号的发送,那么就一定得有信号的释放了:
在设备驱动和应用程序的异步通知交互中,仅仅在应用程序端捕获信号是不够的,因为信号没有的源头是在驱动端,因此要在适当的时机让设备驱动释放信号。
为了使设备支持异步通知机制,驱动程序中涉及三个操作
1)支持F_SETOWN命令,能在这个控制命令处理中设置filp->f_owner为对应的进程ID。不过此项工作已由内核完成,设备驱动无须处理。
2)支持F_SETFL命令的处理,每当FASYNC标志改变时,驱动程序中fasync()函数将得以进行。因此,驱动程序必须实现fasync()函数。
3)在设备资源可获得时,调用kill_fasync()函数激发相应的信号
驱动程序中上面的三步是和应用程序是一一对应的。如下图:

设备驱动中异步通知编程还是比较简单的,主要就是一些数据结构,和两个函数:

数据结构:fasync_struct结构体

函数:

1)处理FASYNC标志变更的函数int fasync_helper(int fd, struct file *filp, int mode ,struct fasync_struct **fa);

2) 释放信号用的函数void kill_fasync(struct fasync_struct **fa, int sig, int band);

和其他设备驱动一样,一般将fasync_struct放到设备结构体中。下边是典型模版:

struct xxx_dev { struct cdev cdev; ... struct fasync_struct *async_queue; //异步结构体}

而在驱动的fasync()函数中,只需要简单的将该参数的3个参数以及fasync_struct结构体指针的指针作为第四个参数传给fasync_helper函数即可.下边是典型模版:

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); } 一旦设备资源可以获得时,应该调用kill_fasync()释放SIGIO信号,可读时第三个参数设置为POLL_IN,可写时第三个参数设置为POLL_OUT,下边是释放信号的典型模版
static ssize_t xxx_write(struct file *filp, const char __user *buf, size_t count,loff_t *f_ops) { struct xxx_dev *dev = filp->private_data; .... //产生异步信号if(dev->async_queue) { kill_fasync(&dev->async_queue, SIGIO, POLL_IN); } .. }
最后,在文件关闭时,即在设备驱动的release函数中,应调用设备驱动的fasync()函数将文件从异步通知的列表中删除,下边是设备驱动的释放函数的典型模版:
static int xxx_release(struct inode *inode, struct file *filp) { struct xxx_dev *dev = filp->private_data; //将文件从异步通知列表中删除 xxx_fasync(-1,filp,0); ... return 0; }
使用信号可以实现设备驱动与用户程序之间的异步通知,总体而言,设备驱动和用户空间要分别完成以下工作:用户空间设置文件的拥有者、FASYNC标志及捕获信号内核空间响应对文件的拥有者、FASYNC标志的设置,并在资源可获得时释放信号。 
Linux  2.6内核包含对AIO 的支持为用户空间提供统一的异步I/O 接口。在AIO中,信号和回调函数是实现内核空间用户空间应用程序通知的两种机制。

异步通知与异步I/O的更多相关文章

  1. arm驱动linux异步通知与异步IO【转】

    转自:http://blog.csdn.net/chinazhangzhong123/article/details/51638793 <[ arm驱动] linux异步通知与 异步IO> ...

  2. Linux设备驱动中的异步通知与异步I/O

    异步通知概念: 异步通知的意识是,一旦设备就绪,则主动通知应用程序,这样应用程序根本就不需要查询设备状态,这一点非常类似于硬件上的“中断”概念,比较准确的称谓是“信号驱动的异步IO”,信号是在软件层次 ...

  3. Linux内核开发之异步通知与异步I/O(一)

    “小王,听说过锦上添花吧..”我拍拍下王的头说. “还锦上添花你,为你上次提的几个东东,我是头上长包..”小王气愤地瞪着我. “啊,为啥这样呢,本来还特意拒绝了MM的月份,抽出时间打算给你说点高级的东 ...

  4. QGC 支付宝无法异步通知及异步通知常见问题注意事项

    支付宝异步通知参数(notify_url)路径常见问题注意事项: 1.不能是内网或者局域网地址,必须是外网可以访问的.否则无法调用!! 2.地址不能有session拦截,支付宝主动发送,所有sessi ...

  5. 蜕变成蝶~Linux设备驱动之异步通知和异步I/O

    在设备驱动中使用异步通知可以使得对设备的访问可进行时,由驱动主动通知应用程序进行访问.因此,使用无阻塞I/O的应用程序无需轮询设备是否可访问,而阻塞访问也可以被类似“中断”的异步通知所取代.异步通知类 ...

  6. linux异步通知

    简述 linux下异步方式有两种:异步通知和异步IO(AIO),aio请参考:linux异步IO--aio 异步通知的含义是:一旦设备就绪,则主动通知应用程序,这样应用程序就不需要查询设备状态,准确称 ...

  7. day114:MoFang:基于支付宝沙箱测试环境完成创建充值订单接口&服务端处理支付结果的同步通知和异步通知

    目录 1.基于支付宝提供的沙箱测试环境开发支付接口 1.后端提供创建充值订单接口 2.前端调用AlipayPlus发起支付 3.注意:自定义APPLoader完成接下来的开发 4.下载支付宝沙箱钱包A ...

  8. 第三十四篇:在SOUI中使用异步通知

    概述 异步通知是客户端开发中常见的需求,比如在一个网络处理线程中要通知UI线程更新等等. 通常在Windows编程中,为了方便,我们一般会向UI线程的窗口句柄Post/Send一个窗口消息从而达到将非 ...

  9. 嵌入式Linux驱动学习之路(十三)按键驱动-异步通知

    之前的按键方式: 查询: 极度占用CPU资源 中断: 在读的时候产生休眠,在没有信号的时候永远不会返回. poll机制: 在中断的基础上加上超时时间. 异步通知就是通过信号来传送. 首先在应用程序中有 ...

随机推荐

  1. python3.7安装模块MySQLdb报错error: Microsoft Visual C++ 14.0 is required.

    error: Microsoft Visual C++ 14.0 is required. Get it with "Microsoft Visual C++ Build Tools&quo ...

  2. git下载别人的代码

    1. 打开别人github上的源码地址,点击Clone or download 2. 拷贝链接 3. 通过git clone URL来下载 此外,还可以通过pwd来查看当前目录的路径,一般都是下载到当 ...

  3. poj3468线段树标记永久化

    #include<map> #include<set> #include<list> #include<cmath> #include<queue ...

  4. Python 用Redis简单实现分布式爬虫

    Redis通常被认为是一种持久化的存储器关键字-值型存储,可以用于几台机子之间的数据共享平台. 连接数据库 注意:假设现有几台在同一局域网内的机器分别为Master和几个Slaver Master连接 ...

  5. 四十三 Python分布式爬虫打造搜索引擎Scrapy精讲—elasticsearch(搜索引擎)的mapping映射管理

    1.映射(mapping)介绍 映射:创建索引的时候,可以预先定义字段的类型以及相关属性elasticsearch会根据json源数据的基础类型猜测你想要的字段映射,将输入的数据转换成可搜索的索引项, ...

  6. 51nod 1640 MST+二分

    http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1640 1640 天气晴朗的魔法 题目来源: 原创 基准时间限制:1 秒 ...

  7. puppet笔记

    简介: puppet是一种Linux.Unix平台的集中配置管理系统,使用ruby语言,可管理配置文件.用户.cron任务.软件包.系统服务等.puppet把这些系统实体称之为资源,puppet的设计 ...

  8. python基础之面向对象(二)

    面向对象对程序设计OOD 找对象---->找类(归纳对象相同的特征与技能,还有没和对象独有的特征)面向对象编程OOP 先定义类---->实例化出对象查看成绩,交作业 在python3中,所 ...

  9. HTTPPost/AFNetWorking/JSONModel/NSPredicate

    一.HTTPPost================================================ 1. POST方式发送请求 HTTP协议下默认数据发送请求方法是GET方式,若需要 ...

  10. laravel5表单验证

    学习laravel框架有一段时间了,觉得它自带的表单验证特别好用,和大家分享分享 对于一些验证规则手册上都有,相信大家看了就会,我简单的说下怎么使用自定义正则验证: 验证手机号:'tel' => ...