2009-08-28 2 views
7

Di seguito è la definizione di struttura sockaddr_storage (rfc2553). Secondo rfc2553, il sockaddr_storage dovrebbe essere allineato con il limite a 64 bit e dovrebbe essere in grado di contenere sia sockaddr_in che sockaddr_in6. Inoltre, deve avere il membro __ss_family atlest. Il resto dei campi è definito dall'implementazione.Perché la struttura sockaddr_storage è definita come è definita?

#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 */ 
}; 

mia domanda è perché sockaddr_storage è definito come il modo di cui sopra? Perché non è stato definito come di seguito?

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

risposta

5

L'alternativa proposta non avrebbe costretto l'intera struttura da allineato a un limite di 8 byte (64-bit), che si parla come requisito da RFC2553.

In generale, una struttura assume l'allineamento più stretto richiesto da uno qualsiasi dei suoi membri. Poiché sa_family_t è probabilmente un u16_t, che richiede solo l'allineamento a 2 byte e una matrice di caratteri richiede al massimo l'allineamento a 1 byte, l'alternativa che si propone richiederebbe solo l'allineamento a 2 byte. (È probabile che il compilatore fornisca comunque almeno 4- e forse l'allineamento di 8 byte, ma non si può essere sicuri.)

Lo stile della definizione effettiva è un tentativo di assicurarsi che ogni byte in la struttura fa parte di un certo campo, cioè che il compilatore non inserisce alcuna spaziatura tra i campi. Questo è necessario (sorta di) in modo che _SS_PAD2SIZE abbia un valore che può essere calcolato in termini di dimensioni di tutti gli altri membri.

Tuttavia, trovo questa definizione piuttosto complicata. Sono abbastanza sicuro che le seguenti opere altrettanto bene, ed è un po 'più facile da capire:

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

Qui, l'unione acquisisce i requisiti di allineamento del suo membro più strettamente allineati, che poi si propaga alla struct racchiude . Nota che in questa versione ho solo il campo richiesto (anche se sepolto in un sindacato) e un singolo array di padding che è la dimensione esatta che voglio che sia l'intera struttura. L'unica parte leggermente ingannevole è la definizione macro di __ss_family. È possibile che il trucco macro non sia strettamente conforme ai requisiti della RFC, ma ci saranno pochi (se nessuno) modi per notare la differenza.

+0

@Dale, unico campo nel sockaddr_storage, che l'utente si suppone che l'accesso è __ss_family. Quindi, anche se il resto dei campi sono allineati a 64 bit, come può essere d'aiuto? Inoltre, ho sbagliato che è sockaddr_in6 piuttosto che sockaddr_storage che dovrebbe essere allineato al limite di 64 bit. – chappar

+1

Se una struttura o unione contiene un membro che richiede un allineamento a 64 bit (ad esempio 'uint64_t'), la struttura stessa verrà posizionata su un limite a 64 bit. Altrimenti non ci sarebbe modo di garantire che quel membro rimanga allineato. Naturalmente se la struttura stessa è allineata a 64 bit, anche il primo campo ('__ss_family') sarà allineato a 64 bit. – mark4o

0

Quindi, da quello che dicono i ragazzi, sembra che

a.

int64_t __ss_align; 

causa l'allineamento della struttura a un limite di 64 bit.

b. __ss_pad1 assicura che ss_family si trovi sul limite a 64 bit appena prima __ss_align

c. __ss_pad2 assicura la dimensione totale richiesta.

Avevo letto il codice sopra a http://www.opengroup.org/onlinepubs/000095399/basedefs/sys/socket.h.html#tag_13_61. Da ciò che è scritto lì, sembra che il valore di _SS_MAXSIZE sia deciso dall'implementatore.

Nel codice di cui da Dale, la divisione in

uint64_t u_pad[_SS_MAXSIZE/sizeof(uint64_t)]

causerà un galleggiante, che verrà poi troncata, che si traduce poi nella struttura essendo più piccola della dimensione richiesta (_SS_MAXSIZE).

:)