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

时间:2013-07-30 17:19:44

标签: c++ linux gcc glibc gcc4.4

生产问题导致我们的团队遇到以下问题:

  1. 在使用GCC 4.4.6的RHEL6下,如何实施ntohsntohl
  2. 已知实施是快还是慢?
  3. 如何实际查看函数的生成汇编代码?
  4. 我知道问题背后的含义可能看起来有些牵强和荒谬,但我被要求调查。

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

4 个答案:

答案 0 :(得分:12)

执行以下操作:

test.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)中,相关的asssembler是:

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

提示:

  • 305419896是十进制的0x12345678。
  • 12(%esp)是volatile变量的地址。
  • 所有movl说明适用于volatile - x的{​​{1}}。唯一真正有趣的指令是bswap
  • 显然,ntohl被编译为内联内在。

此外,如果我查看test.i(预编译输出),我会发现ntohl #defined只是__bswap_32(),它只是一个内联函数致电__builtin_bswap32()

答案 1 :(得分:11)

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

答案 2 :(得分:7)

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

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

答案 3 :(得分:1)

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

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