驱动对异步IO的实现

驱动对异步IO的实现

用一句话描述:就是一旦设备就绪(比如发生了某个硬件中断,或者得到了某个资源),则驱动层向应用程序发送信号,触发应用程序的信号服务函数
使用这种方法,应用层就可以不用一直去查询设备状态,这其实是软件层次上对中断机制的一种模拟

1.应用层接收信号

  • 异步通知是基于信号的,信号还可以用于进程间通信。Linux中的信号有很多,具体可以去查信号表,除了SIGSTOP 和 SIGKILL 两个信号外(kill -9 就是利用了SIGKILL这个信号),我们可以设置进程忽略或捕获其他的全部信号
  • 要让进程支持异步通知,做一些简单的设置即可
/*定义一个信号服务函数*/
void sigterm_handler(int signo)
{
    ...
}


/*可以在main函数中做如下设置*/
...
signal(SIGIO, xxx_handler); /* 让xxx_handler()处理 SIGIO 信号 */
/*设置设备文件的拥有者为本进程,即设置了设备文件将向本进程发信号*/
fcntl(fd, F_SETOWN, getpid());
/*设置flag为FASYNC,使设备文件支持异步通知*/
oflags = fcntl(fd, F_GETFL);
fcntl(fd, F_SETFL, oflags | FASYNC);
...
  • signal接口用来绑定信号和信号服务函数,此处我们选用SIGIO信号。值得注意的是,多个不同的信号可以绑定同一个服务函数,这也是为什么服务函数有signo这个参数的原因,当信号服务函数被触发时,可以通过signo得知是哪个信号触发了自己
  • 利用fcntl设置设备文件的拥有者为本进程,即设置了设备文件将向本进程发信号
  • 最后设置设备文件的flag为FASYNC,使设备文件支持异步通知

2.驱动层发送信号

  • 首先定义异步结构体指针,一般是全局变量,被定义在驱动程序中device的结构体中
struct fasync_struct *async_queue; /* 异步结构体指针 */
  • 然后还需要提供file operation中的.fasync操作,这个函数很简单,其实就是一层皮,我们只要调用fasync_helper接口即可
static int xxx_fasync(int fd, struct file *filp, int mode)
{
    return fasync_helper(fd, filp, mode, async_queue);
}
  • 当资源到位时,发送信号,这一步很多时候在硬件中断中完成。此处我们选用SIGIO信号,可读时第 3 个参数设置为POLL_IN,可写时第 3 个参数设置为 POLL_OUT
/*发信号*/
if (async_queue){
    kill_fasync(async_queue, SIGIO, POLL_IN);
}
  • 最后,在文件关闭时,即在设备驱动的 release()函数中,应调用设备驱动的 fasync()函数将文件从异步通知的列表中删除
static int xxx_release(struct inode *inode, struct file *filp)
{
    /* 将文件从异步通知列表中删除 */
    xxx_fasync(-1, filp, 0);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值