transférer des fichiers binarys entre systèmes

J’essaie de transférer mes fichiers entre 2 clusters UNIX, les données sont numériques (vecteurs de double) sous forme binary. Malheureusement, l’un des systèmes est IBM ppc997 et l’autre est AMD Opteron. Il semble que le format des nombres binarys dans ces systèmes soit différent.

J’ai essayé 3 façons jusqu’à présent:

1- Changé mes fichiers au format ASCII (c.-à-d. Enregistré un numéro à chaque ligne dans un fichier texte), les a envoyés à la destination et les a changés à nouveau en binary sur le système cible (ils sont tous deux UNIX, pas de différence de fin de ligne?) ?!)

2- Envoyé des binarys purs à la destination

3- uuencode utilisé les a envoyés à la destination et les a décodés

Malheureusement, aucune de ces méthodes ne fonctionne pas (mon code dans le système de destination génère des erreurs, alors que cela fonctionne sur le premier système, je suis sûr à 100% que le code lui-même est portable). Je ne sais pas quoi d’autre je peux faire? Avez-vous une idée? Je ne suis pas un professionnel, veuillez ne pas utiliser la terminologie des informaticiens!

Et: mes codes sont en C, donc en binary, je veux dire un mappage individuel entre la mémoire et le disque dur.

Merci

Le code n’est pas portable à 100% si vous écrivez le contenu de la mémoire dans des fichiers.

Vous avez besoin de quelque chose appelé sérialisation . Ok, terme informatique, mais cela signifie essentiellement que vous obtenez vos données et les transformez en une séquence d’octets bien définie et documentée, qui peut être relue en mémoire plus tard par le même programme ou par un autre. Cette séquence d’octets est indépendante de l’architecture et de la plate-forme.

La plupart des environnements Unix sont déjà livrés avec une implémentation XDR , qui fournit des routines pour la sérialisation des données.

Un exemple simple codant 4 double à stdout (vous pouvez utiliser la redirection de shell ou utiliser fopen () pour ouvrir un fichier au lieu de stdout):

XDR xdrs; double data[4] = { 1.0, 255.41, -357.1, 123.4 }; int i; xdrstdio_create(&xdrs, stdout, XDR_ENCODE); for (i = 0; i < 4; i++) xdr_double(&xdrs, &data[i]); 

Maintenant, pour récupérer ces doublons (à partir de stdin) et les imprimer:

 XDR xdrs; double data; int i; xdrstdio_create(&xdrs, stdin, XDR_DECODE); for (i = 0; i < 4; i++) { xdr_double(&xdrs, &data); printf("%g\n", data); } 

Vous pouvez encoder et décoder des structures complexes en utilisant XDR. C'était un moyen très bête d'envoyer quatre doubles à un fichier, et généralement vous devriez plutôt utiliser xdr_array () pour lire / écrire des tableaux de certains types de données. Les mêmes commandes, dans le même ordre, doivent être exécutées lors de la sauvegarde et lors du chargement du fichier. En fait, vous pouvez utiliser rpcgen pour générer des structures C et leurs fonctions xdr correspondantes automatiquement.

La méthode 1 devrait fonctionner. Créez simplement un vecteur de test avec les valeurs 1, 2, …, 10 et envoyez-le. Vous pouvez lire les fichiers ascii créés (pour pouvoir valider «export») et vérifier également l’étape «importation» de relecture du fichier. Vous pouvez perdre de la précision de cette façon, mais cela devrait vous rendre opérationnel.

La méthode 2 fonctionnera une fois que vous utiliserez une bibliothèque telle que XDR qui traite des différentes endianness. Auparavant, ces problèmes posaient problème et il y a des solutions. Par exemple, comment un système comme R vous permet-il de partager des fichiers binarys entre des architectures.

La méthode 3 n’est pas nécessaire à moins que vous ne fassiez quelque chose de très compliqué lors du transfert du fichier.

Les détails fournis sont rares. Répondre au mieux de ma compréhension.

.. l’un des systèmes est IBM ppc997 et l’autre est AMD Opteron

L’ancien système en général (*) utilise la présentation big-endian, plus tard – little-endian. Lisez ceci .

(*) Cela dépend de l’OS. Le processeur POWER d’IBM peut faire à la fois de petites et de grandes versions, mais aucun système d’exploitation ne fonctionne avec le mode little-endian.

Normalement, pour la présentation binary, on choisit une endianness et on l’accompagne pour la présentation binary. Pour les trucs réseau, la présentation des nombres big-endian est une norme.

Cela signifie tous les endroits qui font quelque chose comme ceci:

 /* writing to binary */ int a = 1234; write(fd,&a,sizeof(a)); /* reading from binary */ int x; read(fd,&x,sizeof(x)); 

devrait être converti en quelque chose comme ceci:

 /* writing to binary */ int a = htonl(1234); write(fd,&a,sizeof(a)); /* reading from binary */ int x; read(fd,&x,sizeof(x)); x = ntohl(x); 

Une autre approche consiste à enregistrer l’indicateur d’endianness (par exemple, écrire de la magie et le vérifier de l’autre côté: MAGIC = 0x12345678 v. MAGIC = 0x78563412) avec les données binarys, et appliquer la conversion uniquement lorsque l’endianness diffère. Bien que cette approche soit moins élégante et n’a aucun réel avantage, j’en suis conscient.

Les solutions 2 et 3 ne fonctionneront généralement pas, car différents processeurs peuvent utiliser différentes représentations internes de vos nombres. Pour les entiers, pas float / double, vous pouvez vous en sortir avec quelque chose qui prend juste en compte l’ordre des octets de vos différentes machines. Les représentations en virgule flottante sont beaucoup plus délicates et vous devez rechercher en détail les représentations que vos différentes architectures utilisent. Mais encore pour le double, par exemple, il n’ya qu’une exigence minimale concernant la précision, et vous pourriez vous retrouver dans une situation où vous devriez tronquer la représentation plus petite des deux. Ces problèmes n’ont pas grand chose à voir avec le système d’exploitation que vous utilisez (Unix ou non) mais avec la façon dont le matériel aime les choses.

Tous les processeurs prenant en charge IEEE 754 ont la même représentation binary pour les flottants (appelés techniquement simples) et doubles. La seule différence sera dans l’endianness du processeur.

La seule incompatibilité entre le IBM PPC et le AMD Opteron devrait donc être la cohérence des doubles.

Lorsque vous remplacez les doubles du disque en mémoire, NE FAITES PAS CECI :

 double swap(double a); // THIS IS NEVER THE RIGHT THING TO DO. 

Passer le double par valeur peut le transmettre via des registres à virgule flottante. Comme toutes les combinaisons de bits ne sont pas des doubles valides, le processeur peut convertir silencieusement le double en un NaN, qui peut avoir une représentation de bits différente de celle transmise. Il est plus probable que cela se produise avec un double valide dans l’ordre inverse . (Voir ici pour une explication plus détaillée.)

En d’autres termes, transmettez le double que vous voulez byteswap en tant que pointeur ou tableau de caractères. (Le tableau de caractères devrait être le meilleur pari.)