# 技术背景

### 传统内核网络协议栈面临的问题

在操作系统的设计中，内核通过硬件抽象和硬件隔离的方法，给上层应用程序的开发带来了简便性，但也导致了一些性能下降。在网络方面，主要体现在整体吞吐率的减小和报文延迟的增加上。 主要性能缺陷包括以下几点：

#### 网卡中断

轮询与中断时操作系统与硬件设备进行I/O通信的两种主要方式。在一般情况下，网络数据包的到来都是不可预测的，若采用轮询方式则会造成很高的CPU负载，因此主流操作系统都会采用中断的方式来处理网络的请求。

然而，随着高速网络接口等技术的迅速发展，10Gbit/s，40Gbit/s，甚至100Gbit/s的网络接口已经出现。随着网络I/O速率的不断提升，网卡面对大量的高速数据分组将会引发频繁的中断，每一次的中断都会引起一次上下文切换，操作系统都需要保存和恢复相应的上下文，造成较高的时延，并引起吞吐量下降。

#### 内存拷贝

为了使位于用户空间的应用程序能够处理网络数据，内核首先需要将收到的网络数据从内核空间拷贝到用户空间，同样，为了发送网络数据，也需要进行从用户空间到内核空间的数据拷贝。每次拷贝都会占用大量的CPU，内存带宽等资源，代价昂贵。

#### 锁

在Linux内核的网络协议栈实现中，存在大量的共享资源的访问。当多个进程需要对某一共享资源进行操作时，就需要通过锁的机制来保证数据的一致。然而，为共享资源上锁或者去锁的过程通常需要几十纳秒。此外，锁的存在也降低了整个操作系统的并发性能。

#### 缓存未命中

缓存能够有效提高系统性能，如果因不合理的设计而造成频繁的缓存未命中，会严重削弱数据平面的性能。在缓存命中与不命中的情况下，数据操作耗时相差数倍。如果系统设计时忽略这一点，存在频繁的跨核调用，由此带来的缓存未命中会造成严重的数据读写时延，从而降低系统的整体性能。