【Linux内核】字节序和位域(1)

news/2025/1/4 11:49:48/文章来源:https://www.cnblogs.com/o-O-oO/p/18646589

Linux内核定义的TCP首部的结构体tcphdr如下图所示。你会发现一个奇怪的问题:处理器使用大端字节序时字节内部的位域定义顺序和处理器使用小端字节序时相反,但是位域的字节顺序相同。如果你能把这个问题解释清楚,那么说明你已经完全掌握字节序和比特序,不需要阅读这篇文章。

1. 字节序和比特序

字节序是指多字节数据(例如C语言中的short、int和long类型)在计算机内存中存储或者网络传输时字节的排列顺序。

字节序分为大端(big-endian)序小端(little-endian)序。大端序把多字节数据的高字节存放在内存的低地址,把数据的低字节存放在内存的高地址。这种排列方式和数据用字节表示时的书写顺序一致,符合人类的阅读习惯。除了处理器以外,其它场合几乎都使用大端字节序,例如网络传输和文件存储。

小端序把多字节数据的低字节存放在内存的低地址,把数据的高字节存放在内存的高地址。处理器先处理低位,效率比较高,因为计算都是从低位开始的,例如加法运算,如果从高位开始,不知道低位是否产生进位。

比特序是一个字节的8个二进制位的顺序。通常处理器使用的比特序和字节序保持一致,使用大端字节序的时候比特序是大端序,也就是从高位到低位存放;使用小端字节序的时候比特序是小端序,也就是从低位到高位存放。

例如16进制的32位整数0x12345678使用两种字节序在内存中的存储顺序如下。

x86处理器使用小端字节序和小端比特序,ARM64处理器的字节序是可配置的。

ARM64架构的GCC编译器提供机器相关选项“-mbig-endian”和“-mlittle-endian”。选项“-mbig-endian”生成大端序代码,为“aarch64_be--”目标配置GCC的时候这个选项是默认的。选项“-mlittle-endian”生成小端序代码,为“aarch64--”目标配置GCC的时候这个选项是默认的。

1.1. 主机字节序和网络字节序

主机字节序是处理器的字节序,网络字节序是多字节数据在网络上的字节传输顺序。为了保证数据在不同主机之间传输时能够被正确解释,IP协议的规范RFC 791规定发送多字节数据的时候先发送高字节,也就是规定网络字节序是大端字节序。以太网是现实世界中最普遍的一种计算机网络,先传输高字节,但是每个字节先传输低位。

网卡把从网络收到的报文写到内存的时候,把每个字节的比特序转换成处理器使用的比特序。软件读取报文中的多字节数据,需要把字节序从网络字节序转换为主机字节序。网卡只负责转换每个字节的比特序,不负责转换字节序,因为网卡不知道多字节数据的起始位置和长度,只有软件才知道。

发送报文的时候,软件需要把报文中的所有多字节数据从主机字节序转换为网络字节序。网卡从内存读取报文、把报文发送到网络的时候,把每个字节的比特序转换成网络使用的比特序。

1.2. glibc库提供的字节序编程接口

可以使用宏__BYTE_ORDER判断字节序:如果__BYTE_ORDER等于__BIG_ENDIAN,那么使用大端字节序;如果__BYTE_ORDER等于__LITTLE_ENDIAN,那么使用小端字节序。__PDP_ENDIAN是PDP字节序(PDP-Endian),又称为中间序(Middle-Endian)或者混合序(Mixed-Endian),是DEC PDP-11处理器使用的字节序,是小端序和大端序的混合体,32位整数的存储方式是高16位和低16位使用大端序、但16位内部使用小端序。现在很少使用PDP字节序,我们不需要关注它。

可以使用宏BYTE_ORDER判断字节序:如果BYTE_ORDER等于BIG_ENDIAN,那么使用大端字节序;如果BYTE_ORDER等于LITTLE_ENDIAN,那么使用小端字节序。

可以使用GNU C扩展的预定义宏__BYTE_ORDER__判断字节序,

