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 :

container_of dans kernel.h


Sujet :

C

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Futur Membre du Club
    Inscrit en
    Octobre 2006
    Messages
    4
    Détails du profil
    Informations forums :
    Inscription : Octobre 2006
    Messages : 4
    Par défaut container_of dans kernel.h
    Bonjour, je suis en train d'étudier la gestion des listes chaînées sous linux (list.h) et on se rend compte qu'il y a une macro "container_of".

    Cette macro est définie dans "kernel.h" mais je n'arrive pas à comprendre son fonctionnement et particulierement le "((type *)0)->member )" il semblerait qu'on cast 0 mais dans quelle utilité ?

    Pouvez-vous m'indiquer, s'il vous plait, le fonctionnement de cette macro.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    /**
     * container_of - cast a member of a structure out to the containing structure
     *
     * @ptr:        the pointer to the member.
     * @type:       the type of the container struct this is embedded in.
     * @member:     the name of the member within the struct.
     *
     */
    #define container_of(ptr, type, member) ({			\
            const typeof( ((type *)0)->member ) *__mptr = (ptr);	\
            (type *)( (char *)__mptr - offsetof(type,member) );})
    J'ai une autre question, pour ne pas utiliser les pointeurs NULL, ils utilisent deux pointeurs, je comprends pas le choix de ces adresses spécifiquement et le danger du pointeur NULL.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    /*
     * These are non-NULL pointers that will result in page faults
     * under normal circumstances, used to verify that nobody uses
     * non-initialized list entries.
     */
    #define LIST_POISON1  ((void *) 0x00100100)
    #define LIST_POISON2  ((void *) 0x00200200)
    Merci.

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

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 395
    Par défaut
    container_of() : J'ai du mal à comprendre, car je ne connais pas ce que fait typeof, ni trop comment cette syntaxe peut marcher :
    Pour moi, un compilateur est supposé rejeter ceci. Mais je ne connais pas aussi bien la norme qu'Emmanuel.

    Pour les autres macros, c'est simple: Cala sert à détecter les pointeurs non-initialisés d'une liste, donc on ne peut pas utiliser NULL car NULL est sans doute une valeur valide pour initialiser...
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  3. #3
    Membre éclairé Avatar de telliam
    Inscrit en
    Octobre 2006
    Messages
    63
    Détails du profil
    Informations forums :
    Inscription : Octobre 2006
    Messages : 63
    Par défaut
    Citation Envoyé par Médinoc
    container_of() : J'ai du mal à comprendre, car je ne connais pas ce que fait typeof, ni trop comment cette syntaxe peut marcher :
    Pour moi, un compilateur est supposé rejeter ceci. Mais je ne connais pas aussi bien la norme qu'Emmanuel.
    pour moi, x=({a;b}); aura comme effet x=b;

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

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 395
    Par défaut
    En C++, typeof( ((type*)NULL)->member ) aurait sans doute été remplacé par un typeof( type::member ). Je suppose que comme sizeof(), typeof() n'évalue jamais l'expression.

    On aurait pu remplacer le tout par void* et la macro aurait toujours marché, mais on n'aurait plus de contrôle de type... (qui vérifie que ptr est bien du type typeof(member) *)
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  5. #5
    Membre éclairé Avatar de telliam
    Inscrit en
    Octobre 2006
    Messages
    63
    Détails du profil
    Informations forums :
    Inscription : Octobre 2006
    Messages : 63
    Par défaut
    Citation Envoyé par Médinoc
    En C++, typeof( ((type*)NULL)->member ) aurait sans doute été remplacé par un typeof( type::member ). Je suppose que comme sizeof(), typeof() n'évalue jamais l'expression.

    On aurait pu remplacer le tout par void* et la macro aurait toujours marché, mais on n'aurait plus de contrôle de type... (qui vérifie que ptr est bien du type typeof(member) *)
    void* beurk ,c'est qd mm plus propre d'utiliser le bon type qd tu utilises un pointeur.

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

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 395
    Par défaut
    Si typeof est standard, OK.
    Sinon, c'est un argument en faveur du void*...
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  7. #7
    Membre éclairé Avatar de telliam
    Inscrit en
    Octobre 2006
    Messages
    63
    Détails du profil
    Informations forums :
    Inscription : Octobre 2006
    Messages : 63
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    /**
     * container_of - cast a member of a structure out to the containing structure
     *
     * @ptr:        the pointer to the member.
     * @type:       the type of the container struct this is embedded in.
     * @member:     the name of the member within the struct.
     *
     */
    #define container_of(ptr, type, member) ({			\
            const typeof( ((type *)0)->member ) *__mptr = (ptr);	\
            (type *)( (char *)__mptr - offsetof(type,member) );})
    Je vais essayer d'expliquer ce que j'ai compris :
    1er ligne :
    ((type*)0)->member : on veut récupérer le champ member d'une structure type mais vu qu'on a pas de variable de ce type la sous la main ( et qu'on peut s'en passer) on caste l'adresse 0 comme si il y avait une variable à cette adresse la ( en plus,en 0 on est , dans les plupart des systemes, sur qu'il y a rien).
    Ensuite on applique typeof sur ce membre pour récupérer son type, ce qui permet de créér un pointeur __mptr contenant l'addresse ptr.

    2eme ligne :
    offsetof(type,member) permet de récupérer l'offset du champ member dans uns structure de type type. On retire ce décalage à l'adresse __mptr pour récupérer le container. CCQFD

  8. #8
    Expert confirmé
    Avatar de Thierry Chappuis
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Mai 2005
    Messages
    3 499
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : Suisse

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Industrie Pharmaceutique

    Informations forums :
    Inscription : Mai 2005
    Messages : 3 499
    Par défaut
    Salut,

    On a eu une discussion tout récemment sur ce sujet. Tu peux lire le post:
    http://www.developpez.net/forums/sho...d.php?t=234455

    Sinon, un excellent article traite de ceci dans GNU Linux Magazine France du mois de septembre. Mais l'essentiel est dans le post référencé ci-dessus.

    Mujigkalement

    Thierry
    "The most important thing in the kitchen is the waste paper basket and it needs to be centrally located.", Donald Knuth
    "If the only tool you have is a hammer, every problem looks like a nail.", probably Abraham Maslow

    FAQ-Python FAQ-C FAQ-C++

    +

Discussions similaires

  1. Observer des points dans l'espace kernel (gaussien)
    Par acx01b dans le forum Téléchargez
    Réponses: 0
    Dernier message: 29/04/2010, 01h44
  2. liste chainée dans la programmation kernel
    Par rufa11 dans le forum Debian
    Réponses: 0
    Dernier message: 09/02/2009, 23h12
  3. Changer version du Kernel dynamiquement (dans un chroot)
    Par asher256 dans le forum Administration système
    Réponses: 3
    Dernier message: 04/01/2008, 15h39
  4. sous-section Linux Kernel dans la section développement Linux
    Par kromartien dans le forum Evolutions du club
    Réponses: 1
    Dernier message: 13/04/2007, 09h36
  5. Bug dans unstable => Kernel Panic
    Par Tchetch dans le forum Debian
    Réponses: 1
    Dernier message: 11/01/2007, 12h18

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