假设我想避免linux内核处理传入数据包的开销,而是想直接从用户空间获取数据包。我在谷歌上搜索了一下,似乎所有需要发生的事情就是使用带有某些套接字选项的原始套接字。是这样吗还是比这更复杂?如果是这样,我可以在Google上搜索或引用什么以实现类似的功能?
最佳答案
有许多通过内核旁路进行联网的技术。
首先,如果要将消息发送到同一台计算机上的另一个进程,则可以通过共享内存区域来执行此操作,而不会跳转到内核中。
在不涉及内核的情况下通过网络传递数据包变得更加有趣,并且涉及可直接访问用户内存的专用硬件。这个想法称为RDMA。
这是它可以工作的一种方式(这是InfiniBand硬件的功能)。该应用程序向RDMA硬件注册了一个内存缓冲区。此缓冲区固定在物理内存中,因为换出它显然是不好的(因为硬件将继续写入物理内存区域)。控制区域也映射到用户空间内存中。当应用程序准备好使用缓冲区发送或接收消息时,它将命令写入控制区。硬件从一端的已注册缓冲区中获取数据,并将数据放入另一端的另一已注册缓冲区中。
显然,这太低了,所以有些抽象使RDMA硬件的编程更加容易。 OFED动词就是这样的一种抽象。
InfiniBand软件堆栈还有一个有趣的地方:套接字直接协议(protocol)(SDP),用于与现有应用程序兼容。它通过插入将标准套接字API调用转换为IB动词的LD_PRELOAD填充程序来工作。
我最熟悉InfiniBand。从程序员的角度来看,RoCE/iWARP硬件非常相似,但使用的传输方式与InfiniBand不同(iWarp中使用卸载引擎的TCP,RoCE中使用以太网的TCP)。 RDMA还有其他方法(例如,Quadrics)。