版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
第13章I/O操作模式内容提要
/O操作模式概述
POSIX异步I/OLinux本地异步I/O异步I/O信号驱动I/O多路复用高性能I/O事件驱动13.1I/O操作模式I/O操作模式概述
在Linux系统中,文件作为一个泛化的概念,广泛存在于系统。虽然为文件定义了标准的I/O操作集,但具体实现取决于文件,不同类型的文件具有不同的行为特征。,它们实现的操作集也可能有所不同,如,具有异步特性的网络套接字,慢速的磁盘设备等。当进程需要同时处理多个文件I/O时,基于阻塞的处理方式具有一定的局限性,为此,内核提供了多种非阻塞的处理方法。阻塞与非阻塞
从用户的角度,对于向内核发起的I/O请求,发起者是否需要等待请求的完成,可将I/O模式分为阻塞与非阻塞。若发起者等待,直至I/O请求完成,则称为I/O阻塞模式;若无论I/O请求是否完成,发起者立即返回,则称为I/O非阻塞模式。同步与异步
从内核的角度,对于发起的I/O请求,内核是否需要发起者等待请求的完成,可将I/O模式分为同步I/O模式和异步I/O模式。若内核需发起者等待,直至I/O请求完成,则称为I/O同步模式。若内核无须发起者等待,I/O请求完成时,内核以某种方式通知发起者,期间发起者可继续执行后续操作,则称为I/O异步模式。异步I/O模式
对于需在一个进程中同时监听多个文件的I/O状态,内核提供了多种异步I/O处理模式,它们通常采用非阻塞模式。这些异步I/O方法包括。POSIX异步I/O本地异步I/O异步I/O信号驱动I/O多路复用高性能I/O事件驱动应用编程接口分类接口函数功能描述POSIX异步I/Oaio_read发起异步读请求aio_write发起异步写请求lio_listio提交多个异步I/O请求aio_cancel试图取消异步I/O请求aio_return返回已完成的I/O状态aio_error获得异步I/O错误信息Linux本地异步I/Oio_setup创建异步I/O环境io_submit提交异步I/O请求io_getevents获取已完成异步I/O请求io_cancel取消一个未完成的异步IO操作io_destro注销异步I/O环境I/O多路复用select同时监听多个文件的I/O状态poll同时监听多个文件的I/O状态高性能I/O事件驱动epoll_create创建epoll环境epoll_ctl设置监听对象epoll_wait等待epoll实例上产生的I/O就绪事件13.2POSIX异步I/OPOSIX异步I/O概述POSIX为程序员提供了一组异步I/O编程接口,允许向内核发起一个或多个异步I/O请求,发起者无须等待I/O操作完成,继续执行后续操作,当异步I/O操作完成,内核以某种方式通知发起者,例如,发送信号或启动线程等。Linux异步I/O的实现
POSIX异步I/O在Linux系统中以glibc函数库方式实现,由于早期的内核不支持异步I/O,glibc利用线程处理异步I/O请求;自内核2.6起引入一组本地异步I/O系统调用接口,glibc对原异步I/O处理进行了重构,从根本上提高了异步I/O性能。值得注意的是,POSIX异步I/O仅适用于磁盘文件系统。发起异步读/写请求1.aio_read/aio_write函数头文件
#include<aio.h>函数原型
int
aio_read(struct
aiocb*aiocbp)
int
aio_write(struct
aiocb*aiocbp)功能 发起异步读/写请求。参数
aiocbp:I/O请求。返回值 成功返回0,失败返回-1。发起异步读/写请求(续)(1)异步I/O请求struct
aiocb{
int
aio_fildes; //文件描述符
volatilevoid*aio_buf;//缓冲区地址
size_t
aio_nbytes; //读/写数据的字节数
off_t
aio_offset; //文件偏移量
int
aio_reqprio; //请求优先级
struct
sigevent
aio_sigevent;//通知方式
int
aio_lio_opcode; //仅适用于lio_listio函数};(2)通知方式struct
sigevent{
int
sigev_notify;//通知方法
int
sigev_signo;//信号编号
unionsigval
sigev_value;//传递的数据
void(*sigev_notify_function)(unionsigval);//线程函数
void*sigev_notify_attributes;//线程属性
pid_t
sigev_notify_thread_id;//线程ID};一次提交多个异步I/O请求2.lio_listio函数头文件
#include<aio.h>函数原型
int
lio_listio(int
mode,struct
aiocb*constaiocb_list[],int
nitems,struct
sigevent*sevp);功能 一次提交多个异步I/O请求。参数
mode:提交模式。
aiocb_list:请求数组。
nitems:请求数量。
sevp:通知方式。返回值 所有I/O成功提交返回0,失败返回-1。取消已提交的异步I/O请求3.aio_cancel函数头文件
#include<aio.h>函数原型
int
aio_cancel(int
fd,struct
aiocb*aiocbp);功能 取消已提交的异步I/O请求。参数
fd:文件描述符。
aiocbp:异步I/O请求。返回值 若返回AIO_CANCELED,请求全部被取消。获取异步I/O的返回值4.aio_return函数头文件
#include<aio.h>函数原型
ssize_t
aio_return(struct
aiocb*aiocbp);功能 获取异步I/O的返回值。参数
aiocbp:异步I/O请求。返回值
I/O请求完成,返回异步处理的字节数。
I/O请求失败,返回-1。获取异步I/O请求的当前状态5.aio_error函数头文件
#include<aio.h>函数原型
int
aio_error(const
struct
aiocb*aiocbp);功能 获取异步I/O请求的当前状态。参数
aiocbp:异步I/O请求。返回值 若返回EINPROGRESS,表示正在处理。 若返回ECANCELED,表示异步操作被取消。 如返回0,表示异步操作已完成。 若返回值小于零,表示发生错误。13.3Linux本地异步I/O本地异步I/O概述
为了提高磁盘I/O请求的处理效率,Linux自内核2.6起,引入一组非标准化的本地异步I/O接口。该组接口是glibc构造POSIX异步I/O的基础。它由5个系统调用组成,glibc未对它们进行封装,但可借助syscall函数实现对它们的访问。创建/注销异步I/O上下文头文件
#include<linux/aio_abi.h>函数原型
io_setup(unsigned
nr_events,aio_context_t*ctx_idp);
int
io_destroy(aio_context_t
ctx_id);功能 创建/注销异步I/O上下文。参数
nr_events:容纳异步I/O请求的最大数量。
ctx_idp:异步I/O上下文。返回值 成功返回0,失败返回非0。提交异步I/O请求头文件
#include<linux/aio_abi.h>函数原型
longio_submit(aio_context_t
ctx_id,long
nr,struct
iocb**iocbpp)功能 提交异步I/O请求,参数
ctx_id:异步I/O上下文,
nr:异步I/O请求数量,
iocbpp:异步I/O请求数组,返回值 成功返回提交的请求数,失败返回非0,提交异步I/O请求(续)struct
iocb{__u64aio_data;//自定义参数
__u16aio_lio_opcode;//操作类型,IO_CMD_PWRITE,IO_CMD_PREAD__s16aio_reqprio;//请求的优先级
__u32aio_fildes;//文件描述符
__u64aio_buf;//数据缓存区
__u64aio_nbytes;//请求字节数
__s64aio_offset;//偏移量
...};取消已提交的异步IO请求头文件
#include<linux/aio_abi.h>函数原型
int
io_cancel(aio_context_t
ctx_id,struct
iocb*iocb,struct
io_event*result);io_event*result)功能 取消已提交的异步IO请求。参数
ctx_id:异步I/O上下文。
iocb:异步I/O请求。
result:返回消息。返回值 成功返回0,失败返回非0。获取已完成的异步I/O事件头文件
#include<linux/aio_abi.h>函数原型
longio_getevents(aio_context_t
ctx_id,longmin_nr,longnr,struct
io_event*events,struct
timespec*timeout)功能 获取已完成的异步I/O事件。参数
ctx_id:异步I/O上下文。
min_nr:请求完成的最小数量。
nr:请求完成的最大数量。
events:完成的I/O事件。
timeout:超时时间。返回值 成功返回事件数量,失败返回值在0至min_nr之间。获取已完成的异步I/O事件(续)struct
io_event{__u64data;//对应iocb的aio_data
__u64obj;//产生event的iocb__s64res;//完成的字节数
__s64res2;//返回状态};13.4异步I/O信号驱动异步I/O信号驱动概述
异步
I/O信号驱动是一种文件I/O状态改变时的信号通知机制,默认向目标进程发送SIGIO信号。
对于I/O信号驱动的文件,通常设置为非阻塞模式,信号属于边缘触发事件。
值得注意的是,并非所有文件都支持异步I/O信号。异步I/O信号的操作流程异步处理方式1.为文件定义I/O信号2.将文件设置为异步非阻塞模式3.设置信号的发送目标4.编写信号的处理函数异步I/O信号的操作流程(续)
同步处理方式1和2与异步处理方式相同。3.阻塞I/O信号4.以同步方式处理到达的I/O信号实时信号队列的溢出处理
当众多文件瞬间状态发生改变时,内核会产生大量I/O信号,即使使用了实时信号,也可能导致信号队列溢出。当I/O信号溢出时,新产生的I/O信号恢复为SIGIO,在处理SIGIO信号时,可使用sigwaitipfo函数尽快处理等待的信号,继而使用select/poll函数处理剩余的I/O事件。13.5I/O多路复用内容提要1I/O多路复用概述基于select的I/O多路复用基于poll的I/O多路复用1I/O多路复用概述I/O多路复用是一种同时监听多个文件I/O状态的技术,当有文件I/O状态发生改变时,以I/O事件方式通知监听者。事件的产生采用水平触发模式,只要I/O状态可用,就一直产生I/O事件。
Linux继承了Unix的select和poll两种I/O多路复用接口。基于select的I/O多路复用
处于历史原因select监听的文件受1024数量的限制,每次监听前都需将观察文件信息从用户空间拷贝至内核空间,监听时需扫描整个文件列表,以确定产生就绪I/O事件的文件,无疑增加了系统开销。select函数头文件
#include<sys/select.h> #include<sys/time.h>函数原型
int
select(int
nfds,fd_set*readfds,fd_set*writefds,fd_set*exceptfds,struct
timeval*timeout);功能 同时监听多个文件的I/O状态。参数
nfds:监听的最大文件描述符。readfds:可读文件描述符集。
writefds:可写的文件描述符集。exceptfds:例外文件描述符集。
timeout:超时时间。返回值
>0,返回就绪事件的数量。=0,等待超时。-1,错误。基于poll的I/O多路复用poll也是被广泛支持的I/O多路复用接口,功能与select相似,尽管poll对检查的文件数量没有限制,但每次监听仍需复制和扫描整个文件描述符。poll函数头文件
#include<sys/poll.h>函数原型
intpoll(struct
pollfd*fds,unsignedint
nfds,inttimeout);功能 同时监听多个文件的I/O状态。参数
fds:监听对象数组地址。
nfds:监听文件数量。
timeout:超时时间,单位毫秒。返回值 成功:发生就绪事件的文件数量失败:-1。poll函数(续)struct
pollfd{int
fd;//文件描述符shortevents;//关注的事件shortrevents;//已发生的事件};事件类型含义POLLIN有数据可读POLLPRI高优先级数据可读POLLOUT有数据可写POLLRDHUP套接字对端关闭,Linux内核2.6.171版本之后POLLWRBAND优先级数据可写POLLERR发生错误POLLHUP发生挂起POLLNVAL文件描述符无效13.6高性能I/O事件驱动epoll概述
为了提高I/O多路复用的性能,Linux内核自2.6起,引入了一种高性能异步I/O事件处理的本地化接口,称为epoll
epoll是对传统I/O多路复用的优化和扩展,无须每次设置和扫描整个被监听的文件,仅需一次性将需监听的被文件描述符注册至内核,内核使用红黑树管理监听的对象,将用户缓存映射至内核空间,提高了数据存取效率,使用链表管理产生的I/O就绪事件。事件触发模式
epoll提供了水平触发和边缘触发两种事件触发模式。1.水平触发模式
只要文件的I/O状态可用,便可产生对应的I/O事件。2.边缘触发模式只有文件的状态与上一次相比发生了改变,才产生相应的I/O事件。创建epoll实例头文件
#include<sys/epoll.h>函数原型
int
epoll_create(intsize);功能 创建epoll实例。参数
size:文件描述符的最大数量。返回值 成功返回rpoll文件描述符,失败返回-1。设置监听对象头文件
#include<sys/epoll.h>函数原型
int
epoll_ctl(int
epfd,int
op,int
fd,struct
epoll_event*event);功能 设置监听对象。参数
epfd:epoll实例。
Op:操作符。
fd:文件描述符。
event:事件。返回值 成功返回0,失败返回-1。参数op定义EPOLL_CTL_ADD向epoll实例添加监听对象EPOLL_CTL_MOD修改epoll实例的监听对象EPOLL_CTL_DEL从epoll实例删除监听对象epoll_ctl含住中参数op的定义I/O事件类型含义EPOLLIN接收到普通数据EPOLLPRI接收到紧急数据EPOLLRDHUP套接字对端关闭,Linux内核2.6.171版本之后EPOLLOUT可以写入数据EPOLLET边缘触发EPOLLLT水平触发,缺省模式EPOLLONESHOT只监听一次事件EPOLLERR当描述符发生错误,默认设置E
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
评论
0/150
提交评论