Analysis of the Linux kernel container_of macros in a comprehensible instance

Source: Internet
Author: User

    the first thing to do is to know what its purpose is. Container_of's purpose: How to get pointers to the structure itself through a variable in the structure. General idea: Imagine that you have several members in your structure, how do you get the first address of the entire structure through the "any member" inside. Container_of's approach is to define a pointer variable pvar_a the same type as "any member" (assuming the variable name is pvar_a), and have the pointer variable pvar_a point to the "any member" and then Subtract "Pvar_a" by the TypeOf. _a relative to your structure of the offset ", this result corresponds to the address is actually your structure of the first address, and finally the result of the cast to your structure corresponding to the type of OK.offSee kernel.h in container_of:/** * Container_of-cast A member of a structure out to the containing structure * @ptr: The pointer to the MEM    ber.    * @type: The type of the container struct this was 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));})Note: Add a little C to the knowledge of the macro definition, in a macro, if there are multiple statements, the result of the final macro is the value of the last statement, which is a bit like a comma expression.     about Offsetof See stddef.h in:#define OFFSETOF (Type, MEMBER) ((size_t) & ((type *) 0)->member) type is a struct, (type *) 0 is to cast the 0 address to type Struct,member is a member of the struct (you can fully understand what I said above as "any member"). Since the base site of the struct is 0, so the address of the member itself is undoubtedly meant to represent its own address, in addition it also cleverly has another layer meaning that the address value of member is equal to member relative to the struct header address offset, Now you should understand why the (type *)% conversion is not selected (type *) 100, or otherwise.For typeof, this is the C language extension reserved word for GCC, which declares the variable type."Const typeof ((type *) 0->member) *__mptr = (PTR);" means declaring a pointer constant *__mptr the same type as member, and initializing it to PTR. "(Type *) ((char *) __mptr-offsetof (type,member))," means that the address of the __mptr is subtracted from the offset of member in the struct and converted to a type pointer. In fact, the pointer is the entry address of member.
   Here is a new example of my previous online example, which I hope will help the reader:
#include <stdio.h>/* * The CONTAINER_OF and Offsetof macros provided by the kernel cannot be referenced at the application layer  , so you need to define it yourself */#define CONTAINER_OF (PTR, type, member) ({Const typeof (((type *) 0)->member) *__mptr = (PTR); (Type *) ((char *) __mptr-offsetof (Type,member));})#define OFFSETOF (Type, MEMBER) ((size_t) & ((TYPE *) 0)->member)/ * * structure used for testing */struct student{Char name[20];char sex;} stu={"liuhb569620660", ' M '};int main (int argc, char *argv[]) {struct student *stu_ptr;//Store The return value of the CONTAINER_OF macroint offset; //Store The return value of the OFFSETOF macro/  * * The following three lines of code are equivalent to container_of (&stu.sex, struct  student, Sex) *//*A _mptr pointer is defined first, the type of the sex member in the struct student struct, typeof is used to obtain (((struct student*) 0) The type of->sex, where the member type is char, ((struct student*) 0) explain at Offsetof*/Const typeof ((struct student*) 0)->sex) *_mptr = &stu.sex;/*(struct student*) 0) is a 0 address forced into a pointer to the student struct type, the pointer from the 21 bytes of address 0 to hold name and sex, (Note: Char name[20] and char sex a total of 21 bytes), Sex is stored in the 20th byte out (starting at 0 bytes),& ((struct student *) 0)->sex Remove the sex address (this is 20) and force conversion to reshape, so offset is 20, and the following printf results will prove this*/offset = (int) (& (struct student *) 0)->sex);/*((char*) _mptr-offset) Here first convert the _mptr pointer to a character pointer, (why?). If _MPTR is the shaping pointer _mptr-offset equivalent to subtracting sizeof (int) *offset bytes), subtracting the offset value is equivalent to getting the first address of the struct in which the _mptr is located (that is, the address of the Stu), and then we force the address into a struct s Tudent type can be used normally.*/Stu_ptr = (struct student *) ((char*) _mptr-offset);printf ("\n### offsetof stu.sex =%d\n", offset);printf ("# # # stu_ptr->name =%s \ n")"# # # Stu_ptr->sex =%c\n\n", Stu_ptr->name, Stu_ptr->sex);/  * Add verification directly call CONTAINER_OF This macro effect   * //* Find structure first address through sex member */printf ("\n### container_of (&stu.sex, struct student, sex)->name =%s\n", container_of (&stu.sex, struct Student, sex)->name);printf ("# # # container_of (&stu.sex, struct student, sex)->sex =%c\n", container_of (&stu.sex, struct student, Sex)->sex);/* Find struct first address by name member */printf ("\n### container_of (&stu.sex, struct student, sex)->name =%s\n", container_of (stu.name, struct student, name)->name);printf ("# # # container_of (&stu.sex, struct student, sex)->sex =%c\n", container_of (stu.name, struct student, name )->sex);return 0;}
    The example shows the following results:

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.