阻塞式I/O是一直等待直到设备可以访问,非阻塞式I/O是定期轮询设备是否可以访问。

异步通知则是当设备可以访问时才主动通知应用程序,有点像设备的硬中断。

并不是所有的设备都支持异步通知,应用程序通常假设只有套接字和终端才有异步通知的能力。

异步通知存在一个问题,当进程收到SIGIO信号时,它并不知道是哪个文件有了新的输入,如果

有多于一个的文件可以异步通知同一个进程,那么应用进程还需要借助于poll或select来确定输入

的来源。

应用层

fcntl - manipulate file descriptor

fcntl(fd, F_SETFL, flags | O_ASYNC);

效果:

If you set the O_ASYNC status flag on a file descriptor by using the F_SETFL command of fcntl(),

a SIGIO signal is sent whenever input or output becomes possible on that file descriptor.

例子

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>
#include <fcntl.h> #define MAX_LEN 100 void my_handler(int signum)
{
char data[MAX_LEN];
int len; len = read(STDIN_FILENO, &data, MAX_LEN);
data[len] = 0; printf("Input message: %s\n", data);
exit(0);
} int main(void)
{
int oflags; /* set new SIGIO handler */
signal(SIGIO, my_handler);
/* set fd's owner process */
fcntl(STDIN_FILENO, F_SETOWN, getpid());
/* get old fd flags */
oflags = fcntl(STDIN_FILENO, F_GETFL);
/* set new fd flags */
fcntl(STDIN_FILENO, F_SETFL, oflags | O_ASYNC); /* infinitely wait until recv SIGIO */
while(1);
return 0;
}

为了能处理设备发出的SIGIO信号,用户程序需要做:

1. 设置设备文件的拥有者为本进程,这样一来才能收到设备驱动发出的SIGIO信号。

2. 使设备文件支持异步通知,即设置O_ASYNC标志。

3. 通过signal()指定SIGIO的处理函数。

设备驱动

struct fasync_struct {
spinlock_t fa_lock;
int magic;
int fa_fd; /* 文件描述符 */
struct fasync_struct *fa_next; /* 用于链入单向链表 */
struct file *fa_file; /* fa_file->f_owner记录接收信号的进程 */
struct rcu_head fa_rcu;
};

(1) 设备的异步通知链

struct xxx_dev {
struct cdev cdev;
...
struct fasync_struct *async_queue; /* 异步通知链 */
};

(2) 插入到异步通知链

static int xxx_fasync(int fd, struct file *filp, int on)
{
struct xxx_dev *dev = filp->private_data;
return fasync_helper(fd, filp, on, &dev->async_queue);
}

(3) 发送信号通知进程

设备使用kill_fasync()来发送信号给用户进程,一般sig为SIGIO,可读时band为POLL_IN,

可写时band为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);
}
...
}

(4) 从异步通知链中删除

在关闭文件时,需要把对应的异步通知结构从链表中删除。

static xxx_release(struct inode *inode, struct file *filp)
{
struct xxx_dev *dev = filp->private_data;
...
fasync_helper(-1, filp, 0, &dev->async_queue);
...
}

内核API

异步通知结构体的插入和删除,失败返回负值,没有变化返回0,有变化返回正值。

/* fasync_helper() is used by almost all character device drivers to set up the
* fasync queue, and for regular files by the file lease code. It returns negative
* on error, 0 if it did no changes and positive if it added/deleted the entry.
*/ int fasync_helper(int fd, struct file *filp, int on, struct fasync_struct **fapp)
{
if (!on) /* 删除 */
return fasync_remove_entry(filp, fapp);
return fasync_add_entry(fd, filp, fapp); /* 插入 */
}

发送信号,通知用户进程,sig一般设为SIGIO,可读时band为POLL_IN,可写时band为POLL_OUT。

void kill_fasync(struct fasync_struct **fp, int sig, int band)
{
/* First a quick test without locking: usually the list is empty. */
if (*fp) {
rcu_read_lock();
kill_fasync_rcu(rcu_dereference(*fp), sig, band);
rcu_read_unlock();
}
}

Reference

[1]. http://www.cnblogs.com/hanyan225/archive/2010/10/20/1857040.html

[2]. 《设备驱动程序》

