link list
struct list_element {
void *data;
struct list_element *next;
}
double linklist
struct list_element {
void *data;
struct list_element *prev;
struct list_element *next;
}
list_header
struct list_head{
struct list_head *next;
struct list_head *prev;
}
struct fox {
unsigned long tail_length;
unsigned long weight;
bool is_fantastic;
struct list_head list;
}
container_of
use the macro container_of, we can easily find the parent struct containing any given member variable. the offset of a given variable into a structure is fixed by the ABI at compile time.
#define container_of(ptr, type, member) ({ \
const typeof( ((type *)0)->member) * __mptr = (ptr); \
(type *)((char *)__mptr - offsetof(type, member));})
#defnine list_entry(ptr, type, member) \
container_of(ptr, type, member)
例子
struct container {
int some_other_data;
int this_data;
}
struct container *my_container;
int *my_ptr = &my_container->this_data;
my_container = container_of(my_ptr, struct container, this_data);
my_ptr: 表示指向this_data的指针
struct container: 表示包含this_data的结构体
this_data: 表示my_ptr在struct container中的字段名
define a linked list
struct fox *red_fox;
red_fox = kmalloc(sizeof(*red_fox), GFP_KERNEL);
red_fox->tail_length = 40;
red_fox->weight = 6;
red_fox->is_fantastic = false;
INIT_LIST_HEAD(&red_fox->list);
// or
struct fox red_fox = {
.tail_length = 40,
.weight = 6,
.list = LIST_HEAD_INIT(red_fox. list),
};
iterator
struct list_head *p;
struct fox *f;
list_for_each(p, &fox_list) {
f = list_entry(p, struct fox, list);
}
list_for_each_entry(pos, head, member);
here, pos is a pointer to the object containing the list_head nodes.
struct fox *f;
list_for_each_entry(f, &fox_list, list) {
// for each iteration f points to the next fox structure
}
in real example, from inotify, the kernel’s filesystem notification system:
static struct inotify_watch *inode_find_handle(struct inode *inode,
struct inotify_handle *ih)
{
struct inotify_watch *watch;
list_for_each_entry(watch, &inode->inotify_watches, i_list) {
if (watch->ih == ih) {
return watch;
}
}
return NULL;
}
this function iterates over all the entries in the inode->inotify_watches list, each entry is of type struct inotify_watch and the list_head in that structure is named i_list.
list_for_each_entry_safe
list_for_each_entry_safe(pos, next, head, member)
The next pointer is used by the list_for_each_entry_safe()
macro to store the next entry in the list, we can use this macro to remove the element while iterator the list
Queue
kfifo
Creating queue
int kfifo_alloc(struct kfifo *fifo, unsigned int size, gfp_t gfp_mask);
This function creates and initializes a kfifo with a queue of size
bytes. The kernel uses the gfp mask gfp_mask
to allocate the queue. upon success, it return 0, otherwise it return negtive error code.
struct kfifo fifo;
int ret;
ret = kfifo_alloc(&fifo, PAGE_SIZE, GFP_KERNEL);
if (ret)
return ret;
enqueue
unsigned int i;
for (i = 0; i < 32; i++)
kfifo_in(fifo, &i, sizeof(i));
Map
struct idr id_huh; // define idr
idr_init(&id_huh); // initialize idr