7


2

下記はsockaddr_storage構造体の定義です( rfc2553)。 rfc2553によると、sockaddr_storageは64ビット境界に揃えられ、sockaddr_inとsockaddr_in6の両方を保持できるはずです。 また、それは少なくとも__ss_familyメンバーを持っていなければなりません。 残りのフィールドは実装定義です。

#define _SS_MAXSIZE 128 / *実装固有の最大サイズ* / #define _SS_ALIGNSIZE(sizeof(int64_t))/ *実装固有の望ましい配置
 *  sockaddr_storage構造体パディングデザインに使用される定義。 * /#define _SS_PAD1SIZE(_SS_ALIGNSIZE  -  sizeof(sa_family_t))#define _SS_PAD2SIZE(_SS_MAXSIZE  - (sizeof(sa_family_t)_SS_PAD1SIZE _SS_ALIGNSIZE))struct sockaddr_family_t / *アドレスファミリ* / / *以下のフィールドは実装固有のものです* / char __ss_pad1 [_SS_PAD1SIZE]; / * 6バイトパッド。これは、* / / *がデータ構造内で明示的に続くアライメントフィールドまで実装/ *固有のパッドを作成するためです* / int64_t __ss_align; / *目的の構造を強制するフィールド* / / *ストレージアライメント* / char __ss_pad2 [_SS_PAD2SIZE]; / *目的のサイズを達成するための112バイトパッド、* / / * _SS_MAXSIZE値 -  ss_familyのサイズ* / / * __ss_pad1、__ss_alignフィールドは112 * /}。

私の質問は、sockaddr_storageが上記のように定義されているのはなぜですか? なぜそれが以下のように定義できなかったのでしょうか。

struct sockaddr_storage {sa_family_t __ss_family;} / *アドレスファミリ* / char __ss_pad [_SS_MAXSIZE  -  sizeof(sa_family_t)]; //ここにアライメントの問題がありますか? ;

2 Answer


6


あなたが提案した代替案では、構造全体を8バイト(64ビット)境界に整列させることは強制されません。これは、RFC2553の要件として言及されています。

一般に、構造体はそのメンバーのいずれかで必要とされる最も厳密な配置を取ります。 sa_family_t`はたぶん2バイトのアラインメントしか必要としない u16_t`であり、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つの必須フィールド(共用体に埋め込まれていますが)と、構造体全体に必要な正確なサイズである単一のパディング配列しかありません。 わずかにトリッキーな部分は `__ss_family`のマクロ定義です。 マクロトリックがRFCの要件に厳密に準拠していない可能性がありますが、違いに気付く方法は(あるとしても)ほとんどありません。


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の値は実装者によって決定されることになっているようです。

Daleが述べたコードでは、

uint64_t u_pad [_SS_MAXSIZE / sizeof(uint64_t)]

floatが発生します。これは切り捨てられ、その結果、構造体は必要なサイズ(_SS_MAXSIZE)よりも小さくなります。

:)