大端小端轉換,le32_to_cpu 和cpu_to_le32


參考:http://oss.org.cn/kernel-book/ldd3/ch11s04.html

        小心不要假設字節序. PC 存儲多字節值是低字節為先(小端為先, 因此是小端), 一些高級的平台以另一種方式(大端)工作. 任何可能的時候, 你的代碼應當這樣來編寫, 它不在乎它操作的數據的字節序. 但是, 有時候一個驅動需要使用單個字節建立一個整型數或者相反, 或者它必須與一個要求一個特定順序的設備通訊.

        包含文件 <asm/byteorder.h> 定義了或者 __BIG_ENDIAN 或者 __LITTLE_ENDIAN, 依賴處理器的字節序. 當處理字節序問題時, 你可能編碼一堆 #ifdef __LITTTLE_ENDIAN 條件語句, 但是有一個更好的方法. Linux 內核定義了一套宏定義來處理之間的轉換, 在處理器字節序和你需要以特定字節序存儲和加載的數據之間. 例如:

u32 cpu_to_le32 (u32);
u32 le32_to_cpu (u32);

        這 2 個宏定義轉換一個值, 從無論 CPU 使用的什么到一個無符號的, 小端, 32 位數, 並且轉換回. 它們不管你的 CPU 是小端還是大端, 不管它是不是 32-位 處理器. 在沒有事情要做的情況下它們原樣返回它們的參數. 使用這些宏定義易於編寫可移植的代碼, 而不必使用大量的條件編譯建造.

        有很多類似的函數; 你可以在 <linux/byteorder/big_endian.h> 和 <linux/byteorder/little_endian.h> 中見到完整列表. 一會兒之后, 這個模式不難遵循. be64_to_cpu 轉換一個無符號的, 大端, 64-位 值到一個內部 CPU 表示. le16_to_cpus, 相反, 處理有符號的, 小端, 16 位數. 當處理指針時, 你也會使用如 cpu_to_le32p, 它使用指向一個值的指針來轉換, 而不是這個值自身. 剩下的看包含文件.

 

Then when do we use le32_to_cpu( ) , and when do we use cpu_to_le32( )? 

> The names tell it.

> le32_to_cpu is used for convesions from 32bit little endian data into CPUs endianness

> cpu_to_le32 is used for convesions from CPU endianness to little endian 32bit data. 
> Actually, both macros do the same thing, but one should make the differences clear to make code more readable so that anyone can quickly find out whether some data is kept in native endianness or some particular one. 

可以使用下面的方法來判斷處理器使用的什么模式

 

int GetEndianness() { short s = 0x0110; char *p = (char *) &s; if (p[0] == 0x10) return 0;// 小端格式
   else
      return 1;// 大端格式
}

 

參考:http://blog.chinaunix.net/uid-15751163-id-2762241.html

 

代碼中le32_to_cpu()、le16_to_cpu()按具體CPU的要求進行數據的排列,在i386處理器上訪問Ext2文件系統時這些函數不做任何事情。因為不同的處理器在存取數據時在字節的排列次序上有所謂“big ending”和“little ending”之分。例如,i386就是“little ending”處理器,它在存儲一個16位數據0x1234時,實際存儲的卻是0x3412,對32位數據也是如此。這里索引節點號與塊的長度都作為32位或16位無符號整數存儲在磁盤上,而同一磁盤既可以安裝在采用“little ending”方式的CPU機器上,也可能安裝在采用“big ending方式的CPU機器上,所以要選擇一種形式作為標准。事實上,Ext2采用的標准為“little ending”,所以,le32_to_cpu()、le16_to_cpu()函數不作任何轉換。

 

 

BSD Kernel Developer's Manual

NAME
     bswap16, bswap32, bswap64, be16toh, be32toh, be64toh, htobe16, htobe32,
     htobe64, htole16, htole32, htole64, le16toh, le32toh, le64toh, be16enc,
     be16dec, be32enc, be32dec, be64enc, be64dec, le16enc, le16dec, le32enc,
     le32dec, le64enc, le64dec -- byte order operations

SYNOPSIS
     #include <sys/endian.h>

     uint16_t
     bswap16(uint16_t int16);

     uint32_t
     bswap32(uint32_t int32);

     uint64_t
     bswap64(uint64_t int64);

     uint16_t
     be16toh(uint16_t big16);

     uint32_t
     be32toh(uint32_t big32);

     uint64_t
     be64toh(uint64_t big64);

     uint16_t
     htobe16(uint16_t host16);

     uint32_t
     htobe32(uint32_t host32);

     uint64_t
     htobe64(uint64_t host64);

     uint16_t
     htole16(uint16_t host16);

     uint32_t
     htole32(uint32_t host32);

     uint64_t
     htole64(uint64_t host64);

     uint16_t
     le16toh(uint16_t little16);

     uint32_t
     le32toh(uint32_t little32);

     uint64_t
     le64toh(uint64_t little64);

     uint16_t
     be16dec(const void *);

     uint32_t
     be32dec(const void *);

     uint64_t
     be64dec(const void *);

     uint16_t
     le16dec(const void *);

     uint32_t
     le32dec(const void *);

     uint64_t
     le64dec(const void *);

     void
     be16enc(void *, uint16_t);

     void
     be32enc(void *, uint32_t);

     void
     be64enc(void *, uint64_t);

     void
     le16enc(void *, uint16_t);

     void
     le32enc(void *, uint32_t);

     void
     le64enc(void *, uint64_t);

DESCRIPTION
     The bswap16(), bswap32(), and bswap64() functions return a byte order
     swapped integer.  On big endian systems, the number is converted to lit-
     tle endian byte order.  On little endian systems, the number is converted
     to big endian byte order.

     The be16toh(), be32toh(), and be64toh() functions return a big endian
     byte ordered integer converted to the system's native byte order.	The
     return value will be the same as the argument on big endian systems.

     The le16toh(), le32toh(), and le64toh() functions return a little endian
     byte ordered integer converted to the system's native byte order.	The
     return value will be the same as the argument on little endian systems.

     The htobe16(), htobe32(), and htobe64() functions return a integer in the
     system's native byte order converted to big endian byte order.  The
     return value will be the same as the argument on big endian systems.

     The htole16(), htole32(), and htole64() functions return a integer in the
     system's native byte order converted to little endian byte order.	The
     return value will be the same as the argument on little endian systems.

     The be16enc(), be16dec(), be32enc(), be32dec(), be64enc(), be64dec(),
     le16enc(), le16dec(), le32enc(), le32dec(), le64enc(), and le64dec()
     functions encode and decode integers to/from byte strings on any align-
     ment in big/little endian format.

SEE ALSO
     byteorder(3)

HISTORY
     The hto*() and toh*() functions first appeared in FreeBSD 5.0, and were
     originally developed by the NetBSD project.

     The encode/decode functions first appeared in FreeBSD 5.1.

BSD				April 29, 2002				   BSD

 




免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM