2009-08-28 76 views
7

下面是sockaddr_storage結構的定義(rfc2553)。根據rfc2553,sockaddr_storage 應該與64位邊界對齊,它應該能夠同時保存sockaddr_in和sockaddr_in6。 此外,它必須有atlest __ss_family成員。其餘的字段是實現定義的。爲什麼將sockaddr_storage結構定義爲定義的方式?

#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? 
}; 

回答

5

你擬議的替代不會強迫整個結構的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 
}; 

這裏,工會獲得了最嚴格對齊的成員,然後傳播到封閉結構的對齊要求。請注意,在這個版本中,我只有一個必需的字段(雖然埋入了一個聯合體)和一個單一的填充數組,它是我希望整個結構體的確切大小。唯一稍微棘手的部分是__ss_family的宏定義。宏觀技巧可能並不嚴格符合RFC中的要求,但是很少有(如果有的話)方法可以注意到這種差異。

+0

@Dale,只有在struct sockaddr_storage的領域,用戶應該訪問__ss_family。所以,即使其餘的字段都對齊到64位的邊界,這將如何幫助?此外,我錯了,它是sockaddr_in6而不是sockaddr_storage應該對齊到64位邊界。 – chappar 2009-08-28 08:22:50

+1

如果結構或聯合包含需要64位對齊的任何成員(例如'uint64_t'),則結構本身將被放置在64位邊界上。否則,將無法保證該成員將保持一致。當然,如果結構本身是64位對齊的,那麼第一個字段('__ss_family')也將是64位對齊的。 – mark4o 2009-08-28 14:07:04

0

所以從你們所說的看來,

a。

int64_t __ss_align; 

導致結構對齊到64位邊界。

b。 __ss_pad1確保ss_family在__ss_align之前位於64位邊界上

c。 __ss_pad2確保所需的總尺寸。

我讀過上面的代碼 http://www.opengroup.org/onlinepubs/000095399/basedefs/sys/socket.h.html#tag_13_61。從那裏寫的東西看來,_SS_MAXSIZE的價值似乎由實施者決定。

在由戴爾,分割提到的代碼在

uint64_t u_pad[_SS_MAXSIZE/sizeof(uint64_t)]

會導致浮動,其然後將被截斷,這隨後導致該結構是較小的,所需的尺寸(_SS_MAXSIZE)。

:)