操作系统中的I/O,及高性能IO模型

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);

参考文献:
使用 kqueue 在 FreeBSD 上开发高性能应用服务器
epoll 底层实现源码分析
Kqueue: A generic and scalable event notification facility
FreeBSD Kqueue的实现原理
操作系统-IO系统
操作系统-IO模型

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,590评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 86,808评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,151评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,779评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,773评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,656评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,022评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,678评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,038评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,659评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,756评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,411评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,005评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,973评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,053评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,495评论 2 343

推荐阅读更多精彩内容