I/O(Input/Output)输入输出,总体图

一.操作系统与设备之间的IO

简单来说(详细的请看《现代操作系统》),操作系统通过设备驱动程序访问IO设备。方式有:

(1)轮询方式:

CPU主动在各种设备中轮询检查状态,有数据就IO。

(2)中断方式:

设备有数据的时候,发出中断,由CPU决定要不要响应中断,然后中断,去处理设备的IO。CPU不用经常轮询设备状态。被动接收中断就行。

(3)DMA直接存储器访问方式:

如果1个字节的数据中断一次,传1KB的数据得中断1024次,太浪费CPU时间,于是有了DMA方式,CPU只需要把开头和结束的地址告诉DMA,中间由DMA完成数据IO。CPU从字节干预解放到数据块的干预。

(4)通道控制方式:

DMA方式只能控制一个设备的一块数据,多块数据还是要CPU干预多次。于是有了通道来控制IO,它比DMA更强大,能控制多块数据,多个设备的IO,更加解放了CPU参与IO过程。

二.操作系统与用户进程间的IO

(进程中的线程才是CPU基本的执行/调度单元,下面用线程举例,用socket举例)

设备来的数据放在内核cache中,需要用户线程去内核cache中取数据,复制到自己进程的cache中。有5中读取数据方式:

(1)阻塞:

用户线程调用某些系统函数去内核取数据,直到数据到达内核cache前,该线程处于阻塞状态,等待数据到达。

(2)非阻塞

用户线程去取数据,不管内核cache有没有数据,都直接返回,可能拿到数据,也可能拿不到,不会使线程进入阻塞态。

(3)IO多路复用

多路就是一个线程管理多路IO,线程还是被阻塞调用,其中一路或几路IO有数据了就返回。需要线程遍历全部IO,判断是哪个IO有数据。

例如 socket 的 select() 函数,线程调用 select() 进入阻塞态,任何一个IO有数据了,线程就退出阻塞态,获得机会继续执行。

(4)信号驱动IO

给一个IO注册一个信号和信号触发的回调函数,一旦信号被触发,回调函数里读取数据。

例如给 socket 注册一个“可读”的信号,当数据来了,可读的时候,信号被触发,执行回调函数从内核cache复制数据到用户空间。

(5)异步IO

异步IO中,操作系统完成了数据从内核到用户空间的拷贝后,以信号的方式通知用户线程可以下一步操作。省去了用户线程阻塞下来拷贝数据的过程。

IO管理

假设一台服务器需要被1万个客户端连接。方法有:

(1)单路:

最简单的一个线程管理一个客户端的socket IO,那么需要1万的线程,假设每个线程占内存3MB,需要300G内存,单台服务器没那么大的内存,并且操作系统最大线程数有限制,unix下一个进程好像是最多只能开 4096 个线程。

(2)IO 多路复用:

socket一旦多起来,单路IO 就扛不住了,需要一个线程管理多个 socket IO,下面都是在一个线程内的情况。

(2.1)select

一个线程管理多个socket IO,调用 select() 进入阻塞态,任何一个IO有数据则返回,由于不知道是哪个 socket 有数据,需要遍历所有 socket fd 去判断,当1万个 socket 大部分都是有IO的时候,效率较高,如果只是那么几百个有IO,此方法效率较低。

(2.2)epoll 和 kqueue

epoll 是 linux 下的,kqueue 是 unix 下的。

由于 select 需要遍历全部的 socket fd,效率较低,于是有了 epoll, kqueue 方式,kqueue 管理多个IO,阻塞调用等待函数,当有一个或多个IO事件,kqueue 直接返回多个IO事件的 socket fd,不需要遍历全部 socket fd,效率较高。

假设一个 socket 连接的对象是 3 kb,8G的内存可以管理 280w 个连接。

select,epoll,kqueue 原理

已知的情况

内核中注册 socket 的 IO 中断处理的回掉函数,有 IO 了会回调该函数。

select:

select 管理多个 socket,select 收到一个来自网卡 IO 中断就返回,不知道这个中断对应是哪个 socket fd 的。需要用户线程遍历判断。

epoll:

epoll 收到一个 IO 中断,会去查找这个中断对应哪个 socket fd。

epoll 中建立一个红黑树(平衡二叉树的一种),红黑树查找很高效。

用户注册感兴趣的 socket 事件,就是把这个 socket fd 插入到红黑树中,用中断号做key,可以理解为(中断号,socket fd)的二元组。

用户移除事件就是,删除树上的某个节点。

然后收到一个IO中断,epoll 把网卡数据拷贝到内核cache,根据中断号在红黑树中查找对应的 fd,把 fd 加入到就绪链表中,准备返回给用户线程。用户直接得到就绪的 fd。

kqueue:

收到 socket IO 中断去哈希表中查找对应的 socket fd,再把它放到一个链表里,返回。

用户注册一个感兴趣的事件,就是往哈希表中添加一个 fd。

一些优化

Memory Map (mmap)

设备的数据到内核cache,再到用户空间,中间需要把内核数据复制到用户空间,比较耗时,那么直接用 mmap 把用户空间的地址映射到内核空间,省去了内核数据到用户空间的拷贝

