likes
comments
collection
share

理解五种网络模型和零拷贝的原理

作者站长头像
站长
· 阅读数 11

前置知识:

计算机系统中,应用是没办法直接操纵内存的,应用属于用户态,操纵内存(硬件)需要内核态,也是防止用户态权限过大

理解五种网络模型和零拷贝的原理

所有IO

  • 阻塞IO(Blocking IO)
  • 非阻塞IO(Nonblocking IO)
  • IO多路复用(IO Multiplexing)
  • 信号驱动IO(Signal Driven IO)
  • 异步IO(Asynchronous IO)

阻塞IO(Blocking IO)

理解五种网络模型和零拷贝的原理

应用是无法直接从磁盘上读取数据的,分为两步:

  1. 用户空间等待内核空间从硬件中拿到数据
  2. 再把这个数据写给用户缓存去

这是一个阻塞的过程,两个阶段都要等待

理解五种网络模型和零拷贝的原理

非阻塞IO(Nonblocking IO)

理解五种网络模型和零拷贝的原理

  1. 用户会一直尝试获取数据,因为内核里没有数据
  2. 直到内核台有数据了,再阻塞用户进程,拷贝数据

IO多路复用(IO Multiplexing)

文件描述符(File Descriptor):简称FD,是一个从0 开始的无符号整数,用来关联Linux中的一个文件。在Linux中,一切皆文件,例如常规文件、视频、硬件设备等,当然也包括网络套接字(Socket)。

通过FD,我们的网络模型可以利用一个线程监听多个FD,并在某个FD可读、可写时得到通知,从而避免无效的等待,充分利用CPU资源。

理解五种网络模型和零拷贝的原理

  1. 调用select,指定要监听的FD集合(用户态告诉内核态,这些FD有一个好了就和我说)
  2. 内核态通知,用户态recvfrom读取数据,此时肯定是有数据的

监听的多种方式: select、poll、 epoll

其中select和pool相当于是当被监听的数据准备好之后,他会把你监听的FD整个数据都发给你,你需要到整个FD中去找,哪些是处理好了的,需要通过遍历的方式,所以性能也并不是那么好

而epoll,则相当于内核准备好了之后,他会把准备好的数据,直接发给你,咱们就省去了遍历的动作。

epoll模式中如何解决这些问题的?

  • 基于epoll实例中的红黑树保存要监听的FD,理论上无上限,而且增删改查效率都非常高
  • 每个FD只需要执行一次epoll_ctl添加到红黑树,以后每次epol_wait无需传递任何参数,无需重复拷贝FD到内核空间
  • 利用ep_poll_callback机制来监听FD状态,无需遍历所有FD,因此性能不会随监听的FD数量增多而下降

信号驱动IO

理解五种网络模型和零拷贝的原理

这种相当于 用户态告诉内核态:我要这个的数据,我看你这里没有,搞好了告诉我,我先去搞别的东西。等东西搞好了,内核态通知用户态可以来拿数据了,用户态调用recvfrom(阻塞)并返回数据

异步IO

理解五种网络模型和零拷贝的原理

这一步就是最后数据是由内核态直接传给用户态的

零拷贝

比如我现在要做一个文件传输系统,系统的文件流程大概是这样的:

理解五种网络模型和零拷贝的原理

(DMA是Direct Memory Access 直接访问内存的一个技术)

可以看到文件反复复制,拷贝了4次

进程状态切换了四次

零拷贝:

理解五种网络模型和零拷贝的原理

优化的几个点:

  1. 用户缓冲区和内核态缓冲区共享一个
  2. 内核态直接CPU拷贝到socket缓冲区
  3. mmap() 系统调用函数会直接把内核缓冲区里的数据映射到用户空间,这样,操作系统内核与用户空间就不需要再进行任何的数据拷贝操作。

linux内核提供了一个sendfile函数,又可以优化一些:

理解五种网络模型和零拷贝的原理

所谓零拷贝,我认为就是这一层“用户态和内核态之间”零拷贝吧

详细请看:www.xiaolincoding.com/os/8_networ…

图源:黑马Redis & 小林coding