IO过程

发起IO调用,等待IO条件就绪,将数据拷贝到缓冲区中进行处理。
等待+数据拷贝 两个主要的操作

五种IO模型

  • 阻塞IO:发起IO调用,不具备IO条件,则一直阻塞等待,操作是顺序执行。
  • 非阻塞IO:发起IO调用,不具备IO条件,则立即返回,操作需要循环调用。
  • 信号驱动IO:定义一个IO就绪信号,收到信号则立即发送IO调用,操作不是顺序进行。
  • 异步IO:定义IO完成信号,发起异步IO调用,IO由系统完成。
  • 多路转接IO:对大量描述符集中事件监控,让进车可以只针对就绪的描述符进行操作,提高了效率,避免对未就绪的操作符进行操作,导致阻塞。

阻塞IO

为了完成某个功能,发起IO调用如果当前不具备IO条件,则一直等待。

优点:流程非常简单
缺点:一个IO完成以后,才能执行下一个IO,资源没有充分利用,大量的时间在等待。

非阻塞IO

为了完成一个IO,发起调用,如果当前不具备IO条件,则立即返回,但是需要循环发起IO。

优点:流程相对复杂一点,对资源的利用更加充分。
缺点:IO操作不够实时。

信号驱动IO

定义一个IO信号处理方式,在处理方式中进行IO操作,IO就绪时信号通知进程,进程在IO就绪的时候去进行IO操作。


优点:IO操作更加实时,对资源的利用更加高效。
缺点:操作复杂。

异步IO

例如:排队买票的例子。
假期出去游玩的人比较多,因此异步IO的操作,就类似于,你让别人帮你排队,并且帮你把票买了,最终将票给你就可以了。
因此异步IO的本质就是,其所有的IO操作都是让别人帮忙完成,自身只是发起一个调用,告诉别人需要从哪里开始拷贝数据,以及拷贝多少数据即可。IO的等待与操作都是由别人完成。

优点:对资源利用更加充分
缺点:流程更加负责

同步与互斥

同步

这里的同步与之前进程中的同步不同,这里的同步指的是处理流程中,顺序处理,一个完成之后再完成下一个,并且所有的功能都是由进程自身完成的。

异步
处理流程顺序不定,主要的功能都是由别人完成或者由操作系统完成。

  • 异步阻塞:功能是由别人完成,但是在调用的时候是等着别人完成。
  • 异步非阻塞:功能由别人完成,调用之后立即返回,不用等待。

高级IO中的同步与互斥的主要区别:

判断主要的功能是不是自己完成的,完成的顺序是否确定。

多路转接IO

对大量的描述符进行IO事件监控,可以告诉我们,当前有哪些描述符已经就绪了哪些事件,进程就可以针对就绪了指定事件的进程进行响应操作,避免了对没有就绪的描述符进行操作导致的效率降低。

IO事件
可读事件、可写事件、异常事件

多路转接IO模型:

  • 作用:用于对描述符事件进行监控的。
  • 实现方式:select、poll、epoll

select模型

操作流程:

  • 定义某个事件的描述符集合 (可读、可写、异常事件集合),初始化集合。
  • 对哪个描述符关心,就把这个描述符添加到指定的相应事件中。
  • 将集合拷贝到内核中进行监控。监控的原理是轮询监控。(轮询遍历判断)
    可读事件的就绪:接收缓冲区中的数据大小大于低水位标记,通常默认为一个字节。
    可写事件的就绪:发送缓冲区中剩余空间的大小大于低水位标记,通常默认为一个字节。
    异常事件的就绪:描述符是否产生了某个异常。
  • 监控调用的返回,表示监控出错、描述符已经就绪、监控超时。在调用返回的时候,将事件监控的描述符集合中的未就绪的描述符从集合中移除,在集合中仅仅保留就绪的描述符。
  • 轮询判断哪个描述符处于哪个集合中,就确定这个描述符是否就绪了某个事件,然后进行对应事件的操作。(如果一个描述符处于可读集合中,表述当前描述符已经满足可读事件,然后进行具体的操作)

