io多路复用

io多路复用
io多路复用

TEXT:

io多路复用

 

  • 出现场景
    • 一个网络服务器,供多个网络客户端连接,并处理这些连接传上来的请求
    • 假设有一个网络服务器,5个连接,fdA,fdB,fdC,fdD,fdE
  • 实现思路
    • 多线程
      • RPC框架
        • 并不是最优方案
      • cpu线程切换(上下文)消耗资源
    • 单线程
      • 依赖DMA请求不会丢失
      • DMA既可以指内存和外设直接存取数据这种内存访问的计算机技术,又可以指实现该技术的硬件模块
      • 模拟逻辑代码
      • while(true){
      • for(fdx in (fdA~fdE)){
      • if(fdx 有数据){
      • 读取 fdx;
      • 处理 fdx;
      • }
      • }
      • }
        • 如果用c写,有一定效率
        • 但判断是否有数据,依旧是程序判断的,这里效率还是比较低的
  • 单线程实现
    • io多路复用
      • select(198?年的api)
        • 代码解析
          • 准备部分(while上面部分)
            • 定义一个文件描述符的数组fds,下标:0~4;数组存的值是 243,579等值,非0~4并且找到最大值赋值给max
            • while循环;select函数;for循环读取数据,处理数据;
          • select函数
            • select(max+1,&rset,NULL,NULL,NULL);
              • 参数说明
                • max+1:截取有数据段
                • 读文件描述符集合
                • 写文件描述符集合
                • 异常文件描述符集合
                • 超时时间
            • 最关注的是读文件描述符集合
            • &rset:bitmap:1024
              • bitmap存的是哪些文件描述符被启用|监听
            • 运行时,用户态中 &rset全拷贝到内核态,内核中判断rset中是否有数据
            • 如果没有数据到来,select会阻塞,等待
            • 如果有数据来,内核中
              • fd置位
              • select返回
          • for循环处理
            • for循环判断&rset中每个元素是否被置位
              • 如果置位,则读取数据,并处理数据
        • 简言之:select函数做这样一件事,将fds拷贝到内核态,内核进行监听fds,遍历fdx,如果无数据则阻塞,有数据则置位,select返回(可能哟多个置位)。返回后fds再遍历,将有置位的fdx进行读取数据和处理数据处理。提高效率的核心是将fds判断扔到内核中判断。
        • 仍有几个缺点
          • A 默认大小1024,bitmap
          • B fdset不可重用:fdset中fd置位后,被内核修改,每次rset在while(true)时都会重新赋空值,select置位赋值
          • C 用户态→内核态:fds从用户态到内核态的切换,仍有一个开销
          • D O(n):每次select返回后,能确定有返回,但不确定有几个返回,具体位置,需要全遍历执行
      • poll
        • 准备阶段
          • 构造数组
        • poll
          • 核心是构建了一个结构体
          • `struct pollfd{`
          • `int fd;`
          • `short events;`
          • `short revents;`
          • `};`
          • 用户态→内核态
            • 因为结构体的存在,置位是实质置位结构体中的revents=POLLIN;通俗讲没有置位对象,而是置位java对象的某属性。
          • 解决了select中的 A,B问题
        • for循环处理
          • for循环处理中又会revents=0;
      • epoll
        • 准备阶段
          • 构造白板
        • epoll_event结构体
        • `struct epoll_event{`
        • `int fd;`
        • `short events;`
        • `};`
        • 代码组成
          • epoll_create(10)
            • 10可以是其他值,无实质指代意义
          • epol_ctl(...)
          • epoll_wait(...)
            • 用户态与内核态共享一块内存
              • 有数据:置位(重排序),将有数据的时间重排到数组的前面
              • 返回实际有数量的count,3个置位就返回3,一个置位就返回1
              • 时间复杂度O(1)
          • 解决了select中的 C,D问题
  • 抛出问题
    • ssd为啥比机械硬盘快
      • 虽然SSD和HDD都能存储内容,但两者结构完全不一样。HDD内部有马达、碟片、磁头等机械结构,工作时碟片转动,所以HDD工作时会有轻微震动,并且伴有声音。
      • SSD的内部结构更像是U盘,拥有主控、闪存芯片等。由于工作的时候没有机械结构转动或移动,所以SSD工作的时候没有震动,也不会有声音。
      • 两者工作方式不同,机械硬盘是一个旋转的金属磁盘和磁头来存取数据的,它找到数据需要一个寻道时间,而固态硬盘是电子芯片读写是几乎不需要寻道时间的,没有运动部件都是电子芯片时间当然要快得多。
    • DB对ssd有哪些优化
    • 优化原理
      • 基于SSD的数据库优化法则
        • 将sequential logging修改为In-page logging
        • SSD作为写cache-append write
        • SSD作为读cache-flashcache