https://mp.weixin.qq.com/s/B9rKps4YsLiDTBkRks8rmQ
看到比特序和字节序放在一起被提及,想必就已经填补了概念拼图里面缺失的那一块了,这一块正是比特序。
一直以来,接触到最多的就是字节序:
大端字节序:big-endian byte order;
小端字节序:little-endian byte order;
网络字节序:network byte order;
大小端字节序转换:
/* 大端字节序 */ i = (data[3]<<0) | (data[2]<<8) | (data[1]<<16) | (data[0]<<24); /* 小端字节序 */ i = (data[0]<<0) | (data[1]<<8) | (data[2]<<16) | (data[3]<<24);
网络字节序转换:
uint32_t htonl(uint32_t hostlong);
uint16_t htons(uint16_t hostshort);
uint32_t ntohl(uint32_t netlong);
uint16_t ntohs(uint16_t netshort);
是不是很熟悉?
见多识广的想必也见过这个(from linux kernel include/uapi/linux/tcp.h ):
struct tcphdr { __be16 source; __be16 dest; __be32 seq; __be32 ack_seq; #if defined(__LITTLE_ENDIAN_BITFIELD) __u16 res1:4, doff:4, fin:1, syn:1, rst:1, psh:1, ack:1, urg:1, ece:1, cwr:1; #elif defined(__BIG_ENDIAN_BITFIELD) __u16 doff:4, res1:4, cwr:1, ece:1, urg:1, ack:1, psh:1, rst:1, syn:1, fin:1; #else #error "Adjust your <asm/byteorder.h> defines" #endif __be16 window; __sum16 check; __be16 urg_ptr; };
明显跟我们之前见到的以字节为单位进行转换的不同,这里是以bit为单位;
不深究的话,可能看到BIG_ENDIAN和LITTLE_ENDIAN还有下面的 "Adjust your <asm/byteorder.h> defines" ,就觉得是byte order的变种,也理解成byteorder就行了。
如果知道bit order的概念,就知道这是两个不同的概念了。
PS. 关于上面tcphdr的定义:
1. 条件编译的宏是 :
__LITTLE_ENDIAN_BITFIELD
__BIG_ENDIAN_BITFIELD
意思是比特域的大小端,和字节序大小端是分开的:
__LITTLE_ENDIAN
__BIG_ENDIAN
2. 下面的#error又说是byteorder,
#error "Adjust your <asm/byteorder.h> defines"
是否矛盾?这里的情况是,linux kernel中把字节序和比特序都放在byteorder.h里面定义。这里只说调整这个头文件的定义,并没有说调整字节序的定义,所以应该没问题。
include/uapi/linux/byteorder/big_endian.h 中的定义:
#ifndef _UAPI_LINUX_BYTEORDER_BIG_ENDIAN_H #define _UAPI_LINUX_BYTEORDER_BIG_ENDIAN_H #ifndef __BIG_ENDIAN #define __BIG_ENDIAN 4321 #endif #ifndef __BIG_ENDIAN_BITFIELD #define __BIG_ENDIAN_BITFIELD #endif