0

在 linux 2.6.x 上,给定以下结构

struct A
{
  int a;
  int b;
} ss;

我想到的将上述结构写入管道的两个选项是

  1. memcpy 从 &ss 到 sizeof(ss)
  2. 复制 ss->a,然后复制 ss->b

这个比那个好吗?

4

2 回答 2

2

There is no "correct" way but some methods are definitely better than others.

For starters, the size of an int is dependent on the machine, compiler and options. You probably don't want your network/ipc protocol to vary with those. Secondly, the order of the bytes in an integer can vary with the same things. So, first define the size of your integers and the order (endianess). Let's say you go with 32 bits, big endian. Then extract these bytes using numeric/logical operations - not byte copying or overlays. Finally, you might want to actually encode your size assumption in the stream.

Some sample code. Each function encodes the parameter into the buffer supplied and returns the number of characters used in the buffer.

int encode_int(int v, unsigned char *s) {
   s[0] = (v>>24) & 0xff;
   s[1] = (v>>16) & 0xff;
   s[2] = (v>>8) & 0xff;
   s[3] = v & 0xff;
   return 4;
}
int encode_A(struct A *a, unsigned char *s) {
   int offset = 0;
   s[offset++] = 4; // Size of ints - really belongs in a global header or in encode_int
   offset += encode_int(a->a, s+offset);
   offset += encode_int(a->b, s+offset);
   return offset;
}

Decoding has to take the supplied bytes and reassemble the integers using logical/arithmetic operations. Another possibility is to make encode_int use a variable number of bytes (and encode how many it used) if you expect mostly small integers and/or would like to also handle 64bit platforms. There are many other options - the main thing is don't allow the arbitrariness of the in-memory representation to define your protocol.

Also take a look at ntohl, htonl, ntohs, htons standard functions.

Ps. One final edit - if the size of an integer in the reader is not the same as that in the writer, care has to be taken to correctly handle negative integers.

于 2012-12-17T00:24:08.090 回答
0

我完全同意 DrC。

您的简单结构表明您只是在暗示您手头的问题。您需要考虑的是结构的内存布局,这可能因 CPU、编译器及其 sizeof(int) 而异。考虑:

struct B {
    int a;
    char b;
    int c;
}

编译器将在 sizeof(int) 边界上对齐“c”。也就是说'b'和'c'之间会有一些填充。如果 sizeof(int) 是 2,那么只需要一个额外的字节就可以让 'c' 从 int 边界开始。如果 sizeof(int) 为 4,就像在大多数 32 位处理器上一样,则需要三个填充字节。问题确实来自 64 位处理器。sizeof(int) 可以是四或八。

因此,对您的问题的简单回答是分别传输结构的每个元素,因为这样可以避免传输任何填充字节。但是,如果管道的两端都同意 sizeof(<data-type>) 等于什么,以及 int、longs、long longs、float、doubles 等的字节顺序,你就可以逃脱惩罚。

但是考虑到这些天的网络带宽,我认为最好使用基于 ASCII 的传输协议(例如 XML),除非有很好的理由不这样做。

于 2012-12-17T01:55:06.153 回答