Container_of Macro Analysis

Source: Internet
Author: User

Container_of Macro Analysis
// The macro is located in include/Linux/kernel. h.

1. Define the format

/**

* 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 ));})

Function: obtains the pointer to the entire struct Variable Based on the pointer of a domain member variable in a struct variable.

Example:

Struct demo_struct

{

Type1 member1;

Type2 member2;

Type3 member3;

}

Struct demo_struct demo1, * pdemo;

Type2 * demo_member2 = demo1.member2;

To get the pointer of demo1, you can use this macro:

Pdemo = container_of (demo_member2, struct demo_struct, member2 );

2. Macro Operation Mechanism Analysis

Typeof is an extension of gnu c to Standard C. It is used to obtain the type of a Variable Based on the variable. Expand the macro in the preceding example according to the macro definition, as shown below:

1 pdemo = ({\

2 const typeof (struct demo_struct *) 0)-> member2) * _ mptr = (demo_member2 );\

3 (struct demo_struct *) (char *) _ mptr-offsetof (struct demo_struct, member2 ));\

4 })

From the above definition, the function of line 2nd in the code is to first use typeof to obtain the type of the struct domain variable member2 as type2, and then define a Temporary Variable _ mptr of the type2 pointer type, assign the value of demo_member2, the pointer to the domain variable in the actual struct variable, to the Temporary Variable _ mptr.

The 2nd line of code is similar to the following definition:

Const type2 * _ mptr = demo_member2;

Here (struct demo_struct *) 0) is clever. It refers to the address of the struct demo_struct Variable Based on the address. The address with the offset of 0 is actually the address of the struct demo_struct variable.

In the code of Row 3, (char *) _ mptr is converted to a byte pointer. (Char *) _ mptr-offsetof (type, member) is used to find the starting address of the struct (char * pointer), and then (type *) (char *) _ mptr-offsetof (type, member) converts the starting pointer of a byte struct to the starting pointer of A type * struct under the action of (type.

The offsetof macro is defined as follows:

# Define offsetof (type, member) (size_t) & (type *) 0)-> Member)

The macro calculates the base address of the Member member in the type variable. The macro operation mechanism is as follows:

L (type *) 0) converts zero to type pointer;

L (type *) 0)-> data member in the member access structure;

L & (type *) 0)-> member) retrieves the address of the data member;

L (size_t) (& (type *) 0)-> member) result conversion type.

This macro cleverly converts 0 to (type *). If the struct uses the first address 0 of the memory space as the starting address, the Member Address is naturally an offset address;

_ Mptr-offsetof (struct demo_struct, member2)

Type1 member1

Type2 member2



Type3 member3

Offsetof (type, member) _ mptr

_ Mptr-offsetof (struct demo_struct, member2)

Type1 member1

Type2 member2



Type3 member3

Offsetof (type, member) _ mptr


 

Another article

In the Linux kernel, we often see container_of, which is also a luxury of Linux. The role of container_of is described on page 132 of Linux device driver development; the pointer of the struct member is found. However, it does not analyze how it is implemented.

Next let's take a look at the definition of this macro:

/**

* 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 ));})


The PTR parameter is the pointer of the member Member of the struct typ. We often want to get the starting address of the struct type, that is, the type pointer.

 

Assume that the storage model of this type in the memory is as follows:

Type
| ---------- |
|
|
| ---------- |

PTR-> | member -- |
| ---------- |
|
|
| ---------- |


Here, we can take it apart to understand:

First, (type *) 0 is a pointer to convert the 0 address to the type structure (here, it is the same to change 0 to other values );

(Type *) 0)-> Members of the member type struct;

Typeof (type *) 0)-> member) returns the type of member;

Const typeof (type *) 0)-> member) * _ mptr = (PTR); Use the above type to define a pointer _ mptr, and assign the PTR value to it;

(Char *) _ mptr converts _ mptr into a char pointer;

The offsetof macro is defined in [INCLUDE/Linux/stddef. H]:
# Define offsetof (type, member) (size_t) & (type *) 0)-> Member)
Here, we will describe this macro. (size_t) & (type *) 0)-> member) converts the 0 address to a pointer of the type structure, obtain the pointer of the Member member in the structure and forcibly convert it to the size_t type. Therefore, since the structure is defined from 0, the obtained member Member Address is actually its offset in the structure. This also shows the powerful pointer in C language. Because, for libc implemented under a certain architecture, the offset of each member in the structure is always foreseeable.

Now, with the offset of the Member member in the type struct and the pointer _ mptr pointing to the member, the starting address of the type structure can be calculated.
A small macro contains so many excellent elements that it can be seen that Linux is very broad.

Container_of Macro Analysis

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.