为什么将sockaddr_storage结构定义为定义方式?

时间:2009-08-28 05:04:44

标签: c unix sockets

以下是sockaddr_storage结构(rfc2553)的定义。根据rfc2553,sockaddr_storage 应该与64位边界对齐,它应该能够同时保存sockaddr_in和sockaddr_in6。 此外,它必须有at __ss_family成员。其余的字段是实现定义的。

#define _SS_MAXSIZE    128  /* Implementation specific max size */
#define _SS_ALIGNSIZE  (sizeof (int64_t))
                         /* Implementation specific desired alignment */
/*
 * Definitions used for sockaddr_storage structure paddings design.
 */
#define _SS_PAD1SIZE   (_SS_ALIGNSIZE - sizeof (sa_family_t))
#define _SS_PAD2SIZE   (_SS_MAXSIZE - (sizeof (sa_family_t)+
                              _SS_PAD1SIZE + _SS_ALIGNSIZE))
struct sockaddr_storage {
    sa_family_t  __ss_family;     /* address family */
    /* Following fields are implementation specific */
    char      __ss_pad1[_SS_PAD1SIZE];
              /* 6 byte pad, this is to make implementation
              /* specific pad up to alignment field that */
              /* follows explicit in the data structure */
    int64_t   __ss_align;     /* field to force desired structure */
               /* storage alignment */
    char      __ss_pad2[_SS_PAD2SIZE];
              /* 112 byte pad to achieve desired size, */
              /* _SS_MAXSIZE value minus size of ss_family */
              /* __ss_pad1, __ss_align fields is 112 */
};

我的问题是为什么sockaddr_storage被定义为上面的方式?为什么不能定义如下?

struct sockaddr_storage {
    sa_family_t  __ss_family;     /* address family */
    char __ss_pad[_SS_MAXSIZE  - sizeof(sa_family_t) ]; //will there be any alignment issue here?
};

2 个答案:

答案 0 :(得分:6)

您建议的替代方案不会强制整个结构在8字节(64位)边界上对齐,您提到RFC2553的要求。

通常,结构需要其任何成员所需的最严格的对齐。由于sa_family_t可能是u16_t,只需要2字节对齐,而char数组最多需要1字节对齐,因此您建议的替代方案只需要2字节对齐。 (无论如何,编译器可能会给它至少4个甚至8个字节的对齐,但你无法确定。)

实际定义的样式是尝试确保结构中的每个字节都是某个命名字段的一部分,即编译器不在字段之间插入任何填充。这是必需的(有点),以便_SS_PAD2SIZE具有可以根据所有其他成员的大小计算的值。

但是,我发现这个定义相当复杂。我非常确定以下内容同样适用,并且更容易理解:

struct sockaddr_storage {
    union {
        sa_family_t u_family;
        uint64_t u_pad[_SS_MAXSIZE / sizeof(uint64_t)];
    } __ss_u;
#   define __ss_family __ss_u.u_family
};

这里,union获取其最严格对齐的成员的对齐要求,然后该成员传播到封闭结构。请注意,在这个版本中,我只有一个必填字段(虽然埋在一个联合中)和一个填充数组,它是我想要整个结构的确切大小。唯一有点棘手的部分是__ss_family的宏定义。宏技巧可能并不严格符合RFC中的要求,但很少有(如果有的话)注意到差异的方法。

答案 1 :(得分:0)

所以从你们所说的,似乎

一个。

int64_t   __ss_align;

导致结构与64位边界对齐。

__ss_pad1确保ss_family位于__ss_align

之前的64位边界上

℃。 __ss_pad2确保所需的总大小。

我已阅读上述代码 http://www.opengroup.org/onlinepubs/000095399/basedefs/sys/socket.h.html#tag_13_61。从那里写的,似乎_SS_MAXSIZE的值由实施者决定。

在Dale提到的代码中,

中的分部

uint64_t u_pad[_SS_MAXSIZE / sizeof(uint64_t)]

将导致浮动,然后将其截断,然后导致结构小于所需大小(_SS_MAXSIZE)。

:)