Question

J'écris un système de contrôle intégré dans le C qui se compose de plusieurs tâches qui envoient des messages les uns aux autres (un langage assez commun, je crois!), Mais je vais avoir du mal à concevoir un mécanisme qui:

  • est propre
  • est générique
  • est relativement efficace
  • le plus important: est la plate-forme indépendante (en particulier, ne viole pas-aliasing stricte ou des problèmes d'alignement)

Conceptuellement, je voudrais représenter chaque type de message comme une définition struct séparée, et je voudrais un système avec les fonctions suivantes (simplifié):

void sendMsg(queue_t *pQueue, void *pMsg, size_t size);
void *dequeueMsg(queue_t *pQueue);

où un queue_t comprend une liste chaînée de noeuds, chacun avec un champ de char buf[MAX_SIZE]. Le système que je suis ne dispose pas d'une mise en œuvre de malloc(), donc il faudra être un pool global de nœuds libres, puis l'un des suivants (problèmes perçus en gras):

  1. sendMsg() fait un memcpy du message entrant dans le tampon d'un nœud libre.
    Je crois comprendre que cela aura des problèmes d'alignement à moins que l'appelant de dequeueMsg() fait un memcpy plus loin la valeur de retour.
  2. ou il y aura une fonction qui renvoie le void *getFreeBuffer() buf[] du nœud suivant libre, que l'appelant (l'expéditeur) projettera au pointeur à type approprié.
    je crois comprendre que ce va maintenant avoir des problèmes d'alignement sur la manière, et nécessite encore un memcpy après dequeueMsg() pour éviter les problèmes d'alignement sur la sortie.
  3. ou redéfinir la mémoire tampon dans les noeuds queue_t comme (par exemple) uint32_t buf[MAX_SIZE].
    Ma compréhension est que cela constitue une violation aliasing stricte et n'est pas indépendant de la plateforme.

La seule autre option que je peux voir est de créer une union de tous les types de messages ainsi que des char buf[MAX_SIZE], mais je ne compte pas comme « propre »!

Alors, ma question est, comment peut-on faire correctement?

Était-ce utile?

La solution

La façon dont nous traitons est d'avoir notre liste libre sont constitués entièrement de nœuds alignés. En fait, nous avons plusieurs listes libres pour différentes tailles de noeud, donc nous avons des listes qui sont alignés sur 2 octets, 4 octets, et 16 limites d'octets (notre plate-forme ne se soucient pas de l'alignement plus d'un vecteur SIMD). Toute allocation s'arrondie à l'une de ces valeurs et mettre dans un nœud correctement aligné. Ainsi, ENVOIEMESS copie toujours ses données dans un nœud aligné. Puisque vous écrivez la liste gratuite vous, vous pouvez facilement appliquer l'alignement.

Nous utiliserons également un #pragma ou declspec à la force que l'omble buf array [MAX_SIZE] pour être aligné sur au moins une limite de mot à l'intérieur de la structure de noeud de queue_t.

Ceci suppose bien sûr que les données d'entrée est aligné, mais si pour une raison quelconque vous passez dans un message que attend pour être (disons) 3 octets hors de l'alignement, vous pouvez toujours détecter que avec un module de retour et un décalage dans le noeud libre.

Avec cette conception sous-jacente, nous avons des interfaces qui prennent en charge à la fois l'option 1 et 2 ci-dessus. Encore une fois, nous condition sine qua non que les données d'entrée est toujours en mode natif aligné, notre dequeue bien sûr renvoie un pointeur aligné; mais si vous avez besoin de données curieusement alignées dans, encore une fois, tout décalage dans le nœud libre et renvoyer le pointeur de décalage.

Cela vous évite de traiter void * s évitant ainsi vos problèmes d'aliasing stricts. (En général, je pense que vous pourriez avoir besoin pour se détendre vos exigences strictes d'aliasing lors de l'écriture de vos propres allocataires de mémoire, puisque par nature, ils brouillent les types en interne.)

Autres conseils

Je ne comprends pas pourquoi 1 présente un problème d'alignement - à condition que chaque élément de buf[MAX_SIZE] est aligné sur le plus grand seul type primitif naturel qui se produit dans votre struct de message (probablement 32 ou 64 bits), il n'a pas d'importance ce que le contenu de chaque type de message est; car il sera toujours aligné à cette taille.

Modifier

En fait, il est encore plus simple que cela. Comme chaque élément dans votre file d'attente de messages est MAX_SIZE en longueur, puis en supposant que vous commencez à chaque message dans sa propre buf (vous ne les emballez pas si un message est

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top