if((src = mmap(0, statbuf.st_size, PROT_READ, MAP_SHARED, fdin, 0)) == MAP_FAILED) err_sys("mmap error for input");

if((dst = mmap(0, statbuf.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, fout, 0)) == MAP_FAILED) err_sys("mmap error for output");

memcpy(dst, src, statbuf.st_size);

高性能服务器io函数,操作系统中的I/O,及高性能IO模型相关推荐

  1. 在 Exchange 服务器上的操作系统中的防病毒软件

    本主题介绍文件级防病毒程序对运行 Microsoft Exchange Server 2013 的计算机的影响.如果按照本主题中所述的建议操作,可以帮助提高 Exchange 组织的安全性并改善运行状 ...

  2. 图解高性能服务器开发两种模式,第四章 NETTY高性能架构设计

    目录 一.NIO存在问题以及Netty的优点 二.线程模型基本介绍 三.工作原理图(传统同步阻塞式IO) 四.Reactor模式 五.单Reactor单线程 六.单Reactor多线程 七.主从REA ...

  3. Linux 高性能服务器开发笔记:Reactor 模型定时器 | 网络编程定时器

    本文主要根据游双书本 Linux 高性能服务器开发 学习分析 linux 网络编程常用到的定时器模型,配备详细理解和分析,同时分析了 Linux 内核中定时器的低精度时间轮和高精度定时器实现思路还有 ...

  4. 关于高性能服务器底层网络通信模块的设计方法

    高性能服务器底层网络通信模块的设计方法 在对I/O完成端口进行底层封装的基础上,本文提出一种具有高性能的.可扩展性的通用网络通信模块设计方案.该方案采用多种系统性能优化技术,如线程池.对象池和环形缓存 ...

  5. linux操作系统使用论文_Linux高性能服务器设计

    C10K和C10M 计算机领域的很多技术都是需求推动的,上世纪90年代,由于互联网的飞速发展,网络服务器无法支撑快速增长的用户规模.1999年,Dan Kegel提出了著名的C10问题:一台服务器上同 ...

  6. 高性能服务器中的C10K问题

    原文: The C10K problem 本文中文版翻译仅供我自己学习使用,翻译工作并未获得原作者的许可,请不要转载,感谢. ------------------------------------- ...

  7. linux PCB数组,Linux中的系统IO函数

    一.整体大纲 二. 系统IO函数 1. 一些概念 文件描述符 PCB C库函的IO缓冲区 1) 文件描述符 int 类型 一个进程最多可打开多少文件 2) pcb 进程控制块 在其中有一个文件描述符表 ...

  8. 禁用服务器网络协议怎么设置,如何在Windows操作系统中启用和禁用DHCP?

    原标题:如何在Windows操作系统中启用和禁用DHCP? 无论在公共场所还是家中,WiFi可以为您的计算机提供网络连接.我们出行或者参加会议时需要携带计算机.计算机操作系统具有可操作的DHCP,让大 ...

  9. 安装ao 服务器为空,如何在64位Windows操作系统中安装现场审计实施系统AO2011

    龚泽平 [摘 要]对于医院审计.医保审计等各种需要消耗大量内存的审计工作来讲,64位系统具有更加明显的优势.但是当前国家审计署所研发的现场审计实施系统是基于32为系统的,在一定程度上让计算机软硬件都发 ...

最新文章

  1. C/C++中constkeyword
  2. docker 无法正常启动 解决方法
  3. asp.net和javascript怎样结合
  4. 待处理,待学习(每日更新)
  5. ERROR 1366 (HY000): Incorrect string value......(Mysql报错解决)
  6. Request.ServerVariables 参数大全
  7. oracle 快照用途,Oracle快照原理及实现总结
  8. 无线网络受限制或无连接处理方法
  9. android插件化之路
  10. express捕获全局异常的三种方法
  11. require.js的AMD规范详解
  12. VRTK之手柄事件监听以及重写StartUsing方法实现与物体的交互
  13. SPSS可以生成正交表吗?
  14. mysql reads sql data_在其声明中使用DETERMINISTIC,NO SQL或READS SQL DATA并启用二进制日志记录...
  15. 华为让全球震惊:5G基站出货已过万
  16. CentOS 7 最小化系统安装图形化桌面
  17. Excel规划求解Solver:三种方法的区别
  18. Vue 滚动事件穿透解决方案
  19. 软件功能以图找图自动点击鼠标 发现一款非常好用的以图视图自动操作软件AI万控系统和大家分享一下全名叫“AI人工智能万控系统”
  20. R画图中英文字体完美解决方案

热门文章

  1. Oracle登陆SQL Plus,Oracle基础学习登陆SQLPLUS(一)
  2. eclipse远程调试tomcat
  3. Vue ---- 指令
  4. 输出100以内所有的质数
  5. umi3 如何管理model_umi -- model 的注册与使用
  6. python怎么打开程序管理器_python进程管理工具supervisor的安装与使用教程
  7. 支付接口调用成功后如何让前端知道_开发口中的「接口」到底是什么
  8. sql server2012 第一次访问慢_【共同学习】第1章 数据库和SQL (续)
  9. 计算机共享文件怎样添加,怎么添加另一台电脑的共享文件夹
  10. Apollo添加部门