linux下使用异步通知
阻塞式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下使用异步通知相关推荐
- linux下aio异步读写详解与实例
1.为什么会有异步I/O aio异步读写是在linux内核2.6之后才正式纳入其标准.之所以会增加此模块,是因为众所周知我们计算机CPU的执行速度远大于I/O读写的执行速度,如果我们用传统的阻塞式或非 ...
- 【正点原子Linux连载】第五十三章 异步通知实验 -摘自【正点原子】I.MX6U嵌入式Linux驱动开发指南V1.0
1)实验平台:正点原子阿尔法Linux开发板 2)平台购买地址:https://item.taobao.com/item.htm?id=603672744434 2)全套实验源码+手册+视频下载地址: ...
- 异步通知实验(信号)
目录 异步通知 异步通知简介 驱动中的信号处理 应用程序对异步通知的处理 硬件原理图分析 实验程序编写 修改设备树文件 程序编写 编写测试APP 运行测试 编译驱动程序和测试APP 运行测试 在前面使 ...
- PHP 命令行模式实战之cli+mysql 模拟队列批量发送邮件(在Linux环境下PHP 异步执行脚本发送事件通知消息实际案例)...
源码地址:https://github.com/Tinywan/PHP_Experience 测试环境配置: 环境:Windows 7系统 .PHP7.0.Apache服务器 PHP框架:ThinkP ...
- Linux内核开发之异步通知与异步I/O《来自linux设备开发详解》
阻塞I/O意味着一直等待设备可访问再访问,非阻塞I/O意味着使用poll()来查询是否可访问,而异步通知则意味着设备通知应用程序自身可访问.(异步通知:很简单,一旦设备准备好,就主动通知应用程序,这种 ...
- 你真的懂Linux内核中的阻塞和异步通知机制吗?(花了五天整理,墙裂推荐!)
工科生一枚,热衷于底层技术开发,有强烈的好奇心,感兴趣内容包括单片机,嵌入式Linux,Uboot等,欢迎学习交流! 爱好跑步,打篮球,睡觉. 欢迎加我QQ1500836631(备注CSDN),一起学 ...
- linux. qt信号崩溃,【创龙AM4379 Cortex-A9试用体验】之I/O中断异步通知驱动程序+QT捕获Linux系统信号+测试信号通知...
2.驱动程序 安装字符设备驱动程序开发流程开发. 2.1资源定义 定义按键I/O端口号.I/O中断号,以及字符设备的主设备号变量: #define GPIO_KEY1_PIN_NUM (3*32 + ...
- linux编写驱动后write已杀死_《Linux4.0设备驱动开发详解》笔记--第九章:Linux设备驱动中的异步通知与同步I/O...
在设备驱动中使用异步通知可以使得对设备的访问可进行时,由驱动主动通知应用程序进行访问.因此,使用无阻塞I/O的应用程序无需轮询设备是否可访问,而阻塞访问也可以被类似"中断"的异步通 ...
- i.MX6ULL终结者Linux异步通知实验编写实验程序
文章目录 1 驱动程序编写 2 应用测试程序 3 运行测试 1 驱动程序编写 本实验例程路径:i.MX6UL终结者光盘资料/06_Linux驱动例程/13_key_signal 驱动程序在key_po ...
最新文章
- 关于iOS 架构的文章
- 起底滴滴数据科学团队:面对超复杂线下场景,要数据驱动,但拒绝“唯数据论”...
- [IS-IS] IS-IS路由协议的基本知识及配置
- 2Boost之UPD,Client and Server
- 【EXLIBRIS】纸版书目整理 -- 大书架 上 【292 种】【327册】
- 汇报时,如何让老板快速抓住重点?—— 黄金三步法
- 7-7 天梯赛的善良 (20 分)
- docker 配置ssh
- CVE-2020-16875: Microsoft Exchange远程代码执行漏洞通告
- POJ 1330 Nearest Common Ancestors / UVALive 2525 Nearest Common Ancestors (最近公共祖先LCA)...
- 高斯消元法(Gauss Elimination) 分析 题解 模板——czyuan原创
- java版本位数_java 如何查看jdk版本位数
- java使用RunTime调用windows命令行
- 主板声卡坏了会不会有电流声_不同领域适使用不同类型声卡,千万别选错了~~~...
- HTML期末大作业~酒店网站模板(HTML+CSS+JavaScript)
- ssh工具连接虚拟机(finalshell)
- Vue模板语法——插值
- 微型计算机原理(第六版)姚向华编著(转载请注明出处---https://www.cnblogs.com/qingl)...
- rstudio线性回归_R语言线性回归
- GitHub上传教程,图文并茂