注意

在select中,并不会直接返回给用户就绪的描述符进行操作,而是返回的就绪描述符的集合,因此需要我们自己进行判断。
因为,select在返回的时候,将没有就绪的描述符已经移除,因此在下次监控的时候,就需要重新向集合中添加描述符。

代码操作:

  1. 定义集合(struct fd_set),该成员只有一个数组,在该数组中是以二进制比特位进行使用的,添加描述符的就是将对应的二进制比特位置一。默认大小为1024个描述符。
  2. 初始化清空集合:void FD_ZERO(fd_set *set)
  3. 添加描述符到指定集合中。void FD_SET(int fd,fd_set* set),将fd描述符添加到set集合中。
  4. 开发发起监控调用。
    int select(int nfds,fd_set * readfds,fd_set* writefds,fd_set *exceptfds,struct timeval *timeout);
  • nfds:当前监控集合中最大的描述符+1。因为集合默认监控的描述符大小为1024个,避免遍历没用的描述符,减少遍历的次数。
  • readfds:可读事件描述符集合,如果不需要则置空。
  • writedfs:可写事件描述符集合,如果不需要则置空。
  • exceptfds:异常事件描述符集合,如果不需要则置空。
  • timeout:时间结构体,通过时间决定select阻塞、非阻塞、限制超时的阻塞,如果timeout为空,则表示阻塞监控,直到有描述符就绪或者监控出错才会返回。 如果timeout中的成员数据为0,则表示非阻塞,监控的时候如果没有描述符就绪,则会立即超时返回。如果timeout中的成员数据不为0,则在指定的时间之内,没有就绪则超时返回。
    返回值:返回值大于0,表示就绪描述符个数;返回值如果为0,表示没有描述符就绪,超时返回;返回值小于0,表示监控出错。
  1. 调用返回,返回就绪的描述符,遍历判断哪个描述符还在集合中,就是哪个事件已经就绪。
    int FD_ISSET(int fd,fd_set *set),判断fd描述符是否在集合中。本质就是对二进制比特位查看的封装。

  2. 如果对描述符不进行监控,则移除描述符。
    void FD_CLR(int fd,fd_set* set)在set集合中删除fd描述符

