再讲io模型之前,给大家举一个钓鱼的例子。
张三去钓鱼,他钓鱼的时候一动不动,一直看着鱼竿,看有没有动,无论是谁叫他,他都不动,只有等鱼梢动了(鱼上钩了),他才会动
李四去钓鱼,他没有像张三那样瓷楞着,只是时不时的轮询检查鱼竿有没有动。一直在动。
王五也来钓鱼,他就比较聪明了,在鱼竿上挂个铃铛,只要铃铛响了,就代表鱼上钩了,否则他就干自己的事,不用去检查鱼竿有没有动,因为铃铛会提醒他
这时,土豪的赵六也来了,他带了100个鱼竿,叫了一群人,把鱼竿放到水里,只要鱼上钩了 ,就把它钓上来,这样,鱼上钩的几率就会变大
田七也来钓鱼了,刚打算钓的时候,突然接到电话说公司有事要回去处理,然后田七就让司机帮忙钓,最后钓到的鱼还是属于田七的。
通过上边五个人钓鱼的例子,我们依次介绍五种io模型
io = 等(等鱼上钩) 数据拷贝(把鱼竿拉起)
- 阻塞io
- 在内核将数据准备好之前,系统调用会一直等待,所有套接字,默认都是阻塞方式。(张三一动不动钓鱼)
- 阻塞io是最常见的io模型
- 非阻塞io
-
如果内核还未把数据准备好,系统调用仍然会直接返回,并且返回ewouldblock错误码。(李四轮询检查鱼竿有没有动)
-
非阻塞io往往需要程序员循环的方式反复尝试读写文件描述符, 这个过程称为轮询. 这对cpu来说是较大的浪费, 一 般只有特定场景下才使用.
- 信号驱动
- 内核将数据准备好的时候,使用sigio信号通知应用程序进行io操作。(王五在鱼竿上挂了一个铃铛)
- io多路转接(important!!!)
- 虽然从流程图上看和阻塞io类似,实际最核心在与io多路转接能够同时等待多个文件描述符的就绪状态。(土豪赵六拿100个鱼竿钓鱼)
- 异步io
- 由内核在数据拷贝完成时,通知应用程序(而信号驱动是告诉应用程序开始拷贝数据)(田七让司机帮钓)
- 小结
- 任何io过程中,都包含两个步骤:等 数据拷贝。而在实际的应用场景中,等待小号的时间大于拷贝的时间
- 让io高效的核心办法就是让等待时间减小。
- 阻塞io和非阻塞io的区别?(前者一直等待,后者轮询完返回)