IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C++ Discussion :

Acces a une zone memoire via un File descriptor sans faire d acces disque


Sujet :

C++

  1. #1
    Membre actif
    Profil pro
    Ingenieur
    Inscrit en
    Décembre 2003
    Messages
    138
    Détails du profil
    Informations personnelles :
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingenieur

    Informations forums :
    Inscription : Décembre 2003
    Messages : 138
    Points : 280
    Points
    280
    Par défaut Acces a une zone memoire via un File descriptor sans faire d acces disque
    Bonjour,

    J ai un programme qui recoit des paquets de donnees et les stocke dans un tableau que je redimensionne au fur a mesure a coup de realloc. Je ne connais pas a l avance le nombre de paquets ni leur taille.
    Dans ce programme j appelle aussi une fonction tierce qui traite des donnees et dont le seul parametre est un file descriptor qui permettra d acceder a ses donnees.
    Actuellement une fois le remplissage de mon tableau effectue j ecris son contenu dans un fichier puis j ouvre ce fichier en lecture pour obtenir un file descriptor que je fournis ensuite a la fonction tierce.

    Cette solution ne me satisfait pas car cela m embete de devoir passer par le disque alors que toutes les donnees sont dispos en memoire dans mon programme.
    Je cherche donc un moyen qui me permettrait d obtenir un file descriptor pour acceder a mon tableau memoire.

    Connaissez vous une telle solution ?

    J ai cherche de mon cote et il semble que mmap soit un bon candidat cependant d apres ce que je comprends de la doc mmap donne un acces via memoire a un fichier du disque. Si je pars d un fichier vide et que je fais un memcpy de mon tableau vers la memoire mmapee j ai l impression que cela fera des acces disques
    Autre solution, la shared memory avec un shm_open . Cependant j aurais besoin la aussi de faire un memcpy de mon tableau vers la shared memory ce que je trouve dommage vu que j ai deja l info en memoire.

    Est ce qu il n existerait pas une solution simple qui me permettrait de creer directement un file descriptor a partir de mon tableau ?

    Je developpe sous Linux mais j aimerais que la solution retenue marche aussi en MinGW sous windows

    PS : je ne veux pas remplacer ma fonction tierce par une autre fonction car je considere que se serait se defiler face au probleme que je pose

    Merci d avance
    Julien

  2. #2
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 382
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 382
    Points : 41 590
    Points
    41 590
    Par défaut
    Tu devrais pouvoir essayer avec un pipe, qui ne devrait pas passer par le disque à moins d'y être obligé.

  3. #3
    Membre actif
    Profil pro
    Ingenieur
    Inscrit en
    Décembre 2003
    Messages
    138
    Détails du profil
    Informations personnelles :
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingenieur

    Informations forums :
    Inscription : Décembre 2003
    Messages : 138
    Points : 280
    Points
    280
    Par défaut
    effectivement j avais pas pense au pipe merci!

    Sinon entretemps on m a parle de cette fonction qui m a l air pas mal:
    http://linux.die.net/man/3/fmemopen

  4. #4
    Expert confirmé

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2007
    Messages
    1 895
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Septembre 2007
    Messages : 1 895
    Points : 4 551
    Points
    4 551
    Par défaut
    Citation Envoyé par quicky2000 Voir le message
    Bonjour,

    J ai un programme qui recoit des paquets de donnees et les stocke dans un tableau que je redimensionne au fur a mesure a coup de realloc. Je ne connais pas a l avance le nombre de paquets ni leur taille.
    Dans ce programme j appelle aussi une fonction tierce qui traite des donnees et dont le seul parametre est un file descriptor qui permettra d acceder a ses donnees.
    Actuellement une fois le remplissage de mon tableau effectue j ecris son contenu dans un fichier puis j ouvre ce fichier en lecture pour obtenir un file descriptor que je fournis ensuite a la fonction tierce.

    Cette solution ne me satisfait pas car cela m embete de devoir passer par le disque alors que toutes les donnees sont dispos en memoire dans mon programme.
    Je cherche donc un moyen qui me permettrait d obtenir un file descriptor pour acceder a mon tableau memoire.

    Connaissez vous une telle solution ?

    J ai cherche de mon cote et il semble que mmap soit un bon candidat cependant d apres ce que je comprends de la doc mmap donne un acces via memoire a un fichier du disque. Si je pars d un fichier vide et que je fais un memcpy de mon tableau vers la memoire mmapee j ai l impression que cela fera des acces disques
    Autre solution, la shared memory avec un shm_open . Cependant j aurais besoin la aussi de faire un memcpy de mon tableau vers la shared memory ce que je trouve dommage vu que j ai deja l info en memoire.

    Est ce qu il n existerait pas une solution simple qui me permettrait de creer directement un file descriptor a partir de mon tableau ?

    Je developpe sous Linux mais j aimerais que la solution retenue marche aussi en MinGW sous windows

    PS : je ne veux pas remplacer ma fonction tierce par une autre fonction car je considere que se serait se defiler face au probleme que je pose

    Merci d avance
    Julien
    Un file descriptor est lié à un objet maintenu par l'OS. Pour avoir un file descriptor qui pointe vers de la mémoire, tu ne peux qu'utiliser les mécanismes de l'OS (FILE* est particulier : le type est géré par la libc - on peut donc implémenter n'importe quel type de stream, y compris des memory stream).

    Si tu veux un fd sur de la mémoire, tu n'as pas trop le choix : il te faut créer une zone de mémoire partagée avec shm_open().

    Par contre, tu peux créer cette zone très tôt - et stocker tes données directement dedans plutôt que de passer par un buffer intermédiaire. Une zone de mémoire partagée peut être agrandie autant que nécessaire, comme avec un realloc (avec ftruncate(), qui a en plus l'avantage d'initialiser la mémoire "ajoutée" à 0).

    Avec un peu d'encapsulation, tu peux trouver ton bonheur. Tu va même y gagner quelque chose : l'adresse virtuelle de ta shm ne va jamais changer (contrairement à ce qui peut se passer lorsque tu utilise realloc() (qui, de toute façon, utilise une shm sous Linux)).

  5. #5
    Membre actif
    Profil pro
    Ingenieur
    Inscrit en
    Décembre 2003
    Messages
    138
    Détails du profil
    Informations personnelles :
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingenieur

    Informations forums :
    Inscription : Décembre 2003
    Messages : 138
    Points : 280
    Points
    280
    Par défaut
    OK, merci pour cette nouvelle piste. je vais tester ca.

    J ai regarde fmemopen et ca marche tres bien sous Linux par contre la fonction n est pas dispo sous MinGW... j ai donc essaye avec des fichiers temporaires memory mappes mais j ai du mal a determiner si ca evite les acces disques ou pas.

    Pour ce qui est du pipe il y a apparemment des limitations lies a l OS sur la taille maxi qu un Pipe peut contenir

  6. #6
    Membre actif
    Profil pro
    Ingenieur
    Inscrit en
    Décembre 2003
    Messages
    138
    Détails du profil
    Informations personnelles :
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingenieur

    Informations forums :
    Inscription : Décembre 2003
    Messages : 138
    Points : 280
    Points
    280
    Par défaut
    Citation Envoyé par Emmanuel Deloget Voir le message
    contrairement à ce qui peut se passer lorsque tu utilise realloc() (qui, de toute façon, utilise une shm sous Linux).
    Tu l as trouve ou cette information ? je suis interesse pour en savoir plus sur cet aspect la

    Je reprecise au passage car je m apercois que c etait peut etre pas tres clair que c est via un FILE* que je voulais avoir acces a la memoire

    En attendant voici le petit test case que j ai ecrit et qui ne fait aucun acces dique:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    #include <string.h>
    #include <stdlib.h>
    #include <stdio.h>
    #include <unistd.h>
    #ifdef _WIN32
    #include "windows.h"
    #include <Fcntl.h>
    #endif
     
    #define MY_TEST_SIZE 1000000
     
    int main(void)
    {
      char * l_buffer = (char*)malloc(MY_TEST_SIZE*sizeof(char));
      memset(l_buffer,0,MY_TEST_SIZE);
      strcpy(l_buffer,"Hello World\nIl fait beau aujourdhui!\n#EOF\nYoupi!\nWindows ca me gave carrement, tout est simple sous Linux alors que sous Windows le moindre truc est super complique et mal document!!!e\n");
      char l_read_buffer[11];
      for(uint32_t l_index = 0 ;l_index < 100 ; ++l_index)
      {
    #ifdef _WIN32
            HANDLE l_file_handle = CreateFile("toto",GENERIC_READ | GENERIC_WRITE,0,0,OPEN_ALWAYS,/*FILE_ATTRIBUTE_NORMAL*/FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_DELETE_ON_CLOSE,NULL);
            printf("l_file_handle = %d\n",l_file_handle);
            if(INVALID_HANDLE_VALUE == l_file_handle)
            {
                    printf("ERROR when opening temporary file\n");
                    exit(-1);
            }
     
            HANDLE l_handle = CreateFileMapping(l_file_handle/*INVALID_HANDLE_VALUE*/,0,PAGE_READWRITE,0,MY_TEST_SIZE,NULL);
            if(INVALID_HANDLE_VALUE == l_handle)
            {
                    printf("ERROR when opening file mapping\n");
                    exit(-1);
            }
     
            LPVOID l_mapped_memory = MapViewOfFile(l_handle,FILE_MAP_WRITE,0,0,0);
            if(l_mapped_memory == NULL)
            {
                    printf("Error when mapping file in memory\n");
                    exit(-1);
            }
            memcpy(l_mapped_memory,l_buffer,MY_TEST_SIZE);
            printf("l_handle = %d\n",l_handle);
     
            // Get the file descriptor from the handle
            int fd = _open_osfhandle((long)l_file_handle, O_RDONLY);
            printf("File descriptor = %d\n",fd);
     
            // Get the handle from the file descriptor
                FILE * l_file = _fdopen(fd,"r");
    #else
      FILE * l_file = fmemopen(l_buffer,MY_TEST_SIZE,"r");
    #endif
      if(NULL == l_file)
        {
          printf("Unable to perform open");
          exit(-1);
        }
      while(!feof(l_file))
        {
          size_t l_read_size = fread(l_read_buffer,11,1,l_file);
          write(1,l_read_buffer,11);
        }
    #ifdef _WIN32
      UnmapViewOfFile(l_mapped_memory);
      CloseHandle(l_handle);
      CloseHandle(l_file_handle);
    #else
      fclose(l_file);
    #endif
      }
      free(l_read_buffer);
      free(l_buffer);
    }

  7. #7
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 382
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 382
    Points : 41 590
    Points
    41 590
    Par défaut
    Si tu veux un FILE* plutôt qu'un descripteur, utilise tout simplement tmpfile().
    Cette fonction passe les bons flags à CreateFile() pour éviter les accès disques (FILE_FLAG_DELETE_ON_CLOSE | FILE_ATTRIBUTE_TEMPORARY).

    Edit: Euh, en fait non, dans la version 8 de la CRT (Visual 2005) elle ne passe que le premier flag. Bizarre.
    Par contre, tu dois pouvoir utiliser fopen() en rajoutant simplement les flags T et D à la fin (exemple: fopen("nom_du_fichier", "wb+TD"))

    PS: Je ne suis pas sûr qu'_open_osfhandle sur un handle de File Mapping te permette d'utiliser les fonctions d'écriture/lecture de flux...

  8. #8
    Expert confirmé

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2007
    Messages
    1 895
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Septembre 2007
    Messages : 1 895
    Points : 4 551
    Points
    4 551
    Par défaut
    Citation Envoyé par quicky2000 Voir le message
    Tu l as trouve ou cette information ? je suis interesse pour en savoir plus sur cet aspect la
    ici

    (et puis un peu l'expérience, aussi )

  9. #9
    Expert éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 196
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 196
    Points : 17 165
    Points
    17 165
    Par défaut
    bonne réponse

Discussions similaires

  1. acces impossible à une base MySQL via ODBC en déporté
    Par alakauf dans le forum Bases de données
    Réponses: 5
    Dernier message: 09/03/2018, 19h48
  2. Alimenter une zone texte via une zone déroulante
    Par ecolom dans le forum Général JavaScript
    Réponses: 12
    Dernier message: 27/04/2009, 17h12
  3. Representation hexadecimal d'une zone memoire.
    Par etranger dans le forum C++
    Réponses: 6
    Dernier message: 13/03/2007, 15h26
  4. Rendre une zone memoire accessible a un autre processus
    Par Jack_serious dans le forum POSIX
    Réponses: 12
    Dernier message: 07/12/2005, 22h23

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo