1. 程序自定义的数据结构
x86上的Linux作为server, 通过socket方式传递一个data struct:
点击(此处)折叠或打开
-
struct le_data{
-
uint32_t a;
-
uint32_t b;
-
uint32_t c;
- }__attribute__ ((packed));
点击(此处)折叠或打开
-
int main(void)
-
{
-
struct le_data le_dbuf;
-
int lisfd, connfd;
-
-
le_dbuf.a = 10;
-
le_dbuf.b = 20;
-
le_dbuf.c = 30;
-
...
-
wrn = write(connfd, &le_dbuf, sizeof(le_dbuf));
-
...
- }
AIX client如果需要通过socket得到正确的结构体中的变量b(=20),则必须做字节转换,否则将得到错误的数值,主要代码片段如下:
点击(此处)折叠或打开
-
struct le_data{
-
uint32_t a;
-
uint32_t b;
-
uint32_t c;
-
}__attribute__ ((packed));
-
-
inline uint32_t SwapEndian(uint32_t val)
-
{
-
val = (val<<24) | ((val<<8) & 0x00ff0000) |
-
((val>>8) & 0x0000ff00) | (val>>24);
-
return val;
-
}
-
-
int main(void)
- {
-
struct le_data ldata;
-
...
-
err = read(fd, (char *)&ldata, sizeof(ldata));
-
printf("sizeof(ldata) = %lu, ldata.b = %u\n", sizeof(ldata), SwapEndian(ldata.b));
-
...
- }
printf("sizeof(ldata) = %lu, ldata.b = %u\n", sizeof(ldata), ldata.b);
将会得到错误的结果,而不是20. 简单用下图解释一下上述结果(此处假设在x86机器上ldata.a =0x01020304, ldata.b=0x05060708):
图中左图是通过socket传输前的结构体对象ldata在x86机器内存中的layout,这段内存通过socket传输到PowerPC机器上后,在后者的内存空间中的layout是不变的,如右图所示。对结构体成员变量的解释属于编译器的范畴,所以x86上的ldata.a与PPC上的ldata.a的语义是相同的,但是对于处理器来讲,big与small对内存的解释不同,换言之,同样的ldata.a内存区,x86上处理器认为是0x01020304,而在PPC看来则是0x04030201,所以需要通过SwapEndian()的转换才可得到正确的值。
但是如果我们将一个文件的内容通过socket从Linux传到AIX上,则不需要关注big与small的转换问题,这是因为本地的文件系统写与读都采用同样的字节序,所以程序本身的代码无需再做额外的工作。文件即内存,除非程序需要自己解读文件中的内容。