网络IO基础—read/write系统调用

885 阅读3分钟

众所周知,在传统网络IO编程中应用程序会调用read/write系统调用进行读写操作

read/write系统调用读写数据的具体过程?

read系统调用读取数据的过程

UML 图.jpg

read系统调用结果:内核缓冲区数据拷贝到用户缓冲区

详细说明:

  1. 应用程序执行read系统调用,用户态切换到内核态

  2. 内核检查内核缓冲区有无数据可读

    1. 若无,即缓冲区空了,则等待数据从网络中到达(会阻塞);当数据从网络中到达时,数据会拷贝到内核缓冲区
  3. 内核缓冲区有数据可读,CPU会将内核缓冲区数据拷贝到用户缓冲区中

    是CPU拷贝,CPU负责“数据搬运”

  4. 数据拷贝完毕,则read系统调用返回,内核态切换到用户态

write系统调用写入数据的过程

UML 图 (1).jpg

write系统调用结果:用户缓冲区数据拷贝到内核缓冲区

说明:

  1. 应用程序执行write系统调用,用户态切换到内核态

  2. 内核检查内核缓冲区是否有空间可写

    1. 若不可写,即缓冲区满了,则等待网卡将缓冲区中数据发送出去,此时会阻塞直到缓冲区有空间可写
  3. 内核缓存区有空间可写,则CPU将用户空间数据拷贝到内核空间

    CPU拷贝,CPU负责“数据搬运”

  4. 若用户空间数据拷贝完毕(即全部拷贝到内核空间),则write系统调用返回,内核态切换到用户态

为什么read/write系统调用会阻塞?

为什么read读会阻塞

因为读的时候是从内核缓冲区读取数据的,当内核缓冲区空了就没数据可读,此时会阻塞直到内核缓冲区又有数据可读

为什么write写会阻塞

因为写的时候是将用户缓冲区数据拷贝到内核缓冲区,即向内核缓冲区写,当内核缓冲区满了就无空间可写了,此时会阻塞直到内核缓冲区腾出空间可写

总结

关键:

  1. 读写都有缓冲区,读写本质上是个生产者消费者模式

    1. 读时:

      1. 网卡是生产者,产生数据到内核缓冲区
      2. 应用程序是消费者,将内核缓冲区数据拷贝到用户缓冲区

      应用程序消费速度快(因为内存拷贝数据速度快),当缓冲区空了就不可消费导致阻塞

    2. 写时:

      1. 应用程序是生产者,将数据从用户缓冲区拷贝到内核缓冲区
      2. 网卡是消费者,消费内核缓冲区数据、发送到网络中

      应用程序生产速度快(因为内存拷贝数据速度快),当内核缓冲区满了就不可生产导致阻塞