Loading

网络IO基础知识

网络 IO

  • 在套接字接口的抽象下,网络 I/O 的本质其实是 Socket 的读取
  • Socket 在操作系统接口中被抽象为了数据流,而网络 I/O 就可以理解为是对流的操作

过程:两阶段

  • 等待数据从远程主机到达缓冲区:从远程主机返回的数据会先存放到操作系统内核的缓冲区中
  • 将数据从缓冲区拷贝到应用程序地址空间:从内核的缓冲区,复制到应用程序的地址空间

两类、五种模型

  • 同步:指调用端发出请求之后,在得到结果之前必须一直等待
  • 异步:在发出调用请求之后将立即返回,不会马上得到处理结果,这个结果将通过状态变化和回调通知给调用者

以“你如何领到盒饭”这个情景类比

  • 等待数据从远程主机到达缓冲区 : 等待饭做好
  • 将数据从缓冲区拷贝到应用程序地址空间:将饭带回宿舍
img

异步 I/O(Asynchronous I/O)

你在某团外卖订了个盒饭,付款之后你自己该干嘛还干嘛去,饭做好了骑手自然会到门口打电话通知你

  • 数据到达缓冲区后,不需要由调用进程主动进行从缓冲区复制数据的操作,而是在复制完成后,由操作系统向线程发送信号,所以它一定是非阻塞

同步 I/O(Synchronous I/O)

有一个主动等待发现饭是否做好的过程,需要自己取饭

阻塞 I/O(Blocking I/O)

你去到饭堂,发现饭还没做好,你也干不了别的,只能打个瞌睡(线程休眠),直到饭做好

  • 缓冲区没有数据,线程就休眠等待,直到有数据
    • 优点:节省 CPU 资源
    • 缺点:线程休眠所带来的上下文切换,是一种需要切换到内核态的重负载操作

非阻塞 I/O(Non-Blocking I/O)

你去到饭堂,发现饭还没做好,你就回去了,然后每隔 3 分钟来一次饭堂看饭做好了没,直到饭做好

  • 缓冲区没有数据,不休眠,每隔一段时间就来查看是否有数据
    • 优点:避免线程休眠,对于一些很快就能返回结果的请求,非阻塞 I/O 可以节省上下文切换的消耗
    • 缺点:对于较长时间才能返回的请求,非阻塞 I/O 反而白白浪费了 CPU 资源

多路复用 I/O(Multiplexing I/O)

你是活雷锋,代表整个宿舍去饭堂打饭,去到饭堂,发现饭还没做好,还是继续打瞌睡,不过哪个舍友的饭好了,你就马上把那份饭送回去,然后继续打着瞌睡哼着歌等待其他的饭做好

  • 一个线程处理多个调用的返回。有selectepollkqueue 等不同实现
    • 优点:可以在同一条阻塞线程上处理多个不同端口的监听,CPU资源得到充分利用,且不需要挂起线程

信号驱动 I/O(Signal-Driven I/O)

你去到饭堂,发现饭还没做好,但你跟厨师熟,跟他说饭做好了叫你,然后回去该干嘛干嘛,等收到厨师通知后,你把饭从饭堂拿回宿舍

  • 当缓冲区一旦有数据,就主动通知线程去缓冲区复制数据到应用程序地址空间

信号驱动 I/O与异步 I/O 的区别

  • “从缓冲区获取数据”这个步骤处理,前者收到的通知是可以开始进行复制操作了,也就是你要自己把饭从饭堂拿回宿舍,在复制完成之前线程处于阻塞状态,所以它仍属于同步 I/O 操作;而后者收到的通知是复制操作已经完成,即外卖小哥已经把饭送到了。
  • 信号驱动I/O是由内核通知应用程序何时开始一个I/O操作,I/O操作的执行者还是应用程序自身。而异步I/O模型是由内核通知应用程序I/O操作已经完成,I/O操作执行者是内核。

小结:

  • 异步 I/O 模型是最方便
  • Windows NT 内核早在 3.5 以后,就通过IOCP实现了真正的异步 I/O 模型
  • Linux 系统下,是在 Linux Kernel 2.6 才首次引入,目前也还并不完善,因此在 Linux 下实现高并发网络编程时,仍然是以多路复用 I/O 模型模式为主

参考:

posted @ 2022-01-07 16:42  FynnWang  阅读(145)  评论(0编辑  收藏  举报