如何在RHEL / GCC下实现ntoh功能
How are the ntoh functions implemented under RHEL/GCC?
生产问题导致我们的团队提出以下问题:
- 在使用GCC 4.4.6的RHEL6下,如何实施
ntohs
和ntohl
? - 已知实现是快还是慢?
- 如何实际查看为函数生成的汇编代码?
我知道问题背后的含义可能看起来牵强而荒谬,但我被要求进行调查。
有问题的硬件是英特尔盒子,小端序,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
说明都是为了x
的volatile
性。唯一真正有趣的指令是bswap
. - 显然,
ntohl
被编译为内联内部函数。
此外,如果我查看test.i
(预编译输出(,我发现ntohl
#defined
为简单的__bswap_32()
,这是一个内联函数,只需调用__builtin_bswap32()
。
- 它们由 glibc 提供,而不是 GCC,在
/usr/include/bits/byteswap.h
中查找启用优化时使用的__bswap_16
和__bswap_32
函数(有关如何操作的详细信息,请参阅<netinet/in.h>
(。
你 - 没有说你用的是什么架构,在大端系统上,它们是无操作的,所以速度最快! 在小端序上,它们是特定于架构的手动优化汇编代码。
- 使用 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 类似。
相关文章:
- 如果没有malloc,链表实现将失败
- 如何在c++中实现处理器调度模拟器
- 如何在c++中使用引用实现类似python的行为
- 实现无开销push_back的最佳方法是什么
- 使用简单类型列表实现的指数编译时间.为什么
- 如何在BST的这个简单递归实现中消除警告
- 实现一个在集合上迭代的模板函数
- 我应该实现右值推送功能吗?我应该使用std::move吗
- 如何正确实现和访问运算符的各种自定义枚举器
- C++Union/Struct位域的实现和可移植性
- 这个极客对极客的trie实现是否存在内存泄漏问题
- 在c++中实现LinkedList时,应出现未处理的错误
- 为左值和右值的包装器实现C++范围
- 使用模板进行堆栈实现; "name followed by :: must be a class or namespace"
- 使用GSoap实现ONVIF
- 在用于格式4的arm模拟器中实现功能时的一个问题
- 用于AVX的ln(x)的实现,m256
- 用常见虚拟函数实现的任意组合来实现派生类的正确方法是什么
- 在C++中,如何在类和函数(可能是模板化的)的头中编写完整的实现
- 如何在RHEL / GCC下实现ntoh功能