biefield与endian 2
本帖最后由 karma303 于 2016-07-06 17:19 编辑本来想更新到这篇旧帖子里的,但觉得这部分有点儿“地理大发现”的感觉,就专门贴出来,跟各位交流。
我说的“地理大发现”,是说wiki上的ip header的布局图,它们用0,1,2,3,4,5,6,7细分出每个字节的bit,但wiki上的0,1,2,3,4,5,6,7,分别对应常规思维的7,6,5,4,3,2,1,0。
到这里我才发现,原来wiki上给出的布局图,是彻彻底底的按照“大端思维“来走的。
其实wiki就从RFC里摘的图,1981年的文档,那时的程序员为什么会反着看bit?(是没经过x86的洗礼吗?)
题外话:
在上一篇帖子里,我贴了一点关于bitfield跨字节的测试。
其实今天意识到这个问题,也是从ip header里的offset成员开始的,我发现没办法用bitfield来表示这个成员。
如果编译目标是小端机器,gcc是没有办法用bitfield来表示offset这个成员的。
所以linux内核里,很粗暴的定义成:
__be16 frag_off;
__be16就是unsigned short。
然后在代码里再分解它:
offset = ntohs(ip_hdr(skb)->frag_off);
flags = offset & ~IP_OFFSET;
offset &= IP_OFFSET;
offset <<= 3; /* offset is in 8-byte chunks */ 回复 1# karma303
佩服 LZ 深度钻研的精神!
回复 1# karma303
最后一个图,太能说明问题了。{:qq11:}
karma303 发表于 2016-07-06 17:17 static/image/common/back.gif
本来想更新到这篇旧帖子里的,但觉得这部分有点儿“地理大发现”的感觉,就专门贴出来,跟各位交流。
...
在部分平台或许可以,linux要用在各种CPU平台上,所以这样了 本帖最后由 nswcfd 于 2016-07-07 17:04 编辑
精彩的分析!
对于线上的bit,估计是先到的算0号吧? 回复 5# nswcfd
网线按什么样的bit序传递数据,似乎影响不到软件编程。连写网卡驱动时都不需要关心它。
我在osdev上问过相关的问题,但得到的回答有不痛不痒,可能是我英文水平有限吧。
forum.osdev.org/viewtopic.php?f=1&t=30485 本帖最后由 nswcfd 于 2016-07-07 18:39 编辑
嗯,forum.osdev.org/viewtopic.php?f=1&t=30485,很有意思的讨论。
https://en.wikipedia.org/wiki/Bit_numbering
里面有一句话
The recommended style for Request for Comments documents is "MSB 0" bit numbering.
Scott, Gregor (June 1998 ). "RFC 2360 - Guide for Internet Standards Writers". Internet Engineering Task Force (IETF). p. 11. Retrieved 2010-02-14. The preferred form for packet diagrams is a sequence of long words in network byte order, with each word horizontal on the page and bit numbering at the top
"RFC 1166 - INTERNET NUMBERS". Internet Engineering Task Force (IETF). July 1990. p. 1. Retrieved 2014-06-11. Whenever an octet represents a numeric quantity the left most bit in the diagram is the high order or most significant bit
https://upload.wikimedia.org/wikipedia/commons/5/54/Msb0.svg
本帖最后由 nswcfd 于 2016-07-07 19:31 编辑
struct BYTE {
char bit:1;
};
bitfield是C语言的概念,所以C编译器需要关心,BYTE.bit到底使用MSB还是使用LSB。
*选择LSB,BYTE.bit =1 对应 or 0x01;
*选择MSB,BYTE.bit = 1对应 or 0x80;
*选择其它bit应该也是可以的吧?
我的问题是,虽然x86上的gcc事实上选择了LSB(没说错吧?),
但是如果假设它选择了使用MSB,那有没有违反C标准的规定?或者会造成其它语义上的错误? 回复 8# nswcfd
《程序员的自我修养》的附录A.1讲了byte order,不知道你看过没。
类似这样的句子,
Big-endian和little-endian的区别就是big-endian规定MSM在存储时放在低地址,在传输时MSB放在流的开始;LSB存储时放在高地址,在传输时放在流的末尾。little-endian则相反。
讲的很好。
但我几乎不关心LSB和MSB的概念,它只会让我困扰。
所以你的问题,都不在我的思维模式里,抱歉我一个答不上来。
回复 4# mordorwww
对,像MIPS上,用bitfield访问就很自然。
这种东西,只要道理明白了,剩下的都事在人为。像我的内核(x86)里,照样的用bitfield访问:
struct iphdr{
u32 len: 4; /* header length */
int version: 4;
u8 ignore;
u16 tot_len; /* total length, header included */
u16 msgid; /* IP datagram identification */
union{
struct{
u16 me_offset: 13; /* the offset of this IP fragment */
int flag_mf: 1; /* more fragments */
int flag_df: 1; /* don't fragment */
int flag_reserved: 1;
};
u16 flag_off;
};
u8 ttl;
u8 protocol;
u16 chksum;
u32 myip;
u32 yourip;
};
每当接收到一个ip报文时,我先把flag_off成员字节翻转,然后就可以用bitfield访问了。
页:
[1]
2