linux下使用异步通知的更多相关文章

  1. Linux驱动之异步通知的应用

    前面的按键驱动方式都是应用程序通过主动查询的方式获得按键值的: 1.查询方式 2.中断方式 3.poll机制 下面介绍第四种按键驱动的方式 4.异步通知:它可以做到应用程序不用随时去查询按键的状态,而 ...

  2. linux驱动的异步通知(kill_fasync,fasync)---- 驱动程序向应用程序发送信号

    应用程序 #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include < ...

  3. linux 下同步异步,堵塞非堵塞的一些想法

    补充: 发现一个更好的解释样例:同步是一件事我们从头到尾尾随着完毕.异步是别人完毕我们仅仅看结果. 堵塞是完毕一件事的过程中可能会遇到一些情况让我们等待(挂起).非堵塞就是发生这些情况时我们跨过. 比 ...

  4. Linux通信之异步通知模式

    [参考]韦东山 教学笔记 为了使设备支持异步通知机制,驱动程序中涉及以下3项工作:1. 支持F_SETOWN命令,能在这个控制命令处理中设置filp->f_owner为对应进程ID. 不过此项工 ...

  5. Oracle在Linux下使用异步IO(aio)配置

    1.首先用root用户安装以下必要的rpm包 # rpm -Uvh libaio-0.3.106-3.2.x86_64.rpm# rpm -Uvh libaio-devel-0.3.106-3.2.x ...

  6. Linux学习 :按键信号 之 异步通知

    一.异步通知概念: 异步通知是指:一旦设备就绪,则主动通知应用程序,应用程序根本就不需要查询设备状态,类似于中断的概念,一个进程收到一个信号与处理器收到一个中断请求可以说是一样的.信号是异步的,一个进 ...

  7. PHP 命令行模式实战之cli+mysql 模拟队列批量发送邮件(在Linux环境下PHP 异步执行脚本发送事件通知消息实际案例)

    源码地址:https://github.com/Tinywan/PHP_Experience 测试环境配置: 环境:Windows 7系统 .PHP7.0.Apache服务器 PHP框架:ThinkP ...

  8. Linux的fasync驱动异步通知详解【转】

    本文转载自:http://blog.csdn.net/coding__madman/article/details/51851338 版权声明:本文为博主原创文章,未经博主允许不得转载. 工作项目用有 ...

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

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

随机推荐

  1. chrome下positon:fixed无效或抖动的解决办法

    先来看一下我们要实现的效果 我想这种效果大家都有实现过,或者说吸顶的效果和这差不多 页面结构 js代码如下 /*吸顶*/ var $child = $("#child_3"); v ...

  2. CAP原理和BASE思想和ACID模型

    问题的解读 对于上面三个例子,相信大家一定看出来了,我们的终端用户在使用不同的计算机产品时对于数据一致性的需求是不一样的: 1.有些系统,既要快速地响应用户,同时还要保证系统的数据对于任意客户端都是真 ...

  3. Jenkins执行批处理文件、powershell失败

    今天搭建Jenkins持续集成环境,编译环境是.net core.整理了一些发布的命令配置在Jenkins,问题来了,使用powershell插件运行dotnet restore.dotnet bui ...

  4. Oracle中查询和删除相同记录的3种方法

    --创建测试表 )); ,'); ,'); ,'); ,'); ,'); ,'); commit; select * from test; --查询相同记录 ); select id,name fro ...

  5. 无忧代理免费ip爬取(端口js加密)

    起因 为了训练爬虫技能(其实主要还是js技能-),翻了可能有反爬的网站挨个摧残,现在轮到这个网站了:http://www.data5u.com/free/index.shtml 解密过程 打开网站,在 ...

  6. JavaScript的事件、DOM模型、事件流模型以及内置对象详解(三)

    JS中的事件 JS中的事件分类 1.鼠标事件: click/dbclick/mouseover/mouseout 2.HTML事件: onload/onunload/onsubmit/onresize ...

  7. Ruby 2.x 命名参数特性简介

    我以前曾有一个梦想,就是我的爹是李嘉诚-,那个-,不是啦,我的梦想是ruby像ObjC,或是现在的swift那样给方法提供命名参数. 之前的ruby只能用hash来模拟这个行为,不过你没法很容易的定义 ...

  8. Linux系统中查询发行版本号以及内核版本的命令总结

    了解Linux发行版本的版本号是一项非常重要的事情,大多数软件对系统的版本都有要求,发行版本号与软件不匹配,软件将无法安装或者无法使用.这边集合市面上流行的Linux发行版本版本号查询方法.有了这边文 ...

  9. 在Mac上搭建React Native开发环境

    概述 前面我们介绍过在window环境下开发React Native项目,今天说说怎么在mac上搭建一个RN的开发环境. 配置mac开发环境 基本环境安装 1.先安装Homebrew:用于安装Node ...

  10. 理解性能的奥秘——应用程序中慢,SSMS中快(4)——收集解决参数嗅探问题的信息

    本文属于<理解性能的奥秘--应用程序中慢,SSMS中快>系列 接上文:理解性能的奥秘--应用程序中慢,SSMS中快(3)--不总是参数嗅探的错 前面已经提到过关于存储过程在SSMS中运行很 ...