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 :

map d'une zone memoire en tant que fichier sous linux


Sujet :

C

  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Juillet 2004
    Messages
    410
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2004
    Messages : 410
    Points : 361
    Points
    361
    Par défaut map d'une zone memoire en tant que fichier sous linux
    Bonjour,
    Je souhaite faire une opération qui s'apparente a mmap, mais a l'envers.
    En fait, j'ai déjà de la data en mémoire a une adresse allouée dans mon programme. J'aimerais plus tard dans mon programme (dans d'autres routines) attaquer cette zone mémoire a l'aide des posix open,pread,pwrite,close.

    Je ne sais pas ce genre d’opération est possible.
    Est ce que quelqu'un a une idée?
    Merci d'avance.

  2. #2
    Membre expert
    Avatar de Metalman
    Homme Profil pro
    Enseignant-Chercheur
    Inscrit en
    Juin 2005
    Messages
    1 049
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Enseignant-Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 1 049
    Points : 3 532
    Points
    3 532
    Par défaut
    C'est possible il me semble...
    Il te faut peut être une extension spéciale à ton OS pour y accéder.

    Sur les Linux/BSD tu peux te renseigner sur le /dev et ses accès à la mémoire.
    Par exemple il me semble que sous FreeBSD, /dev/mem te permet cela.

  3. #3
    Membre expert
    Avatar de kwariz
    Homme Profil pro
    Chef de projet en SSII
    Inscrit en
    Octobre 2011
    Messages
    898
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Chef de projet en SSII
    Secteur : Conseil

    Informations forums :
    Inscription : Octobre 2011
    Messages : 898
    Points : 3 352
    Points
    3 352
    Par défaut
    Bonsoir,

    pread et pwrite travaillent sur des fichiers et il leur faut un file descriptor.
    Si ton mmap mappe un fichier il n'y pas trop de problèmes (quoique ...). Mais comme tu poses la question je suppose que ton map n'est pas relié à un fichier. Je pense qu'une solution serait de créer un fichier avec le contenu de ton map. Une autre solution serait de créer un fichier au départ avec la bonne taille, le mmaper, utiliser msync le démapper puis utiliser tes routines d'accès au fichier.

    EDIT: en creusant un peu il y a peut-être la possibilité d'utiliser shm_open ... à vérifier.

  4. #4
    Membre averti
    Profil pro
    Inscrit en
    Juillet 2004
    Messages
    410
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2004
    Messages : 410
    Points : 361
    Points
    361
    Par défaut
    Merci pour vos retours.
    En fait, je souhaite éviter d’écrire ce que j'ai en mémoire car ça fait potentiellement plusieurs gigas. Ensuite la raison pour laquelle je souhaite que ce fichier virtuel soit accédé par pread pwrite c'est par ce que pour une couche basse de mes routines, elles font des IO sur un fichier en mode posix pread/pwrite. Donc je voulais juste pouvoir adresser ma mémoire comme un fichier pour ne pas changer le code dans la couche basse.

    Je vais me renseigner sur ce que peut me proposer /dev

  5. #5
    Membre expert
    Avatar de kwariz
    Homme Profil pro
    Chef de projet en SSII
    Inscrit en
    Octobre 2011
    Messages
    898
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Chef de projet en SSII
    Secteur : Conseil

    Informations forums :
    Inscription : Octobre 2011
    Messages : 898
    Points : 3 352
    Points
    3 352
    Par défaut
    Ta question m'a fait un peu chercher dans la doc ...
    shm_open peut certainement résoudre ton problème. Mais cela passe toujours par la création sous-jacente d'un fichier ; c'est plus ou moins transparent de ton point de vue. J'attache un exemple simple mélangeant accès mémoire et par fd.

    mmap.tar.gz

    L'autre solution aurait été d'utiliser fmemopen qui renvoie un stream (FILE*), et comme la man page précise :
    There is no file descriptor associated with the file stream returned by these functions (i.e., fileno(3) will return an error if called on the returned stream).
    je suppose que cela ne t'intéressera pas du tout.

  6. #6
    Membre averti
    Profil pro
    Inscrit en
    Juillet 2004
    Messages
    410
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2004
    Messages : 410
    Points : 361
    Points
    361
    Par défaut
    Ok merci pour ton code.
    Je vais essayer m'en inspirer pour voir si j'arrive a faire la chose suivante:
    • Créer le segment mémoire /dev/shm/blabla a l'aide de shm_open,... et écrire mes data dedans.

    • Puis voir si je peux l'acceder en lecture avec un posix open sur le fichier /dev/shm/blabla en lecture.


    Je test ça dans l'aprem (si je peux).
    merci encore.

  7. #7
    Membre averti
    Profil pro
    Inscrit en
    Juillet 2004
    Messages
    410
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2004
    Messages : 410
    Points : 361
    Points
    361
    Par défaut
    voici ce que j'ai pu obtenir et qui semble fonctionner:

    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
     
    void abort(const char* message)
    {
        perror(message);
        exit(1);
    }
     
    void read_data(const char* filename,int nb_int)
    {
        int data;
     
        int fd=open(filename,O_RDONLY);
     
        for (int i=0; i<nb_int; ++i)
        {
            pread(fd,&data,sizeof(int),sizeof(int)*i);
            printf("data[%d]=%d\n",i,data);
        }
     
        close(fd);
    }
     
    int main(int argc,char* argv[])
    {
        char filename[1024];
        char arraytmp[1024];
        const int nb_int=100;
        const int len=nb_int*sizeof(int);
        int shfd;
        int* buffer;
     
        if ((shfd=shm_open("test_rafix",O_RDWR|O_CREAT,0766))==-1)
            abort("shm_open");
     
        // Read out the link to our file descriptor
        sprintf(arraytmp,"/proc/self/fd/%d",shfd);
        memset(filename,0, sizeof(filename));
        readlink(arraytmp,filename,sizeof(filename)-1);
     
        printf("Filename : %s\n",filename);
     
        if (lseek(shfd,len-1,SEEK_SET)==-1)
            abort("lseek");
     
        if ( write(shfd,"",1)==-1)
            abort("lseek/write");
     
        if ((buffer=(int*)mmap(NULL,len,PROT_READ|PROT_WRITE,MAP_SHARED,shfd,0))==MAP_FAILED)
            abort("mmap");
     
        // from 150 to 249 in buffer
        for (int i=0; i<nb_int; ++i)
            buffer[i]=150+i;
     
        if (msync(buffer,len,MS_SYNC))
            abort("msync");
     
        // Read data in a deep part of the code...
        read_data(filename,nb_int);
     
        munmap(buffer,len);
        close(shfd);
     
        if (shm_unlink(filename)==-1)
            abort("unlink");
     
        return 0;
    }
    Est ce que j'ai l'assurance que shm_open crée bien quelque chose en mémoire et pas sur hard drive? En gros est ce aue /dev/shm c'est de la memoire?
    Je ne suis pas assez bon en linux pour le savoir. Au pire je poserai la question au boulot demain.

    Merci a tous pour votre participation.

  8. #8
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Juin 2009
    Messages
    4 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 481
    Points : 13 678
    Points
    13 678
    Billets dans le blog
    1
    Par défaut
    Salut,

    Juste une petite remarque. Tu peux remplacer :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    char filename[1024];
    memset(filename,0, sizeof(filename));
    par :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    char filename[1024] = {0};
    Voir : http://gradot.wordpress.com/2012/09/...ructures-en-c/


  9. #9
    Membre averti
    Profil pro
    Inscrit en
    Juillet 2004
    Messages
    410
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2004
    Messages : 410
    Points : 361
    Points
    361
    Par défaut
    oui oui ,
    en fait ces trois lignes sont bêtement copiées de google car je cherchais un moyen pour récupérer le filename associé à un file descritor.

    Ceci dit il me suffisait de faire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    sprintf(filename,"/proc/self/fd/%d",shfd);
    La redirection automatique du lien symbolique me permet d'attaquer le fichier.

    Mais merci pour ta remarque.

  10. #10
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Juin 2009
    Messages
    4 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 481
    Points : 13 678
    Points
    13 678
    Billets dans le blog
    1
    Par défaut
    Il est vrai que sprintf() ajoute un \0 à la fin de la chaine. Pas mal de gens ignorent qu'un tableau s'initialise facilement à zéro. Tu aurais pu être de cela mais tu as mieux appris tes leçons

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Representation hexadecimal d'une zone memoire.
    Par etranger dans le forum C++
    Réponses: 6
    Dernier message: 13/03/2007, 14h26
  2. Fixer google map sur une zone précise ?
    Par tlafont dans le forum Général JavaScript
    Réponses: 1
    Dernier message: 05/02/2007, 09h54
  3. Lancer une appli Java en tant que Service Windows
    Par danyboy85 dans le forum Général Java
    Réponses: 4
    Dernier message: 28/09/2006, 12h17
  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, 21h23

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