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 :

Différence entre mmap() et read()


Sujet :

C

  1. #1
    Membre du Club
    Homme Profil pro
    Inscrit en
    Août 2013
    Messages
    274
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Août 2013
    Messages : 274
    Points : 56
    Points
    56
    Par défaut Différence entre mmap() et read()
    Bonjour à tous,

    voila si je veux lire un fichier je peux faire :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    int fd = open("fichier_a_lire.txt", O_RDONLY);
    et ensuite je peux faire :
    ou faire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    void* addr = mmap(NULL,length_of_fichier_a_lire,…, fd, 0);
    strncpy( buffer, addr, 256);
    mais c'est quoi le mieux?
    dans les deux cas le fichier est chargé en RAM par le noyau via l'appel système open, donc pourquoi s’embêter avec mmap ?

    merci de vos éclaircissements

  2. #2
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 689
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 689
    Points : 30 983
    Points
    30 983
    Billets dans le blog
    1
    Par défaut
    Bonjour
    Citation Envoyé par cosmoff Voir le message
    dans les deux cas le fichier est chargé en RAM par le noyau via l'appel systeme open
    Perdu

    Quand tu lis un fichier via open(), une partie du fichier est chargée en mémoire pour économiser les accès disques (bufferisation) donc les lectures suivantes se font depuis le buffer mémoire ok. Mais déjà la bufferisation ne concerne qu'une portion du fichier (portion équivalente à la taille du buffer) et d'autre part, du point de vue programme, la lecture par read(), même si elle est faite depuis le buffer, est quand-même considérée comme se faisant depuis un fichier disque.

    Bien entendu, si le fichier est assez petit, alors effectivement la différence devient négligeable (si tout le fichier est chargé dans le buffer les read seront très rapide) mais tu ne peux pas implémenter un choix technique en te fondant sur la chance.

    Donc si ton algorithme n'a besoin que d'un caractère, ou 10 ou 100 en séquentiel, alors tu pars sur open()+read() et si ton algo a besoin de tout le fichier en RAM, alors nmap(). Mais dans ce cas il faut vraiment que le besoin soit réellement justifié (comme par exemple tu as besoin de te ballader super souvent et super rapidement à différentes positions du fichier aussi bien avant que arrière) parce que charger tout un fichier en RAM ça peut vite devenir gourmand...
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  3. #3
    Expert confirmé
    Inscrit en
    Mars 2005
    Messages
    1 431
    Détails du profil
    Informations forums :
    Inscription : Mars 2005
    Messages : 1 431
    Points : 4 182
    Points
    4 182
    Par défaut
    Justement, ou alors je n'ai pas saisi ce que tu as exprimé Sve@r : l'intérêt d'mmap un fichier est de produire une vue de son contenu en mémoire système. Cela permet à l'application de faire comme si elle disposait d'un buffer gigantesque alors que le kernel réalise une transposition d'adresse et charge et décharge à la volée les pages requises.

    Lorsque l'on read, les données sont a priori réellement chargées en mémoire.

  4. #4
    Responsable Systèmes


    Homme Profil pro
    Gestion de parcs informatique
    Inscrit en
    Août 2011
    Messages
    17 446
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Gestion de parcs informatique
    Secteur : High Tech - Matériel informatique

    Informations forums :
    Inscription : Août 2011
    Messages : 17 446
    Points : 43 090
    Points
    43 090
    Par défaut
    mmap permet de charger un fichier complet dans l'espace d'adressage d'un processus. L’intérêt par rapport à fopen/read est de pouvoir se balader comme on veut dedans. Pour des fichiers standards, l’intérêt est faible, surtout que je pense que mmap utilise le système du copy on write ce qui peut être dangereux en cas d'erreur IO, plus facilement contrôlable par la famille des fonctions fopen/fread.

    L’intérêt de mmap est aussi de pouvoir changer les droits d'accès lors du chargement (exemple zone de code au lieu de données), nécessaire pour charger du code exécutable par exemple. Les fonctions execve utilisent mmap (la page de man fait référence à exec, et fork notamment)

    Tu peux considérer mmap comme une façon exotique de charger un fichier en mémoire. A ne pas faire si on ne maitrise pas ce qu'on fait.
    Ma page sur developpez.com : http://chrtophe.developpez.com/ (avec mes articles)
    Mon article sur le P2V, mon article sur le cloud
    Consultez nos FAQ : Windows, Linux, Virtualisation

  5. #5
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 689
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 689
    Points : 30 983
    Points
    30 983
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par Matt_Houston Voir le message
    Lorsque l'on read, les données sont a priori réellement chargées en mémoire.
    Oui parce que le read() est limité à 32767 caractères donc ces 32767 caractères sont réellement chargés dans la RAM. Alors que le fichier chargé par mmap() est probablement chargé dans la RAM+SWAP.

    Mais j'ai aussi parlé de "se ballader super souvent et super rapidement à différentes positions du fichier aussi bien avant que arrière". Si ton fichier est chargé en RAM (que ce soit en vraie RAM ou en SWAP pour le programmeur ça reste de la RAM), tu peux traiter le premier caractère, puis le dernier, puis le second, puis l'avant-dernier et etc (par exemple : tester que le contenu d'un fichier est un palindrome).
    Tu peux obtenir le même résultat à base de tell() + seek() + read() mais ça sera 1000 fois plus long (ne serait-ce par exemple; que parce que le fichier est trop gros pour tenir entièrement dans le buffer donc si tu lis le premier caractère, puis le dernier, puis le second et etc alors à chaque lecture le fichier sera réellement pris depuis le disque dur).
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  6. #6
    Membre du Club
    Homme Profil pro
    Inscrit en
    Août 2013
    Messages
    274
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Août 2013
    Messages : 274
    Points : 56
    Points
    56
    Par défaut
    merci beaucoup pour vos réponses tres completes.

    donc quand je fais open(), le noyau va juste regarder si le fichier existe et mettre à jour sa table de descriptor de fichier, il ne charge pas le fichier en RAM. Il ne charge les data que lorsque je fais un read(fd, buffer, 256), et il charge un nombre de caractere correspondant à 256 dans mon exemple

  7. #7
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 689
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 689
    Points : 30 983
    Points
    30 983
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par cosmoff Voir le message
    donc quand je fais open(), le noyau va juste regarder si le fichier existe et mettre à jour sa table de descriptor de fichier,
    Probablement (encore que le fichier peut ne pas exister et sera créé si tu as demandé l'option "O_CREAT")...

    Citation Envoyé par cosmoff Voir le message
    il ne charge pas le fichier en RAM.
    Là c'est sûr que non

    Citation Envoyé par cosmoff Voir le message
    Il ne charge les data que lorsque je fais un read(fd, buffer, 256), et il charge un nombre de caractere correspondant à 256 dans mon exemple
    Exact. Même s'il est quasi certain qu'il va en charger beaucoup plus dans le buffer IO en prévision des read() suivants, toi (progammeur) tu n'en as que 256 à ta disposition immédiate.
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  8. #8
    Expert confirmé
    Inscrit en
    Mars 2005
    Messages
    1 431
    Détails du profil
    Informations forums :
    Inscription : Mars 2005
    Messages : 1 431
    Points : 4 182
    Points
    4 182
    Par défaut
    Je ne te suis pas Sve@r. Lorsque tu mmap le fichier, la présence réelle des données en mémoire système est entièrement à la discrétion du kernel. Tu pourrais très bien lire ou écrire partout dans le fichier de manière aléatoire - c'est d'ailleurs un cas d'usage bien connu de mmap - en ne disposant à tout moment que d'une seule page chargée en mémoire, et ce serait tout aussi transparent pour l'application (exceptées les horrible perfs qui en découleraient ). Quant à parler de swap, c'est incongru ici.

    Je n'ai pas connaissance de cette limite de 2^15 pour read, c'est sensé être quoi ? La taille du buffer ? Je serais surpris que POSIX impose un truc aussi arbitraire.

  9. #9
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 689
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 689
    Points : 30 983
    Points
    30 983
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par Matt_Houston Voir le message
    Lorsque tu mmap le fichier, la présence réelle des données en mémoire système est entièrement à la discrétion du kernel. Tu pourrais très bien lire ou écrire partout dans le fichier de manière aléatoire
    Oui, ça rejoint ce que j'ai dit quand je parlais de "se ballader super souvent et super rapidement à différentes positions du fichier aussi bien avant que arrière"...

    Citation Envoyé par Matt_Houston Voir le message
    Quant à parler de swap, c'est incongru ici.
    Euh... si le fichier est super gros, fatalement la RAM sera swappée. Comme le PO parlait aussi de perfs comparatives, j'ai juste voulu aussi rappeler que même la RAM peut aussi nécessiter des accès disques (tout comme j'ai aussi voulu rappeler que même les demandes d'accès disques peuvent en réalité se faire en RAM quand j'ai parlé de bufferisation). Le yin et le yang quoi...

    Citation Envoyé par Matt_Houston Voir le message
    Je n'ai pas connaissance de cette limite de 2^15 pour read, c'est sensé être quoi ? La taille du buffer ? Je serais surpris que POSIX impose un truc aussi arbitraire.
    Alors ça ça date de l'époque où je travaillais sur Unix et j'avais remarqué cette limitation. Effectivement je viens de tester, sur un Linux j'ai lu 50000 sans souci (n'ai pas cherché plus haut). Mais c'est pas tout à fait arbitraire (plus grande valeur d'un short signé).

    Toutefois le man de read parle de SSIZE_MAX comme limitation de la valeur "count" et j'ai trouvé un "_POSIX_SSIZE_MAX" valant 32767 dans "/usr/include/x86_64-linux-gnu/bits/posix1_lim.h" (mais j'ai pas réussi à trouver si "SSIZE_MAX" utilisait ce "_POSIX_SSIZE_MAX" à un moment ou un autre...
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  10. #10
    Expert confirmé
    Inscrit en
    Mars 2005
    Messages
    1 431
    Détails du profil
    Informations forums :
    Inscription : Mars 2005
    Messages : 1 431
    Points : 4 182
    Points
    4 182
    Par défaut
    Citation Envoyé par Sve@r Voir le message
    Euh... si le fichier est super gros, fatalement la RAM sera swappée. Comme le PO parlait aussi de perfs comparatives, j'ai juste voulu aussi rappeler que même la RAM peut aussi nécessiter des accès disques (tout comme j'ai aussi voulu rappeler que même les demandes d'accès disques peuvent en réalité se faire en RAM quand j'ai parlé de bufferisation). Le yin et le yang quoi...
    On se comprend pas. Peu importe que le fichier occupe 64 octets ou 64 GiB, puisque son adressage est totalement virtuel. C'est ce qu'expliquait également chrtophe. En théorie tu pourrais le mmapper sur une machine avec 4 MiB de RAM.

Discussions similaires

  1. Différences entre Delphi et Visual Basic ?
    Par Anonymous dans le forum Débats sur le développement - Le Best Of
    Réponses: 75
    Dernier message: 30/03/2009, 20h09
  2. La difference entre XSL et XSLT?
    Par pantin dans le forum XSL/XSLT/XPATH
    Réponses: 3
    Dernier message: 27/06/2003, 15h14
  3. Difference entre fenetre et boite de dialog
    Par billyboy dans le forum Windows
    Réponses: 2
    Dernier message: 02/06/2003, 15h43
  4. [] Difference entre MSHFlexGrid et MSFlexGrid
    Par olivierx dans le forum VB 6 et antérieur
    Réponses: 6
    Dernier message: 23/04/2003, 08h48
  5. Difference entre types d'Adresse IP
    Par freud dans le forum Développement
    Réponses: 3
    Dernier message: 02/03/2003, 02h06

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