大端小端转换,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

 



原文地址:https://www.cnblogs.com/pengdonglin137/p/3423399.html