in linux/include/linux/list.h I found:
/**
* list_entry - get the struct for this entry
* #ptr: the &struct list_head pointer.
* #type: the type of the struct this is embedded in.
* #member: the name of the list_head within the struct.
*/
#define list_entry(ptr, type, member) \
container_of(ptr, type, member)
What do they mean by "get the struct for this entry" can I see a usage example to understand in a better way?
This is a great example of a kind of Polymorphism in C. To borrow terminology from C++, the list_entry() macro allows you to downcast from a list_head type to any type that contains it.
Have a look at kthread.c for a simple fundamental example:
kernel/kthread.c:
struct kthread_create_info
{
/* Information passed to kthread() from kthreadd. */
int (*threadfn)(void *data);
void *data;
int node;
/* Result passed back to kthread_create() from kthreadd. */
struct task_struct *result;
struct completion *done;
struct list_head list;
};
...
int kthreadd(void *unused)
{
...
while (!list_empty(&kthread_create_list)) {
struct kthread_create_info *create;
create = list_entry(kthread_create_list.next,
struct kthread_create_info, list);
...
create_kthread(create);
By including a list_head object in the kthread_create_info struct, you can say that kthread_create_info "derives" from list_head. This allows kthread_create_info objects to be used as nodes in a list, meaning you can pass them to any of the functions declared in list.h by simply dereferencing the list member of the struct. The list_entry macro then gives you the mapping from a base class pointer to its derived start address.
In other words, given a list_head object that you know is contained within an outer kthread_create_info struct, you can recover a pointer to the kthread_create_info container.
This is an extremely common pattern in C programming, where object oriented constructs are desired, but a C++ compiler isn't available.
Related
I saw an interesting design for a doubly-linked-list inside the Pintos operating system and I don't quite understand how it was able to achieve this behavior. I wrote a small adaptation to demo what I'm referring to.
#include <stdio.h>
#include <stdint.h>
#include "list.h"
struct foo {
int x;
struct list_node node;
};
int main()
{
struct list list;
list_initialize(&list);
struct foo n1 = {1, NULL};
list_push_back(&list, &n1.node);
struct list_node *e = list_get_front(&list);
struct foo *ptr = list_entry(e, struct foo, node);
printf("%d", ptr->x);
return 0;
}
In essence, list.h implements two structures; namely, list and list_node. A list can be made for any arbitrary struct so long as the struct includes a list_node field. A reference to the structure can be returned by passing a pointer to it's list_node using the following macro defined in list.h.
#define list_entry(LIST_NODE, STRUCT, MEMBER) \
((STRUCT *) ((uint8_t *) &(LIST_NODE)->next \
- offsetof (STRUCT, MEMBER.next)))
The list_node struct declares a known field name, that is used to develop the result.
The key is found in the expression:
(uint8_t *)&(LIST_NODE)->next - offsetof (STRUCT, MEMBER.next)
offsetof() gives the offset in bytes of the specified field in the specified struct.
(uint8_t *)&(LIST_NODE)->next returns a byte pointer, that points to (the beginning of) the specified member of the specified node.
When you subtract the byte offset of the field from the pointer to the field, you get a byte pointer to (the beginning of) the struct.
The macro then casts this to a pointer to the struct.
I was looking at Glibc codes. Some codes of glibc's queue caught my attention. I couldn't give a meaning to this struct definition. This struct doesn't have a name. Why? How does it work?
#define LIST_ENTRY(type) \
struct { \
struct type *le_next; /* next element */ \
struct type **le_prev; /* address of previous next element */ \
}
Source
That is actually a preprocessor macro, that could be expanded (most probably with trailing name) somewhere else.
In the comments at the start of that header file there is a reference to queue(3) man page that contains more details on that and other macros:
The macro LIST_ENTRY declares a structure that connects the elements
in the list.
And an example of use:
LIST_HEAD(listhead, entry) head = LIST_HEAD_INITIALIZER(head);
struct listhead *headp; /* List head. */
struct entry {
...
LIST_ENTRY(entry) entries; /* List. */
...
}
*n1, *n2, *n3, *np, *np_temp;
LIST_INIT(&head); /* Initialize the list. */
n1 = malloc(sizeof(struct entry)); /* Insert at the head. */
LIST_INSERT_HEAD(&head, n1, entries);
Being this C code (not C++), and C lacks templates, this preprocessor macro can be used to "simulate" templates (note the type parameter).
It's a macro that is used to declare a struct type, with next and prev pointers to instances of a second struct type. That second type can be a parent type, so you can make a "linkable struct" like this:
struct foo {
LIST_ENTRY(foo) list;
int value;
};
This creates a struct foo containing a member called list which in turn is the structure in the question, with the pointers pointing at struct foo.
We can now create a little linked list of struct foos like so:
struct foo fa, fb;
fa.value = 47;
fa.list.le_next = &fb;
fa.list.le_prev = NULL;
fb.value = 11;
fb.list.le_next = NULL;
fb.list.le_prev = &fa.list.le_next;
I'm not 100% sure about the last line, but I think it kind of makes sense.
In the below code,
/**********linkedListImpl.c ***********/
#include"list/list.h"
#if defined(LINKED_LIST)
/***************** Representation - start ******************/
/* struct members are not visible to other .c files */
static struct DListNode{
void *item;
struct DListNode *next;
struct DListNode *prev;
};
/* Should be used in this .c file, only, so static */
static typedef struct DListNode DListNode;
static DListNode* createNode(void *);
static struct List{
DListNode *head;
int size; /*size attribute is not part of list definition, but quick way
to help user code */
}List;
.....
#endif
/************ list.h ************/
#ifndef LIST_H /* Header guard */
#define LIST_H
#include"type.h"
/***************** Usage-start ************/
#if defined(ARRAY) || (LINKED_LIST)
typedef struct List List;
#else
#error "Wrong list implementation macro name !!!"
#endif
...
#endif /* LIST_H */
List type is declared in list.h, using staticspecifier,
typedef struct List List;
and defined in linkedListImpl.c, using staticspecifier,
static struct List{
DListNode *head;
int size;
}List;
Purpose: To make List symbol available to user(main.c) only through a pointer(List*). User(main.c) should not be able to access List members in main.c.
In linkedListImpl.c Symbol DListNode is defined using static specifier,
static struct DListNode{
void *item;
struct DListNode *next;
struct DListNode *prev;
};
static typedef struct DListNode DListNode;
Purpose: For symbol DListNode, user(main.c) should neither be able to access DListNode members in main.c nor access DListNode object through DListNode* pointer.
Is this the right approach to hide the symbols List & DListNode?
Note: Here is the complete code
Yes, this is it. It is called opaque pointer, and is used to hide the implementation details in the interface.
You may be interested by What is an opaque pointer in C?
static struct DListNode { ... }; is useless (it declares no variables of struct DListNode), but do declare the struct DListNode so is exactly the same as simply struct DListNode { ... };. It is like static int; declaring a list of 0 integer variables (notice that static int x,y; is a common way of declaring a list of two variables x & y).
A very common way is to define all your struct (and their fields) in public header files. Indeed, you are showing implementation details (but the compiler needs them to emit code).
A less common way is to declare a struct in a header file, and only use pointers to it (an opaque pointer, like Burns' answer). Then you might have an implementation defining the members of that struct. See also this.
A common example is the FILE from <stdio.h>. It is very likely to be defined as some struct but the field names are conventionally hidden and unused.
C programming is a lot about having good conventions and following them.
What you have will work.
The typedef you have in the header file also acts as a forward declaration of the structure. This is sufficient to pass around a pointer to the struct type but prevents the pointer from being dereferenced.
This allows you to keep the implementation details of the struct private to the .c file were it is defined.
When you need to create opaque references in plain C the best way is to create 2 separate sets of headers, one with full declarations that will be used in sources that implement the 'methods', and another header with the opaque reference for user use.
This is the common strategy used in many OS's. Take a look to MS headers, they use HANDLEs to refer to objects. The HANDLES are created and passed to system functions, plain C simulation of C++ methods, that resides in modules using the full definition header.
Consider these 2 headers:
/* Internal header "InnerDList.h" */
struct DListNode{
void *item;
struct DListNode *next;
struct DListNode *prev;
};
2nd
/* User header "DList.h" */
typedef struct DListNode DListNode;
DListNode *CreateDList(void * data, ...);
HRESULT AddDListNode(DListNode *Dlist, void *data);
HRESULT GetDListNode(DListNode *Dlist, void *SearchData);
...
Using the first allow the compilation of the functions that works on the DList structures, the second allows the use of DList's through an opaque object.
A variation to allow the use of full or partial definition could be the following: define a preprocessor symbol in the internal header and use this to conditionally define opaque objects.
/* Internal header "InnerDList.h" */
#define INNERDLIST 1 //We will use this symbol to modify user header
typedef struct DListNode{
void *item;
struct DListNode *next;
struct DListNode *prev;
} DListNode;
#include "DList.h" //Now include user header
In the User header:
/* User header "DList.h" */
#ifndef INNERDLIST
typedef struct DListNode DListNode; //define only if not called by internal header
#endif
DListNode *CreateDList(void * data, ...);
HRESULT AddDListNode(DListNode *Dlist, void *data);
HRESULT GetDListNode(DListNode *Dlist, void *SearchData);
...
I need some help to understand this struct:
typedef struct std_fifo{
char* name;
struct std_fifo* next;
}std_fifo, *fifo;
With typedef I know that I can use only std_fifo instead of writing struct std_fifo in my code. But what about the *fifo?
The code
typedef struct std_fifo{
char* name;
struct std_fifo* next;
}std_fifo, *fifo;
creates two (very badly named) typedef names, std_fifo and fifo.
The typedef name std_fifo is equivalent to the type struct std_fifo, and can be used in place of struct std_fifo:
std_fifo fifo_instance; // creates an instance of struct std_fifo
std_fifo get_fifo(); // declares get_fifo as a function returning an
// instance of struct std_fifo
void read_fifo( std_fifo * );// declares a function taking parameter of type
// pointer to struct std_fifo
The typedef name fifo is equivalent to the type struct std_fifo *, and can be used in place of struct std_fifo *:
fifo fifo_ptr; // creates a pointer to an instance of struct std_fifo
fifo get_fifoptr(); // declares get_fifoptr as a function returning a pointer
// to an instance of struct std_fifo
void read_fifo( fifo ); // declares a function taking a parameter of type
// struct std_fifo *
The reason code like
typdef struct std_fifo { ... } std_fifo;
works is because C has four different name spaces for identifiers: labels, tag names, struct and union member names, and everything else. The tag name std_fifo is always preceded by the struct keyword, which is how the compiler distinguishes it from the std_fifo typedef name.
Some advice on using typedefs:
While they can help your code scan better in some cases, using typedefs can actually obscure your intent and make types harder to use. If the user of the type has to be aware of its representation (such as to access a member of a struct, or dereference a pointer type, or to use the right conversion specifier in a printf or scanf call, or to call a function propertly, etc.), then you should not hide the representation behind a typedef.
If you decide you do want to hide a type's representation behind a typedef, then you should also provide a full API for any operations involving that type. C does this with the FILE type; instead of manipulating a FILE object directly, you pass a pointer to it to the various stdio routines. So, if you decide you want to hide struct std_fifo * behind the typedef name fifo, then you should also create an API like:
fifo new_fifo(); // create a new fifo queue
void destroy_fifo( fifo * ); // destroy an existing fifo queue
set_name( fifo, const char * ); // set the name of a fifo element
char *get_name( fifo ); // retrieve the name of a fifo element
fifo push_fifo( fifo ); // add an element to the end of the queue
fifo pop_fifo( fifo ); // remove an element from the front of the queue
Abstraction can be a Good Thing, but "leaky" abstractions are worse than no abstraction at all.
It is a valid definition of struct to give either with a name and with a pointer.
typedef struct std_fifo{
char* name;
struct std_fifo* next;
}std_fifo, *fifo;
In this code, where std_fifo is a struct and *fifo is the pointer to this struct.
I would strongly suggest you to take a look at here : http://www.cplusplus.com/forum/windows/57382/
I want to implement container_of macro/function from scratch like that is available in linux kernel to get the address of parent structure from the member of the parent structure.
e.g. if the parent structure is
struct parent{
int id;
struct list_head list; };
and i have the address of the list_head element inside the structure.
So i want to get the address of struct parent so that i can access id of the parent.
I have only three known information
1. Type of parent structure
2. Type of struct list_head
3. identifire/name of the list_head variable.
#define container_of(ptr, type, member) ({ \
const typeof( ((type *)0)->member ) *__mptr = (ptr); \
(type *)( (char *)__mptr - offsetof(type,member) );})
Thaks i any body can explain.
Firstly your question is not appropriate. From my understanding you want to understand the working of the macro, not implement it.
Moving on,
Linked lists used in the linux kernel are nicely explained in Linux Kernel Linked List Explained
In the linux kernel the list is contained in the list node.
Example:
struct list_head { /* Kernel list structure */
struct list_head *next, *prev;
}
struct my_list {
int to;
struct list_head list; /* list is contained in the node */
int from;
}
So we iterate the linked list using the list_head variable. The tricky part is that we use the list variable to get the node structure ( in which it is contained )
See Q. 2.14 and 2.15 in MIT FAQ. The question explains how we can retrieve pointer to the CONTAINING structure if we have the offset of a variable in the struct.
So in layman terms, we could say,
struct s address = <address of struct variable> - <offset of that variable in the struct>
Coming to the macro, consider this definition of the macro. (simplistic implementation, i found in drivers/gpu/drm/nouveau/include/nvif/list.h )
#define container_of(ptr, type, member) \
(type *)((char *)(ptr) - (char *) &((type *)0)->member)
So think of the left operand as the structure VARIABLE ( this is the list_head variable usually). Now coming to the right operator. To get the OFFSET of that variable ( say list_head variable ) in the containing strict ( say struct my_list ), we create a zeroed struct ( i.e., a temp struct with the address 0x0 ) so the addresses of any variables in the struct corresponds to the offset of that variable.
Now the last part to understand is why cast to char *. Well this basic pointer arithmetic. char * addtion would increment the values by 1 at a time ( char* points to a char of 1 byte ).
((char*)0) + 1 -> 0x1
Had it been int * addition of 1 to the pointer would increment the offset by 4 , as int * points to a int of size 4( on my computer).
((int*)0) + 1 -> 0x4
Hope that helped .. :)