kernel 异步
2016-08-02 22:45
246 查看
异步
一旦设备就绪,则主动通知应用程序,这样应用程序根本就不需要查询状态用户空间处理一个设备释放的信号的三项工作:
/* specify handler for signal */ signal(SIGIO, input_handler); /* current process owns this fd */ fcntl(STDIN_FILENO, F_SETOWN, getpid()); /* launch the async mechanism */ flags = fcntl(STDIN_FILENO, F_GETFL); fcntl(STDIN_FILENO, F_SETFL, flags | FASYNC);
异步通知的设备驱动模版
struct xxx_dev { struct cdev cdev; ... struct fasync_struct *async_queue; }; static int xxx_fasync(int fd, struct file *filp, int mode) { struct xxx_dev *dev = filp->private_data; /* when file has been set as async mode, add fd into async queue */ return fasync_helper(fd, filp, mode, &dev->async_queue); } static ssize_t xxx_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos) { struct xxx_dev *dev = filp->private_data; ... /* launch async read signal */ if (dev->async_queue) kill_fasync(&dev->async_queue, SIGIO, POLL_IN); ... } static int xxx_release(struct inode *inode, struct file *filp) { /* delete fd from async_queue */ xxx_fasync(-1, filp, 0); ... return 0; }
AIO
异步I/O的时序:发起I/O动作后,并不等待I/O结束,
+ 要么过一段时间来查询之前的I/O请求完成情况
+ 要么I/O请求完成了会自动调用绑定的回调函数
AIO 多种实现
在用户空间的glibc库中实现
基于线程实现,通过 pthread_cond_signal() 实现线程间同步1. aio_read()
2. aio_write()
3. aio_error() 确定请求的状态
4. aio_return()
5. aio_suspend()
6. aio_cancel()
7. lio_listio()
采用 aio_return() 不断询问的方式
#include <aio.h> int fd, ret; struct aiocb my_aiocb; fd = open("file.txt", O_RDONLY); if (fd < 0) printf("open failed\n"); bzero(&my_aiocb, sizeof(struct aiocb)); my_aiocb.aio_buf = malloc(BUFSIZE + 1); if (!my_aiocb.aio_buf) printf("malloc failed\n"); my_aiocb.aio_fildes = fd; my_aiocb.aio_nbytes = BUFSIZE; my_aiocb.aio_offset = 0; ret = aio_read(&my_aiocb); if (ret < 0) printf("aio_read failed\n"); while (aio_error(&my_aiocb) == EINPROGRESS) continue; if ((ret = aio_return(&my_aiocb)) > 0) /* read success */ else /* read failed */
采用 aio_suspend() 阻塞的方式
struct aiocb *cblist[MAX_LIST]; bzero((char *)cblist, sizeof(cblist)); cblist[0] = &my_aiocb; ... ret = aio_read(&my_aiocb); ret = aio_suspend(cblist, MAX_LIST, NULL);
采用 lio_listio() 操作多个io control block
struct aiocb aiocb1, aiocb2; struct aiocb *cblist[MAX_LIST]; aiocb1.aio_fildes = fd; aiocb1.aio_buf = malloc(BUFSIZE + 1); aiocb1.aio_nbytes = BUFSIZE; aiocb1.aio_offset = 0; aiocb1.aio_lio_opcode = LIO_READ; ... bzero((char *)cblist, sizeof(cblist)); cblist[0] = &aiocb1; cblist[1] = &aiocb2; ... /* LIO_WAIT means block mode */ ret = lio_listio(LIO_WAIT, list, MAX_LIST, NULL);
内核提供 libaio 的系统调用
AIO的读写请求都用 io_submit() 下发。下发前通过 io_prep_pwrite() 和 io_prep_pread() 生成iocb的结构体,作为 io_submit() 的参数。这个结构体指定了读写类型、起始地址、长度和设备标识符等信息。读写请求下发之后,使用 io_getevents() 函数等待I/O完成事件。 io_set_callback() 设置一个AIO完成的回调函数。file_operation 包含3个与AIO相关的成员函数:
* aio_read()
* aio_write()
* aio_fsync()
io_submit() 间接调用 file_operation 中 aio_read() 和 aio_write()
总结
内核包含对AIO的支持,为用户空间提供了统一的异步I/O接口。glibc也提供了不依赖内核的用户空间AIO支持。相关文章推荐
- <2012 11 6 > linux设备驱动程序开发初探(6) 异步通讯机制: Kernel ---> APP
- finding hidden modules on 2.6 kernel_module_hunter(zz)
- .net socket与完成端口、异步发送相关研究
- jquery 异步提交表单 上传图片小例子
- Servlet 3特性:异步Servlet
- 6410开发板通过USB烧写u-boot,kernel,system
- 【开源项目1】使用ImageLoader实现图片异步加载
- 怎样理解同步异步与阻塞非阻塞的区别?
- 基于ajax的异步分页技术实现
- 如何通过异步方法读取消息队列(BeginReceive())?
- Windows I/O模型、同步/异步、阻塞/非阻塞
- Adobe Edge Animate --异步条件加载框架(yepnop)之三:加载bootstrap之按钮、进度条、菜单效果
- C#异步调用四大方法
- jquery 异步请求Demo【转载】
- 同步异步和阻塞非阻塞模式
- android异步加载
- NSURLConnection 异步请求
- jQuery异步验证用户名是否存在示例代码
- 异步文件 I/O