它的值可能是__ORDER_LITTLE_ENDIAN____ORDER_BIG_ENDIAN__或者__ORDER_PDP_ENDIAN__

函数htonl()把32位整数从主机字节序转换为网络字节序,函数htons()把16位整数从主机字节序转换为网络字节序。

函数ntohl()把32位整数从网络字节序转换为主机字节序,函数ntohs()把16位整数从网络字节序转换为主机字节序。

下面这些函数把16、32或64位整数在主机字节序和大/小端字节序之间转换。

(1) htobe16()、htobe32()、htobe64()、htole16()、htole32()和htole64()。

(2) be16toh()、be32toh()、be64toh()、le16toh()、le32toh()和le64toh()。

1.3. Linux内核提供的字节序编程接口

如果定义了宏__BIG_ENDIAN,那么应该使用大端字节序。如果定义了宏__LITTLE_ENDIAN,那么应该使用小端字节序。

如果定义了宏__BIG_ENDIAN_BITFIELD,那么位域应该使用大端字节序。如果定义了宏__LITTLE_ENDIAN_BITFIELD,那么位域应该使用小端字节序。

定义使用大端字节序的整数的时候,应该使用__be16、 __be32和__be64这些类型。__be16是__u16的别名,__be32是__u32的别名,__be64是__u64的别名,好处是名字可以提示你使用大端字节序。

定义使用小端字节序的整数的时候,应该使用__le16、__le32和__le64这些类型。__le16是__u16的别名,__le32是__u32的别名,__le64是__u64的别名,好处是名字可以提示你使用小端字节序。

宏htonl()把32位整数从主机字节序转换为网络字节序,宏htons()把16位整数从主机字节序转换为网络字节序。

宏ntohl()把32位整数从网络字节序转换为主机字节序,宏ntohs()把16位整数从网络字节序转换为主机字节序。

__constant_htonl()、__constant_htons()、__constant_ntohl()和__constant_ntohs()这4个宏的参数是常数。

下面这些宏把16、32或64位整数在处理器字节序和大/小端字节序之间转换。

(1) cpu_to_be16()、cpu_to_be32()、cpu_to_be64()、cpu_to_le16()、cpu_to_le32()和cpu_to_le64()。

(2) be16_to_cpu()、be32_to_cpu()、be64_to_cpu()、le16_to_cpu()、le32_to_cpu()和le64_to_cpu()。

下面这些宏把指针指向的16、32或64位整数在处理器字节序和大/小端字节序之间转换,返回转换后的值,不修改指针指向的内存。

(1) cpu_to_be16p()、cpu_to_be32p()、cpu_to_be64p()、cpu_to_le16p()、cpu_to_le32p()和cpu_to_le64p()。

(2) be16_to_cpup()、be32_to_cpup()、be64_to_cpup()、le16_to_cpup()、le32_to_cpup()和le64_to_cpup()。

原创 微信号szyhb1981 Linux驿站

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/862535.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

多尺度计算3

分成四个阶段第一个阶段,是pretrain。先学习mean和variance的生成,一条轨迹会生成两个平均值和方差(分别表示时间和空间的)。然后输入到解码器中解码,两个lstm.一个用于重构时间,一个是用于重构路段 第二个阶段,是生成Gaussian model。计算sample轨迹的mean和variance,…

[Windows/虚拟化/OS] WSL(Windows Subsystem for Linux)技术

概述:WSL 什么是WSL?WSL代表“Windows Subsystem for Linux”,是一种由Microsoft开发的技术,允许在Windows操作系统上运行Linux发行版(如Ubuntu、Debian、Fedora等)。WSL的目标是在Windows环境中提供原生的Linux兼容性,让开发者能够在Windows系统上进行Linux开发,无需创…

NGINX完全指南:实现高性能负载均衡的进阶实操指南(第三版)PDF、EPUB免费下载

