In the process of learning the Linux driver, I encountered a macro called container

  
 

This macro is defined in include/linux/kernel.h, first to post its code:

/** * container_of - cast a member of a structure out to the containing structure * @ptr * @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) );} )

It's obvious that it's a pointer to a domain member variable in a structure variable to get a pointer to the entire structure variable. For example, there is a structure variable defined as follows:

struct demo_struct { type1 member1; type2 member2; type3 member3; type4 member4; }; struct demo_struct demo; meanwhile, in another place, the variable demo is obtained A pointer to a domain member variable, for example: type3 *memp = get_member_pointer_from_somewhere(); At this point, if we need to get a pointer to the entire structure variable, not just a pointer to one of its domain member variables, we can To do this: struct demo_struct *demop = container_of(memp, struct demo_struct, member3); Thus, we get a pointer to the entire struct variable through a pointer to a domain member variable of the struct variable. Let me talk about my understanding of the implementation of this container_of: First, we expand container_of(memp, struct demo_struct, type3) according to the definition of the macro as follows: struct demo_struct *demop = ({ \\ const typeof( (struct demo_struct * )0)->member3 ) *__mptr = (memp); \\ (struct demo_struct *)( (char *)__mptr - offsetof(struct demo_struct, member3) );}) where typeof is an extension of GNU C to standard C Its role is to get the type of the variable based on the variable. Therefore, the second line in the above code is to first use typeof to get the type of the structure body variable member3 as type3, then define a temporary variable __mptr of type3 pointer type, and the domain variable in the actual structure variable The value of the pointer memp is assigned to the temporary variable __mptr.

(char *)__mptr is converted to a byte pointer. (char *)__mptr - offsetof(type,member) ) is used to find the starting address of the structure (for char * pointers), then (type *)( (char *)__mptr - offsetof(type,member) ) Under the action of (type *), the start pointer of the structure of the byte structure is converted to the start pointer of the structure of type *.

Assuming the position of the structure variable demo in real memory is as shown below: demo+-------------+ 0xA000

Copyright © Windows knowledge All Rights Reserved