6 votes

Tous les structs qui sont censés être lus à partir d'un binaire doivent-ils être marqués comme étant emballés ?

Je sais que certaines structures peuvent, ou non, ajouter un remplissage entre les éléments.

Mon projet actuel consiste à lire les entrées des fichiers /dev/input. La disposition binaire de ces fichiers est définie dans le fichier <linux/input.h> :

struct input_event {
    struct timeval time;
    __u16 type;
    __u16 code;
    __s32 value;
};

Je me demande cependant si cette structure est non marqués d'un attribut emballé . Cela signifie que les fichiers /dev/input (qui sont emballés bit par bit) ne sont pas garantis de correspondre au même paquetage que la structure. Ainsi, la logique

struct input_event event;
read(fd, &event, sizeof(event));

N'est pas défini pour fonctionner sur tous les archs.

Y a-t-il une erreur dans ma logique ? Ou est-il prudent de supposer que certaines choses ne seront pas emballées ?

2voto

Emballage par disposition

Dans le cas présent, vous êtes en sécurité. Votre structure input_event est déjà configurée et emballée.

struct timeval time;  /* 8 bytes */
__u16 type;           /* 2 bytes */
__u16 code;           /* 2 bytes */
__s32 value;          /* 4 bytes */

Cela signifie que les membres forment des blocs propres de 32 bits et qu'aucun remplissage n'est nécessaire. Ce site article explique comment la taille des membres d'une structure (en particulier les caractères) et leur disposition affectent le remplissage et donc la taille finale d'une structure.

Emballage par le préprocesseur

L'empaquetage des structs via le préprocesseur semble être une bonne solution à première vue. En y regardant de plus près, plusieurs inconvénients apparaissent et l'un d'eux vous frappe au point qui vous intéresse (voir aussi #pragma pack effect )

Performance

Le remplissage garantit que les membres de votre structure sont accessibles sans avoir à chercher dans les blocs de mémoire (blocs de 4 octets sur une machine 32 bits et blocs de 8 octets sur une machine 64 bits respectivement). En conséquence, l'empaquetage de telles structures conduit à ce que les membres s'étendent sur plusieurs blocs de mémoire et nécessitent donc que la machine les recherche.

Différentes plates-formes (Archs, compilateurs)

Les instructions du préprocesseur sont très spécifiques au fournisseur et à l'architecture. Ainsi, leur utilisation entraîne une portabilité moindre ou, dans le pire des cas, la non-portabilité de votre code.

Conclusion

En tant qu'auteur de ce article (déjà mentionné ci-dessus), même NTP lit directement les données du réseau dans les structures. Par conséquent, la solution la plus sûre et la plus portable est d'organiser soigneusement vos structures et de les remplir à la main.

1voto

Malcolm McLean Points 5437

Si vous insistez pour charger directement des structures en mémoire à partir d'images binaires, alors le C n'est pas votre ami. Le remplissage est autorisé, et les types de base peuvent avoir des largeurs et des endiannages différents. On ne vous garantit même pas 8 bits dans un octet. Cependant, le fait d'empaqueter les structures et de s'en tenir à int32_t et ainsi de suite vous sera d'une grande aide, c'est effectivement un endianning bar portable.

Mais la meilleure solution est de charger la structure à partir du flux de manière portative. C'est même possible avec des nombres réels, bien que ce soit un peu compliqué.

Voici comment lire un entier de 16 bits de manière portative. Voir mon projet github pour le reste des fonctions (logique similaire) https://github.com/MalcolmMcLean/ieee754

/**
  Get a 16-bit big-endian signed integer from a stream.
  Does not break, regardless of host integer representation.
  @param[in] fp - pointer to a stream opened for reading in binary mode
  @ returns the 16 bit value as an integer
*/
int fget16be(FILE *fp)
{
    int c1, c2;

    c2 = fgetc(fp);
    c1 = fgetc(fp);

    return ((c2 ^ 128) - 128) * 256 + c1;
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X