2009-08-28 26 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

あなたの提案の代替では、RFC2553からの要件として言及8バイト(64ビット)境界上で整列する構造全体を強制しないでしょう。

一般に、構造体は、そのメンバのいずれかによって要求される最も厳格な配置をとります。 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 
}; 

、組合はその後、外側の構造体に伝播し、その最も厳密に整列部材の整列要件を取得します。このバージョンでは、(構造体に埋め込まれていても)1つの必須フィールドと構造体全体が必要な正確なサイズの1つのパディング配列しか持たないことに注意してください。少し厄介なのは、__ss_familyのマクロ定義です。マクロトリックはRFCの要件に厳密に準拠していない可能性がありますが、その違いに気づく方法はほとんどありません。

+0

ユーザーがアクセスすることになっていることを@Dale、SOCKADDR_STORAGEで唯一のフィールドは、__ss_familyです。したがって、フィールドの残りの部分が64ビットの境界に揃えられていても、どのように役立つでしょうか?また、私は間違っていたsockaddr_in6ではなく、sockaddr_storageは、64ビット境界に位置合わせされることになっています。 – chappar

+1

構造体または共用体に64ビット境界整列を必要とするメンバ(たとえば、uint64_t)が含まれている場合、構造体自体は64ビット境界に配置されます。さもなければ、そのメンバーが一直線にとどまることを保証する方法はありません。もちろん、構造体自体が64ビットで整列されている場合、最初のフィールド( '__ss_family')も64ビットに整列されます。 – mark4o

0

あなたの意見では、

aと思われます。

int64_t __ss_align; 

は、構造体を64ビット境界に整列させます。

b。 __ss_pad1は、__ss_alignの直前にss_familyが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)が小さい構造をもたらす次いで切り捨てされるフロートを引き起こすであろう。

:)

関連する問題