内核链表
Posted myjune
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了内核链表相关的知识,希望对你有一定的参考价值。
1 引言
如果大家用c做应用(哈哈,估计基本不用),就会发现总要造轮子,本着服务大家,方便自己的原则,搞点小程序方便大家做开发。
这里就泼个内核链表的实现给大家(程序如果有问题,希望大家及时指正)使用。
为啥要用内核链表?
主要还是为了方便,比如用c做个项目需要多次用到链表,注意这里的意思是多个链表中的数据类型不同,format as:
struct StringList { char str[256]; struct UserList* pre; struct UserList* next; }; strcut IntList { int id; struct Intlist* pre; struct Intlist* next; };
需要实现两个链表的逻辑,因为链表是“数据相关”(自创词)的。
内核链表是数据无关的,基本原理是通过结构体的一个元素地址从而可以获取结构体入口地址,这块不清楚的老铁自行查一下container_of这个宏,这里不再啰嗦。
2 扣出内核中的链表实现
# define POISON_POINTER_DELTA 0 #define LIST_POISON1 ((void *) 0x00100100 + POISON_POINTER_DELTA) #define LIST_POISON2 ((void *) 0x00200200 + POISON_POINTER_DELTA) //计算member在type中的位置 #define offsetof(type, member) (size_t)(&((type*)0)->member)
//根据member的地址获取type的起始地址 #define container_of(ptr, type, member) ({ const typeof(((type *)0)->member)*__mptr = (ptr); (type *)((char *)__mptr - offsetof(type, member)); }) #define list_entry(ptr, type, member) \ container_of(ptr, type, member) #define list_first_entry(ptr, type, member) \ list_entry((ptr)->next, type, member) #define list_for_each(pos, head) for (pos = (head)->next; pos != (head); pos = pos->next) //链表结构 struct list_head { struct list_head *prev; struct list_head *next; }; static inline void init_list_head(struct list_head *list) { list->prev = list; list->next = list; } static inline void __list_add(struct list_head *new, struct list_head *prev, struct list_head *next) prev->next = new; new->prev = prev; new->next = next; next->prev = new; } //从头部添加 static inline void list_add(struct list_head *new , struct list_head *head) { __list_add(new, head, head->next); } //从尾部添加 static inline void list_add_tail(struct list_head *new, struct list_head *head) { __list_add(new, head->prev, head); } static inline void __list_del(struct list_head *prev, struct list_head *next) { prev->next = next; next->prev = prev; } static inline void list_del(struct list_head *entry) { __list_del(entry->prev, entry->next); entry->next = LIST_POISON1; entry->prev = LIST_POISON2; } static inline void list_move(struct list_head *list, struct list_head *head) { __list_del(list->prev, list->next); list_add(list, head); } static inline void list_move_tail(struct list_head *list, struct list_head *head) { __list_del(list->prev, list->next); list_add_tail(list, head); }
//An example
int main(int argc, const char* argv[])
{
//Init List Head
struct list_head* global_head = (struct list_head*)malloc(sizeof(struct list_head));
init_list_head(global_head);
//Insert an value from tail
struct Val {
struct list_head node;
int value; //Identify your data on list
};
struct Val* v = (struct Val*)malloc(sizeof(struct Val));
struct list_head* node = v->node;
list_add_tail(node, global_head);
//travel the list.
struct list_head* p;
list_for_each(pos, global_head)
{
v = list_entry(pos, struct Val, value);
printf("%d ", v->value);
}
fputs();
return 0;
}
以上是关于内核链表的主要内容,如果未能解决你的问题,请参考以下文章
Linux 内核 内存管理RCU 机制 ④ ( RCU 模式下更新链表项 list_replace_rcu 函数 | 链表操作时使用 smp_wmb() 函数保证代码执行顺序 )
LINUX PID 1和SYSTEMD PID 0 是内核的一部分,主要用于内进换页,内核初始化的最后一步就是启动 init 进程。这个进程是系统的第一个进程,PID 为 1,又叫超级进程(代码片段