IO复习总结

Linux的五种IO模型

  1. 阻塞IO

进程或线程等待某个条件,如果不满足则一直等待,进入阻塞

  1. 非阻塞IO

如果不满足条件则直接返回,然后轮询全部的请求,如果满足条件则读取

  1. 信号驱动IO模型

由于轮询的效率还是不够高,那么则采用信号机制,也就是说采用报警器,如果满足条件则内核让进程去读取

  1. IO复用模型

添加select函数去监听所有的请求,如果哪个成功则直接进行IO读取

  1. 异步IO模型

IO读取由内核自己完成,如果读取完则直接告诉进程读取完成

Java中的IO

  • BIO
  • NIO
    • 原理图
      • channel
        数据通过channel到达buffer,之后从buffer再读取到线程
      • buffer
        作为nio的重要实现,数据不需要像javaIO阻塞读取,而是可以一直被读取,而不影响线程的其它操作
      • 总结分析
        NIO是同步非阻塞IO,由于buffer的实现,那么假如有数据需要读取到线程中,那么可以先读取到channel,再读取到buffer,但是如果数据没有完全读取完,线程在buffer还在不停的被读入数据的同时做其它的操作
    • selector
      nio_selector.jpg
      进一步的非阻塞,线程不会只是一个channel写入数据,单个线程可以利用selector控制多个channel写入数据
  • AIO

NIO的进化版本,同步的io需要线程本身的资源去读取,而非阻塞异步io,数据的读取过程由内核自己完成,当成功读取到线程中后,会有操作系统来提示线程数据读取完成。

IO多路复用

select,poll,epoll都是IO多路复用的机制。I/O多路复用就是通过一种机制,一个进程可以监视多个描述符,一旦某个描述符就绪(一般是读就绪或者写就绪),能够通知程序进行相应的读写操作。

  • select
    • 维护了三个状态数组,分别是
      • fd_set* writefds
      • fd_set* readfds
      • fd_set* exceptfds
    • 通过遍历这三个数组则可以获取到状态
    • 问题: 单个进程可以监控的文件描述符有限,linux上是1024个
  • poll
    • select的进化,三个数组变成一个pollfd链表
      struct pollfd {
          int fd; /* file descriptor */
          short events; /* requested events to watch */
          short revents; /* returned events witnessed */
      };
      
    • 问题: 虽然说取消了1024的限制,但是如果变长,效率还是很差
  • epoll
    • 将改进转移到内核中,将用户关系的文件描述符的事件存放到内核的一个事件表

    • epoll的操作过程

      • int epoll_create(int size);、
        初始化内核中事件表的大小,size参数则是指定的大小,但是并不做限制,只是建议
      • int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);
        • epfd 是 epoll_create()的返回值
        • op 是 add,mod,del (增删改查的操作)
        • fd 监听的文件描述符
        • epoll_event 表示监听的具体什么事件的数组
          struct epoll_event {
              __uint32_t events;  /* Epoll events */
              epoll_data_t data;  /* User data variable */
              };
          
              //events可以是以下几个宏的集合:
              EPOLLIN :表示对应的文件描述符可以读(包括对端SOCKET正常关闭);
              EPOLLOUT:表示对应的文件描述符可以写;
              EPOLLPRI:表示对应的文件描述符有紧急的数据可读(这里应该表示有带外数据到来);
              EPOLLERR:表示对应的文件描述符发生错误;
              EPOLLHUP:表示对应的文件描述符被挂断;
              EPOLLET: 将EPOLL设为边缘触发(Edge Triggered)模式,这是相对于水平触发(Level Triggered)来说的。
              EPOLLONESHOT:只监听一次事件,当监听完这次事件之后,如果还需要继续监听这个socket的话,需要再次把这个socket加入到EPOLL队列里
          
      • int epoll_wait(int epfd, struct epoll_event * events, int maxevents, int timeout);
        epoll_create()返回的内核处理的事件结果
        • epfd 是 epoll_wait的结果
        • events 是内核上处理的事件的集合
        • maxevent就是告诉内核这些事件有多大,小于创建时的size
        • 事件的超时事件
    • epoll的工作方式

      • LT : 可以暂时不处理,等下次再来处理
      • ET :需要立刻处理
    • epoll的全流程总结

    epoll首先需要利用epoll_create()去创建一个句柄,方便直接联系到内核
    之后利用epoll_ctl()去为epoll_create()在内核中空间创建的时间表中,添加文件描述符,或为文件描述符添加,删除或者是修改事件
    注意一个文件描述符可以添加很多的描述的事件
    之后,由于内核中存在事件表,如果事件表发生某种变化,可以利用一种callback的方式回调到epoll中
    这个时候如果调用epoll_wait则可以获取这些状态 (减少了轮询,而是直接通知到epoll)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值