select,poll,epoll

简单概述

select,poll,epoll都是用来实现IO多路复用的机制,在Linux网络模型中对应着IO复用模型Unix上的IO模型

select:最大支持1024个文件描述符,在描述符较多情况下性能较差,水平触发
poll:poll与select基本相同,只是没有文件描述符的限制,水平触发
epoll:文件描述符为系统上限,在描述符较多情况下性能较好,同时支持水平与边缘触发

水平触发与边缘触发

水平触发:只要文件描述符关联的读内核缓冲区非空,有数据可以读取,就一直发出可读信号进行通知,当文件描述符关联的内核写缓冲区不满,有空间可以写入,就一直发出可写信号进行通知,如果系统中有大量不需要读写的就绪文件描述符,而它们每次都会返回,这样会大大降低处理程序检索自己关心的就绪文件描述符的效率

边缘触发:当文件描述符关联的读内核缓冲区由空转化为非空的时候,则发出可读信号进行通知,当文件描述符关联的内核写缓冲区由满转化为不满的时候,则发出可写信号进行通知。如果这次没有把数据全部读写完(如读写缓冲区太小),它不会再次通知你,直到该文件描述符上出现第二次可读写事件才会通知你,这种模式比水平触发效率高,系统不会充斥大量不关心的就绪文件描述符

使用Linux epoll模型的水平触发模式,当socket可写时,会不停的触发socket可写的事件,如何处理?当需要向socket写数据时,将该socket加入到epoll等待可写事件。接收到socket可写事件后,调用write或send发送数据,当数据全部写完后, 将socket描述符移出epoll列表,这种做法需要反复添加和删除。边缘模式就可以直接搞定,并不需要用户层程序的补丁操作。

select

Linux将进程分类为两个队列,阻塞队列和工作队列。网络应用程序调用linux read读取数据时,如果没有数据就一直阻塞。假设当进程执行到read时,A进程就从工作队列中移到该socket的等待队列中,A进程就被阻塞。阻塞期间,如果来数据了,中断处理就会将数据装入接收队列,然后唤醒A进程,移动到工作队列中。

read阻塞原理:进程分为“运行”和“等待”等几种状态。当进程 A 执行到创建 socket 的语句时,操作系统会创建一个由文件系统管理的 socket 对象。这个 socket 对象包含了发送缓冲区、接收缓冲区与等待队列等成员。当程序执行到 read 时,操作系统会将进程 A 从工作队列移动到该 socket 的等待队列中,那么进程A就不会被执行,也不会占用 CPU 资源。当 socket 接收到数据后,操作系统将该 socket 等待队列上的进程重新放回到工作队列,该进程变成运行状态

如何从阻塞队列移到工作队列:网卡将数据写入内存后,网卡产生一个中断,处理器立即停止它正在做的事,然后跳转到内存中预定义的中断程序开始执行。

但是每个read方法只能监控一个socket,select的原理就是使用一个数据存放socket,如果数组(代码中写死了数组长度为1024)中的所有socket都没有数据,进程就被挂起,直到有socket收到数据,唤醒进程。

假如程序同时监视如下图的 sock1、sock2 和 sock3 三个 socket,那么在调用 select 之后,操作系统把进程 A 分别加入这三个 socket 的等待队列中。

当任何一个 socket 收到数据后,中断程序将唤起进程,所谓唤起进程,就是将进程从所有的等待队列中移除,加入到工作队列里面

当进程 A 被唤醒后,它知道至少有一个 socket 接收了数据。程序只需遍历一遍 socket 列表,就可以得到就绪的 socket。

缺点:每次调用select都需要将进程加入到所有要监控的socket的等待队列中,每次唤醒都要从所有的队列中移除;被唤醒后,进程并不知道哪些socket有数据,需要遍历。

epoll

epoll将等待队列和阻塞进程分开了,使用epoll_ctl维护等待队列,使用epoll_wait阻塞进程,epoll内部维护了一个就绪队列,收到数据的socket直接加入就绪队列,当 epoll 监听的 socket 状态发生改变(变为可读或可写)时,就会把就绪的 socket 添加到就绪队列中,当进程被唤醒,只要获取就绪队列就能知道哪些socket收到数据了。epoll内部使用红黑树保存所有监听的socket,添加和查找元素的时间复杂度为 O(log n)

当某个进程调用 epoll_create 方法时,内核会创建一个 eventpoll 对象。eventpoll 对象也是文件系统中的一员,和 socket 一样,它也会有等待队列。

rdllist: 保存已经就绪的文件列表。
rbr: 使用红黑树来管理所有被监听的文件。红黑树节点是epitem

创建 epoll 对象后,可以用 epoll_ctl 添加或删除所要监听的 socket。以添加 socket 为例,如果通过 epoll_ctl 添加 sock1、sock2 和 sock3 的监视,内核会将 eventpoll 添加到这三个 socket 的等待队列中。

当 socket 收到数据后,中断程序会给 eventpoll 的“就绪列表”添加 socket 引用。如下图展示的是 sock2 和 sock3 收到数据后,中断程序让 rdlist 引用这两个 socket。

eventpoll 对象相当于 socket 和进程之间的中介,socket 的数据接收并不直接影响进程,而是通过改变 eventpoll 的就绪列表来改变进程状态。

当 socket 接收到数据,中断程序一方面修改 rdlist,另一方面唤醒 eventpoll 等待队列中的进程,进程 A 再次进入运行状态(如下图)。也因为 rdlist 的存在,进程 A 可以知道哪些 socket 发生了变化。

Java中select BUG

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

推荐阅读更多精彩内容