如何在RHEL / GCC下实现ntoh功能

How are the ntoh functions implemented under RHEL/GCC?

本文关键字:实现 ntoh 功能 GCC RHEL      更新时间:2023-10-16

生产问题导致我们的团队提出以下问题:

  1. 在使用GCC 4.4.6的RHEL6下,如何实施ntohsntohl
  2. 已知实现是快还是慢?
  3. 如何实际查看为函数生成的汇编代码?

我知道问题背后的含义可能看起来牵强而荒谬,但我被要求进行调查。

有问题的硬件是英特尔盒子,小端序,64位处理器,并以64位编译。

执行以下操作:

测试.c

#include <arpa/inet.h>
int main()
{
   volatile uint32_t x = 0x12345678;
   x = ntohl(x);
   return 0;
}

然后编译:

$ gcc -O3 -g -save-temps test.c

并分析生成的test.s文件,或者运行objdump -S test.o .

在我的机器(Ubuntu 13.4(中,相关的组装器是:

movl    $305419896, 12(%esp)
movl    12(%esp), %eax
bswap   %eax
movl    %eax, 12(%esp)

提示:

  • 305419896以十进制表示0x12345678。
  • 12(%esp)是易失性变量的地址。
  • 所有movl说明都是为了xvolatile性。唯一真正有趣的指令是 bswap .
  • 显然,ntohl被编译为内联内部函数。

此外,如果我查看test.i(预编译输出(,我发现ntohl #defined为简单的__bswap_32(),这是一个内联函数,只需调用__builtin_bswap32()

  1. 它们由 glibc 提供,而不是 GCC,在/usr/include/bits/byteswap.h中查找启用优化时使用的 __bswap_16__bswap_32 函数(有关如何操作的详细信息,请参阅<netinet/in.h>(。
  2. 没有说你用的是什么架构,在大端系统上,它们是无操作的,所以速度最快! 在小端序上,它们是特定于架构的手动优化汇编代码。
  3. 使用 GCC 的 -save-temps 选项保留中间.s文件,或使用 -S 在编译后和组装代码之前停止,或使用 http://gcc.godbolt.org/

这些是在glibc中实现的。看看/usr/include/netinet/in.h。 他们很可能会依赖glibc byteswap宏(我的机器上的/usr/include/bits/byteswap.h(

这些是在我的标题中的汇编中实现的,所以应该很快。 对于常量,这是在编译时完成的。

GCC/glibc 导致 ntohl(( 和 htonl(( 内联到调用代码中。因此,避免了函数调用开销。此外,每个 ntohl(( 或 htonl(( 调用都会转换为单个 bswap 汇编器操作。根据"英特尔 64 和 IA-32 架构优化参考手册",bswap 在所有当前的英特尔® CPU 上的延迟和吞吐量均为"1"。因此,只需要一个 CPU 时钟即可执行 ntohl(( 或 htonl((。

ntohs(( 和 htons(( 被暗示为旋转 8 位。这有效地交换了 16 位操作数的两半。延迟和吞吐量与 bswap 类似。