NGINX 是当今使用最广泛的 Web 服务器之一,部分原因在于它可以用作 HTTP 和其他网络协议的负载均衡器和反向代理服务器。本修订版完全指南通过一些简单易懂的例子解析了应用交付中真实存在的问题。实用的实操指南可帮助您设置开源或商业产品,并利用它们解决各种用例中的问题。…

架构师启示录:知识模型、落地方法与思维模式PDF、EPUB免费下载

本书由资深架构师撰写,从架构知识模型、架构落地方法和架构思维模式三大维度剖析架构师的能力模型。具体而言,本书融合TOGAF、DDD、RUP等主流架构方法论,抽象出一个具有高度普适性的架构认知框架,帮助读者轻松入门,成为合格架构师。适读人群 :资深程序员、初级架构师 从架…

Chrome Updater(Chrome更新器) v2.1

Chrome Updater 是一个便携Chrome、Chrome++版本检查和更新的工具。将程序放置于App目录内或手动指定App文件夹,未检测到Chrome将初始化安装。部分API依赖于GitHub服务,如果遇到网络问题可以设置GitHub代理。Chrome及Chrome++均可单独更新,互不影响。 配置存储路径:C:Users…

PowerISO(映像文件处理) v8.9 中文版

PowerISO作为一款专业的映像文件处理软件,凭借其出色的功能收到了众多用户的喜爱。PowerISO软件小巧,下载包仅为3.6M,支持大部分的CD/DVD–ROM映像文件格式,而且PowerISO同时支持Windows的32位与64位操作系统,功能实用,操作简便。获取地址:https://www.dmjf.top/2273.htm…

Android 万能格式转换器 v1.2.1 专业版

万能格式转换器 是一个一键操作的格式转换工具,可以轻松实现多种视频格式、音频格式、文档格式、图片格式转换。同时支持日常生活中的各种文件转换,比如视频转换音频、视频压缩、视频音频提取、图片转pdf、视频md5转码等。获取地址:https://www.dmjf.top/2592.html

PDF-XChange Editor Plus(PDF编辑器) v10.4.4.392 便携版

PDF-XChange PRO-使用PDF的通用解决方案。包含了Tracker软件的三个最佳应用程序的软件包:PDF-XChange Editor Plus,PDF-Tools和PDF-XChange Standard。 使用PDF-XChange Editor Plus,您可以创建,查看和编辑图像和PDF文件。 PDF-Tools在创建和处理PDF文件方面处于世界领先地…

《docker基础篇:5.本地镜像发布到阿里云》

《docker基础篇:5.本地镜像发布到阿里云》@目录5.本地镜像发布到阿里云本人其他相关文章链接 5.本地镜像发布到阿里云案例使用步骤: 1)本地镜像素材原型 2)阿里云开发者平台 3)创建仓库镜像 4)将镜像推送到阿里云 5)将阿里云上的镜像下载到本地 6)运行 注意点1: 本地镜…

【Linux运维】网络及网卡收发数据过程和Linux服务器排查丢包方法

服务器丢包是网络通信中常见的问题之一,它会导致网络不稳定和数据丢失,进而影响业务的正常运行。面对这种情况,我们需要采取一系列措施来诊断和解决问题。以下是一些有效的解决方法和建议,帮助你应对服务器丢包问题。 首先,我们要知道网络数据是如何封装及流向的,涉及哪些…

教育资源库:AI知识库在教学资源共享中的作用

一、引言 在当今教育领域,教学资源共享已成为提升教学质量和促进教育公平的重要手段。然而,传统的教学资源共享方式面临着诸多挑战,如资源检索效率低下、资源质量参差不齐、难以实现个性化学习等。随着人工智能技术的快速发展,AI知识库作为一种新兴的智能工具,正逐步改变教…

风险管理新视角:AI知识库在金融风险评估中的应用

一、引言 金融风险评估是金融机构运营中的关键环节,它直接关系到金融机构的稳健运营和客户的资金安全。然而,传统的金融风险评估方法往往依赖于人工经验和历史数据,存在评估周期长、准确性不足等问题。随着人工智能技术的兴起,AI知识库作为一种智能风险评估工具,正逐渐在金…