linux驱动---file_operations异步读写aio_read、aio_write
2017-02-06 13:49
447 查看
简述:
file_operations中read,write是同步读写,异步读写用接口是aio_read、aio_wirte(在4.5版本中发现已经把名字改成read_iter、write_iter)。
异步读写对应的系统调用API:
定义在头文件中(如ubuntu,/usr/include/aio.h):
详细的关于异步读写应用程序编程,参考下面博客:
慢慢聊Linux AIO
场景考虑:
同步读写:应用程序发起读写后,等到读写函数完成返回,才能继续跑后面的代码。
异步读写:应用程序发起读写后,将读写注册到队列,然后立马返回,应用程序继续跑后面的代码,速度非常快,当读写动作完成后,系统发消息通知应用程序,然后应用程序接收读写结果。
根据场景选择,驱动可以同时都实现同步和异步的接口。
file_operations结构体定义(在include/linux/fs.h):
其中异步读写:
在linux 4.5版本中已经变成:
驱动如果已经实现了同步的读写,异步的实现还需要用到include/linux/aio.h中的数据结构和函数以及工作队列。
异步结构体struct kiocb;
函数:bool is_sync_kiocb(struct kiocb *kiocb),判断此处aio_read或aio_write是否指定为同步,是同步返回true,不是同步返回false。
函数:void aio_complete(struct kiocb *iocb, long res, long res2),通知系统异步完成,res为读取字节数,res2一般为0.
驱动接口实现例子:
新版本的用法如下:
这样,如果本次异步系统调用指定为同步,就和一般的read一样,如果是异步,就加入到一个workqueue,等到work(这个work,最好用延时版本)完成后,再通知系统。(个人理解,没有验证过- _ -,后面验证如发现不对再修改)
这样,应用程序(进程)可以很快返回,将读写的动作交给了workqueue的线程处理,完成后,再通知应用程序。
然后:
就ok,异步写和读差不多用法。
异步读写,主要是在系统中差异,驱动只要实现对应的接口,类似同步的。
参考博客:
Linux驱动中的异步函数
file_operations中read,write是同步读写,异步读写用接口是aio_read、aio_wirte(在4.5版本中发现已经把名字改成read_iter、write_iter)。
异步读写对应的系统调用API:
int aio_read(struct aiocb *__aiocbp); int aio_write(struct aiocb *__aiocbp);
定义在头文件中(如ubuntu,/usr/include/aio.h):
#include <aio.h>
详细的关于异步读写应用程序编程,参考下面博客:
慢慢聊Linux AIO
场景考虑:
同步读写:应用程序发起读写后,等到读写函数完成返回,才能继续跑后面的代码。
异步读写:应用程序发起读写后,将读写注册到队列,然后立马返回,应用程序继续跑后面的代码,速度非常快,当读写动作完成后,系统发消息通知应用程序,然后应用程序接收读写结果。
根据场景选择,驱动可以同时都实现同步和异步的接口。
file_operations结构体定义(在include/linux/fs.h):
struct file_operations { struct module *owner; loff_t (*llseek) (struct file *, loff_t, int); ssize_t (*read) (struct file *, char __user *, size_t, loff_t *); ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *); ssize_t (*aio_read) (struct kiocb *, const struct iovec *, unsigned long, loff_t); ssize_t (*aio_write) (struct kiocb *, const struct iovec *, unsigned long, loff_t); int (*readdir) (struct file *, void *, filldir_t); unsigned int (*poll) (struct file *, struct poll_table_struct *); long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long); long (*compat_ioctl) (struct file *, unsigned int, unsigned long); int (*mmap) (struct file *, struct vm_area_struct *); int (*open) (struct inode *, struct file *); int (*flush) (struct file *, fl_owner_t id); int (*release) (struct inode *, struct file *); int (*fsync) (struct file *, loff_t, loff_t, int datasync); int (*aio_fsync) (struct kiocb *, int datasync); int (*fasync) (int, struct file *, int); int (*lock) (struct file *, int, struct file_lock *); ssize_t (*sendpage) (struct file *, struct page *, int, size_t, loff_t *, int); unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long); int (*check_flags)(int); int (*flock) (struct file *, int, struct file_lock *); ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, loff_t *, size_t, unsigned int); ssize_t (*splice_read)(struct file *, loff_t *, struct pipe_inode_info *, size_t, unsigned int); int (*setlease)(struct file *, long, struct file_lock **); long (*fallocate)(struct file *file, int mode, loff_t offset, loff_t len); int (*show_fdinfo)(struct seq_file *m, struct file *f); };
其中异步读写:
ssize_t (*aio_read) (struct kiocb *, const struct iovec *, unsigned long, loff_t); ssize_t (*aio_write) (struct kiocb *, const struct iovec *, unsigned long, loff_t);
在linux 4.5版本中已经变成:
ssize_t (*read_iter) (struct kiocb *, struct iov_iter *); ssize_t (*write_iter) (struct kiocb *, struct iov_iter *);
驱动如果已经实现了同步的读写,异步的实现还需要用到include/linux/aio.h中的数据结构和函数以及工作队列。
异步结构体struct kiocb;
函数:bool is_sync_kiocb(struct kiocb *kiocb),判断此处aio_read或aio_write是否指定为同步,是同步返回true,不是同步返回false。
函数:void aio_complete(struct kiocb *iocb, long res, long res2),通知系统异步完成,res为读取字节数,res2一般为0.
驱动接口实现例子:
struct kiocb *aki; struct iovec *aiov; loff_t aio_off = 0; struct workqueue *aiowq; void data_a(struct work_struct *work); DECLARE_DELAYED_WORK(aio_delaywork,data_a); ssize_t d_read(struct file *f, char __user *buf, size_t n, loff_t *off) { } void data_a(struct work_struct *work) { int ret = 0; ret = d_read(aki->ki_filp,aiov->iov->iov_base,n,&off); aio_complete(aki,ret ,0); } ssize_t d_aio_read(struct kiocb *ki, const struct iovec *iovs, unsigned long n, loff_t off) { if(is_sync_kiocb(ki)) return d_read(ki->ki_filp,iovs->iov->iov_base,n,&off); else { aki = ki; aiov = iovs; aio_off = off; queue_delayed_work(aiowq,aio_delaywork,100); return -EIOCBQUEUED;//一般都返回这个, } } void init_aio() { aiowq= create_workqueue("aiowq"); }
新版本的用法如下:
ssize_t d_read_iter(struct kiocb *ki, struct iov_iter *iovs) { if(is_sync_kiocb(ki)) return d_read(ki->ki_filp,iovs->iov->iov_base,n,&off); else { aki = ki; aiov = iovs; aio_off = off; queue_delayed_work(aiowq,aio_delaywork,100); return -EIOCBQUEUED; } }
这样,如果本次异步系统调用指定为同步,就和一般的read一样,如果是异步,就加入到一个workqueue,等到work(这个work,最好用延时版本)完成后,再通知系统。(个人理解,没有验证过- _ -,后面验证如发现不对再修改)
这样,应用程序(进程)可以很快返回,将读写的动作交给了workqueue的线程处理,完成后,再通知应用程序。
然后:
struct file_operations fop = { ..... ... .aio_read = d_aio_read, ..... ... };
就ok,异步写和读差不多用法。
异步读写,主要是在系统中差异,驱动只要实现对应的接口,类似同步的。
参考博客:
Linux驱动中的异步函数
相关文章推荐
- Linux简单设备驱动(2): file_operations的write、read、ioctl驱动及Android应用层开发验证
- linux kernel read write file 读写文件
- linux驱动之file_operations
- 驱动该如何入门 关于file_operations和Linux设备模型
- Linux 设备驱动中的file_operations
- linux下aio异步读写详解与实例
- linux设备驱动第三版笔记---->linux驱动重要数据结构之file_operations
- RandomAccessFile,read,write,复制文件,指针,批量读写,基本类型读写
- Linux下异步I/0:O_ASYNC标志,aio_read
- 【驱动开发】file_operations ---linux 2.6.30
- Linux下异步I/0:O_ASYNC标志,aio_read
- linux下文件的读写操作(openreadwrite)
- sys_read()/vfs_read()/vfs_write() Linux VFS文件系统之读写(read/write)文件
- linux驱动的read和write
- Linux 驱动学习笔记(file_operations结构体详细分析)
- Linux下异步I/0:O_ASYNC标志,aio_read
- linux设备驱动归纳总结(三):2open.close.read.write
- Linux下异步I/0:O_ASYNC标志,aio_read
- Linux 字符设备驱动开发基础(三)—— read()、write() 相关函数解析
- linux下文件的读写操作(openreadwrite)