阻塞和同步

# 浅谈阻塞


  网络IO的阻塞、同步大多都是类比,没有深入到实质。

接收数据包举例

数据包
数据包
网卡
网卡
硬中断
硬中断
DMA方式
DMA方式
软中断
软中断
RingBuffer缓冲区
RingBuffer缓冲区
OSI模型
OSI模型
内核
内核
Socket
Socket
接受缓冲区
接受缓冲区
发送缓冲区
发送缓冲区
应用层
应用层
sk_buffer
sk_buffer
Viewer does not support full SVG 1.1

  1. 数据准备阶段
    数据包到达网卡后,通过DMA方式将数据包拷贝到内存中,然后经过硬中断和软中断,接着通过内核线程ksoftirqd经过内核协议栈的处理,将数据发送到内核Socket的接收缓冲区中。
  2. 数据拷贝阶段
    数据包到达内核空间的Socket接收缓冲区后,需要拷贝到用户空间的内存中,才能够被应用程序读取。

# 阻塞与非阻塞的区别

阻塞与非阻塞的区别就发生在第一阶段,数据准备阶段。当应用程序发起启动系统调用(read),线程开始从用户态转换为内核态, 线程开始读取Socket接收缓冲区中的网络数据。

应用程序
应用程序
DMA方式
DMA方式
数据接收缓冲区
数据接收缓冲区
数据准备阶段
数据准备阶段
数据拷贝阶段
数据拷贝阶段
Socket缓冲区
Socket缓冲区
内核拷贝数据返回
内核拷贝数据返回
没有数据
没有数据
有数据
有数据
经过中断,内核线程发送到缓冲区
经过中断,内核线程发送到缓冲区
1.系统调用read
1.系统调用read
阻塞:等待
阻塞:等待
数据拷贝线程等待
数据拷贝线程等待
非阻塞:直接返回错误
非阻塞:直接返回错误
内核
内核
Viewer does not support full SVG 1.1

阻塞与非阻塞的区别在于,当数据包还没有经过网卡到达RingBuffer缓冲区之前,也就是数据准备阶段,缓冲区没有数据包,阻塞:会一直等待;非阻塞:内核会返回错误标志EWOULDBLOCK。
相同点在于,都会等待第二阶段数据从内核到用户空间拷贝完成后,read调用才会返回。

# 同步与异步的区别


同步与异步的区别在第二阶段,数据拷贝阶段。数据拷贝阶段,主要是将内核空间的数据拷贝到用户空间,然后应用程序才可以读取到数据。

  1. 同步 同步模式是指,用户线程的内核态来执行第二阶段,所以应用程序会在第二阶段发生阻塞,因为此时用户线程在忙碌从内核空间往用户空间搬运数据,直至用户数据拷贝完成, 系统调用才会返回。linux的epoll和mac的kqueue都属于同步IO模型。
  2. 异步 异步IO模型是指内核来完成数据的拷贝操作,当内核执行完第二阶段,会通知用户线程IO操作已经完成,并且将数据回调给用户线程。所以异步依赖内核的支持,也就是底层 操作系统的支持。目前流行的操作系统中,只有windows的IOCP属于真正的异步IO,实现的非常成熟。