字節序

這是linux對IP頭的定義 /usr/include/linux/ip.h 或 linux/include/linux/ip.h)

  1. struct iphdr { 
  2. #if __BYTE_ORDER == __LITTLE_ENDIAN 
  3. uint8_t ihl:4, 
  4. version:4; 
  5. #elif __BYTE_ORDER == __BIG_ENDIAN 
  6. uint8_t version:4, 
  7. ihl:4; 
  8. #endif 
  9. uint8_t tos; 
  10. uint16_t tot_len; 
  11. uint16_t id; 
  12. uint16_t frag_off; 
  13. uint8_t ttl; 
  14. uint8_t protocol; 
  15. uint16_t check; 
  16. uint32_t saddr; 
  17. uint32_t daddr; 
  18. /*The options start here. */ 
  19. }; 

版本號和首部長度是同一個字節的,這也要區分大端小端嗎?我一直以爲大端小端是字節間順序的問題,不是字節內部位順序的問題。網絡數據發送時是字節流還是位流?發送時uint16_t和uint32_t的高字節必需先發送,那麼同一字節的高位先發送還是低位?我找不到gcc講結構位定義的文檔,有鏈接麼?

可以這樣來解釋,
1)從道理上來說,little endian中的位應該這樣排列:
01234567
即排在前面的是低位。因此,先分配least significant bits
2)而在Big endian中,位應該這樣排列:
76543210
即排在前面的是高位。因此,先分配most significant bits。

可以這樣來理解,
1)在Big Endian的情況下,"排在前面的是高位"
a. 對於順序的兩個字節來說,第一個字節是高位(排在前面),第二個字節是低位(排在後面)。
b. 對於字節內部的位來說,
-------most significant bits排在前面,是高位,
-------least significant bits排在後面,是低位。
2)在Little Endian的情況下,"排在前面的是低位"
a. 對於順序的兩個字節來說,第一個字節是低位(排在前面),第二個字節是高位(排在後面)。
b. 對於字節內部的位來說,
-------least significant bits排在前面,是低位,
-------most significant bits排在後面,是高位。

這樣,在對struct中的成員進行分配的時候,"按排列順序分配,先分配排在前面的"
1)big endian從高位向低位分配,
a. 對字節,是先分配低地址的字節,再分配高地址的字節。
b. 對位域,先分配most significant bits,再分配least significant bits。
1)little endian從低位向高位分配,
a. 對字節,是先分配低地址的字節,再分配高地址的字節。
b. 對位域,先分配least significant bits,再分配most significant bits。

======================================

以上說的都是分配的順序。

對於IP協議來說,
1)IP's byte order is big endian.
2)The bit endianness of IP inherits that of the CPU,
3)and the NIC takes care of converting it from/to the bit transmission/reception order on the wire.

並且,按照IP協議,
1)"version" is the most significant four bits of the first byte of an IP header.
2)"ihl" is the least significant four bits of the first byte of the IP header.

也就是說,version必須分配在most significant four bits,
按照上面說的分配順序,在big endian中,version必須放在前面。

 

MSB  most significant bits

LSB    least significant bits

一句話:對於 little-endian 來說 MSB 在高地址,對 big-endian 來說 MSB 在低地址。

 

Here is how we would write the integer 0x0a0b0c0d for both big endian and little endian systems, according to the rule above:
Write Integer for Big Endian System
byte addr 0                1              2               3
bit offset  01234567 01234567 01234567 01234567
binary      00001010 00001011 00001100 00001101
hex           0a          0b         0c         0d

Write Integer for Little Endian System
byte addr 3               2              1                0
bit offset 76543210 76543210 76543210 76543210
binary     00001010 00001011 00001100 00001101
hex          0a           0b        0c          0d
In both cases above, we can read from left to right and the number is 0x0a0b0c0d.

 

在小字節序機器上跑測試例1:

  1. int value = 0x12345678;
  2.         union ValueT
  3.         {
  4.             int value;
  5.             char data[4];
  6.         } a;
  7.         a.value = 0x12345678;
  8.         printf("value is 0x%x/n", a.value);
  9.         printf("address is %p, 0x%x/n",&a.data[0], a.data[0]);
  10.         printf("address is %p, 0x%x/n",&a.data[1], a.data[1]);
  11.         printf("address is %p, 0x%x/n",&a.data[2],  a.data[2]);
  12.         printf("address is %p, 0x%x/n",&a.data[3], a.data[3]);
  13.         //value is 0x12345678
  14.         //address is 0012FF6C, 0x78
  15.         //address is 0012FF6D, 0x56
  16.         //address is 0012FF6E, 0x34
  17.         //address is 0012FF6F, 0x12

測試例2:

  1. struct bitfield{ 
  2.             int ia:2; 
  3.             int ib:6; 
  4.         } field; 
  5.         field.ia=1; 
  6.         field.ib=4; 
  7.         char * c; 
  8.         c=(char *)&field; 
  9.         printf("%d/n",*c);
  10.         // 17 = 000100 01

原帖地址:http://www.unixresources.net/linux/clf/program/archive/00/00/64/28/642822.html

亦可參考:http://bbs.chinaunix.net/viewthread.php?tid=823662&extra=&page=1    

               http://www.unixresources.net/linux/clf/linuxK/archive/00/00/63/86/638637.html

 

Endianness of CPU
The CPU endianness is the byte and bit order in which it interprets multi-byte integers from on-chip registers, local bus, in-line cache, memory and so on. 

Little endian CPUs include Intel and DEC. Big endian CPUs include Motorola 680x0, Sun Sparc and IBM (e.g., PowerPC). MIPs and ARM can be configured either way.

Endianness of Ethernet
Ethernet is big endian. This means the most significant byte of an integer field is placed at a lower wire byte address and transmitted/received in front of the least significant byte.

Endianness of IP
IP's byte order also is big endian. The bit endianness of IP inherits that of the CPU, and the NIC takes care of converting it from/to the bit transmission/reception order on the wire.

                  

發佈了134 篇原創文章 · 獲贊 29 · 訪問量 41萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章