int main()
{fd_set redfs;while(1){cout<<"开始监控"<<endl;struct timeval tv;tv.tv_sec = 3;tv.tv_usec = 0;FD_ZERO(&redfs)FD_SET(0,&redfs); //将0号标准输入描述符添加到集合中int res = select(1,redfs,NULL,NULL,&tv); if(res<0){perror("select error")return -1;}else if(res == 0){cout<<"监控超时"<<endl;continue;}if(FD_ISSET(0,&redfs)){cout<<"监控成功,0号事件已经响应"<<endl;}}
}

优缺点:

  • 跨平台移植性比较好。
  • select对描述符的监控由最大数量上限。FD_SETSIZE 。
  • 在内核中进行监控数通过轮询遍历实现的,因此性能会随着描述符的增多而下降。
  • 只能返回就绪的集合,需要进程进行轮询判断才能知道哪个描述符就绪了哪个事件。
  • 每次监控都需要将描述符添加到集合中,每次监控都需要将集合拷贝到内核中。

poll模型

操作流程:

  • 定义监控的描述符时间的结构体数组,将需要监控的描述符以及事件标识信息,添加到数组的各个节点中。
  • 发起调用开始监控,将监控事件的描述符结构体数组,拷贝到内核中进行轮询遍历判断,如果有就绪/等待超时则调用返回,并且在每个描述符对应的事件结构体中,标识当前就绪的事件。
  • 进程轮询遍历数组,判断数组中的每个节点中的就绪事件是哪个事件,再决定对描述符如何进行操作。

接口:

  • int poll (struct pollfd* arry,nfds_t nfds,int timeout)
    监控采用事件结构体。
    struct pollfd {int fd; shor events; shor revents}
    fd要监控的描述符、events要监控的事件(POLLIN可读事件、POLLOUT可写事件)、revents哪个监控事件就绪了就将其放在其中。
    nfds:数组中有效节点的个数
    timeout:监控的超时等待时间:毫秒
    返回值:>0表示监控的就绪事件的个数;返回值==0表示等待超时,返回值<0监控出错。

优缺点:

  • 使用事件结构体进行监控,简化了select中三种事件集合的操作流程。
  • 监控数量不做限制。
  • 不需要每次重新定义事件节点。
  • 跨平台移植性差。
  • 每次监控依然需要向内核中拷贝数据。
  • 在内核中监控,依然采用轮询遍历。

epoll模型

操作流程:

  • 在内核中创建epoll句柄(epollevent结构体。红黑树+双向链表)
  • 对内核中的epollevent结构添加、删除、修改
  • 开始监控,发起调用,在内核中采用异步阻塞实现监控,等待超时或者描述符就绪了事件后调用返回,返回给用户就绪描述符事件的结构信息。
  • 进行直接对就绪的事件结构体中的描述符成员进行操作即可

接口信息:

  • int epoll_create(int size)创建epoll句柄,size只要大于0即可。
    返回值:一个文件描述符,
  • int epoll_ctl(int epfd,int cmd,int fd,struct epoll_event* ev)
    epfd:epoll_create返回的操作句柄
    cmd:针对fd描述符的监控信息进行操作,添加/删除/修改操作。EPOLL_CTL_ADD /EPOLL_CTL_DEL / EPOLL_CTL_MOD
    fd:要监控的描述符
    ev:描述符对应的事件结构体信息。当epoll开始监控的时候,描述符如果就绪了进程关心的事件,则会给用户返回我们添加对应事件结构体信息,通过事件结构体信息中包含的描述符进行操作,所以fd与ev结构体中的fd是同一个描述符。
  • int epoll_wait(int epfd,struct epoll_events *evs,int max_event,int timeout)
    epfd:epoll操作句柄
    evs:struct epoll_events结构体数组的首地址,用于接受就绪的描述符对应的事件结构体信息。
    max_event:本次监控想要获取就绪事件的最大数量,不能大于evs数组大小。
    timeout:超时等待时间,单位毫秒。
    返回值:>0表示就绪事件的个数 =0表示等待超时,<0监控出错

监控原理

异步阻塞操作。
监控由系统完成,用户添加监控的描述符以及对应事件结构体会被添加到内核的eventpoll结构体中的红黑树中,一旦进程发起调用,操作系统为每个描述符的事件进行回调。当描述符就绪了哪个事件,则将描述符对应的事件结构体添加到双向链表中。
进程自身,每隔一段事件,判断双向链表是否为NULL,决定是否有事件就绪。

Linux---高级IO相关推荐

  1. linux 高级IO函数之fcntl mmap/munmap

    fcntl函数提供了对文件描述符的各种控制操作.另外一个常见的控制文件描述符属性和行为的系统调用是ioctl,而且ioctl比fcntl能够执行更多的控制.但是对于控制文件描述符常用的属性和行为,fc ...

  2. linux 高级IO函数之sendfile splice tee

    sendfile函数在两个文件描述符之间传递数据(完全在内核中操作),从而避免内核缓冲区和用户缓冲区之间的数据拷贝,效率很高,这被称为零拷贝.函数的定义如下: #include<sys/send ...

  3. Linux之高级IO

    目录 一.五种IO模型 以网络为例 什么叫做IO? 什么叫做高效的IO呢? 为什么第二个大爷的效率很高呢? 五种IO模型 感性认识 这五个人,在钓鱼的时候,谁的效率是最高的? 阻塞IO 非阻塞IO 信 ...

  4. 【Linux练习生】高级IO

    本文收录于专栏:Linux 关注作者,持续阅读作者的文章,学习更多知识! https://blog.csdn.net/weixin_53306029?spm=1001.2014.3001.5343 高 ...

  5. Linux文件IO深入剖析

    文章目录 1 linux文件系统基本概念 1.1 文件系统基本概念 1.2 文件系统缓存 2 文件IO访问方式概述 2.1 标准文件IO 2.2 直接IO 2.3 缓存同步 1 linux文件系统基本 ...

  6. Linux 文件 IO

    参考:http://blog.csdn.net/wanxiao009/article/details/5648583 C 和 C++ 文件操作详解:http://blog.csdn.net/freek ...

  7. linux系统IO操作

    本文重点说明下面内容: 什么是标准IO,什么是文件IO? 什么是Direct IO? O_SYNC标识有什么意义? 各个层面的缓存如何同步? 还在page cache中的脏页可以读写吗? IO路径上的 ...

  8. 转:Linux网络IO并行化技术概览

    转:http://codinginet.com/articles/view/201605-linux_net_parallel?simple=1&from=timeline&isapp ...

  9. Linux内核IO追踪:用GDB调试,一个磁盘IO的流程是什么样的

    Table of Contents 构建内核 产生IO写入的程序 追踪到兔子洞 准备步骤 进入FS层:我正在使用的fs是XFS 潜入块层 进入块驱动程序层:我的块驱动程序是SCSI 回到fs层,研究内 ...

  10. 《Kali Linux高级渗透测试原书第2版》网络渗透测试技术书 无线网络渗透测试详解 黑客攻击与防范实战从入门到精通书

    内容简介: KaliLinux面向专业的渗透测试和审计,集成了大量挑选的检测工具.本书在KaliLinux平台上从一个攻击者的角度来审视网络框架,详细介绍了攻击者"杀链"采取的具体 ...

最新文章

  1. html实时显示log,websocketd 实现浏览器查看服务器实时日志
  2. Qt 控制watchdog app hacking
  3. --7、学期表(表)
  4. java 静态方法覆盖_Java中方法的覆盖和静态方法的隐藏
  5. yuv420,yuv420p,yuv420sp,nv12,nv21,I420,YV12概念区别
  6. 计算机ftp无法找到启动路径,filezilla出现路径错误导致无法启动怎么办?filezilla无法启动的解决方法...
  7. 一文讲懂什么是三层交换机、网关、DNS、子网掩码、MAC地址
  8. Hadoop之HDFS概述
  9. 几种C++ std::string和std::wstring相互转换的转换方法
  10. linux 查看历史打印,2019-02-01 Linux查看用户/历史命令
  11. 如何用python新建文件夹_用Python编写一个每天都在系统下新建一个文件夹的脚本...
  12. MFC之CString与const char* string 转换
  13. Flex实现双轴条状图
  14. 自学python买什么教材-学习Python的正确姿势—基础教学,教科书该怎么买?
  15. cpp调用python_从python ctypes调用CPP函数
  16. iocomp入门教程-以MFC中iplotx为例
  17. 空间数据格式转换之MapInfo mid/mif文件转ArcGIS shpfile文件
  18. Spring学习—Spring中定时器实现
  19. html a 标签 邮件超链接 发送邮件
  20. java中美元符号的作用_$美元符号在配置文件中的意义

热门文章

  1. laravel 方法摘要
  2. YAML文件结构简介
  3. (寒假集训)Mooo Moo (完全背包)
  4. 手把手教你制作easyUI+bootstrap工作站,主要学习tabs方法
  5. jquery获取父级元素和子级元素
  6. MySQL 5.7原生JSON格式支持
  7. 开源-一步步实现cnblogs博客采集工具-实现过滤设置对话框
  8. ASP.NET MVC 1.0 + spring.net 1.2.0.20288 + NHibernate 2.0.1.4000整合笔记(四)——整合asp.net mvc...
  9. openHEVC在Windows下构建vs32/64位工程(vs2013)
  10. json替换table下的所有值_京东云所有地域正式支持 MySQL 8.0!