回复
Linux链表
JoyboyCZ
发布于 2023-3-29 17:27
浏览
0收藏
linux创建及初始化链表
动态方法
通过struct list_head创建,INIT_LIST_HEAD初始化。(list_head以及INIT_LIST_HEAD位于***<u><linux/list.h></u>***)
struct list_head {
struct list_head *next, *prev;
};
static inline void INIT_LIST_HEAD(struct list_head *list)
{
list->next = list;
list->prev = list;
}
struct list_head mylist;
INIT_LIST_HEAD(&mylist)
静态方法
静态分配通过LIST_HEAD宏完成:
#define LIST_HEAD_INIT(name) {
&(name), &(name)
}
#define LIST_HEAD(name) struct list_head name = LIST_HEAD_INIT(name) /* 将list_head的前后指针都指向name本身 */
LIST_HEAD(mylist)
创建链表节点
要创建新节点,只需创建数据结构实例,并初始化嵌入其中的list_head。
举例:
struct person {
int age;
string sex;
string name;
struct list_head list;
};
struct person *laowang = kzalloc(sizeof(struct person), GFP_KERNEL);
LIST_HEAD_INIT(&laowang->list);
关于kzalloc申请内存可参考Linux内核空间内存申请函数kmalloc、kzalloc、vmalloc的区别【转】 - sky-heaven - 博客园 (cnblogs.com)
添加链表节点
内核提供的list_add用于向链表添加新项,它是内部函数__list_add的包装:
static inline void __list_add(struct list_head *new, struct list_head *prev, struct list_head *next)
{
next->prev = new;
next->next = next;
new->prev = prev;
prev->next = new;
}
void list_add(struct list_head *new, struct list_head *head); /* 这种模式科研用来实现堆栈 */
static inline void list_add(strcut list_head *new, struct list_head *head)
{
__list_add(new, head, head->next);
}
static LIST_HEAD(person_list); /* 如何使用呢? 需要先创建一个struct list_head变量 */
list_add(&zhangsan->list, &person_list); /* 之后将节点添加到person_list中 */
还有另一个函数可以将节点添加到链表:
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 *entry) /* entry:要删除的链表的首地址 */
{
__list_del(entry->prev, entry->next);
entry->next = LIST_POISON1; /* LIST_POISON1/2皆为NULL,详细位于/linux/poison.h */
entry->prev = LIST_POISON2;
}
static inline void list_del_init(struct list_head *entry)
{
__list_del_entry(entry);
INIT_LIST_HEAD(entry); // 运行中初始化链表节点
}
static inline void __list_del_entry(struct list_head *entry)
{
__list_del(entry->prev, entry->next);
}
list_del只是移除该节点,分配给该节点的内存需要使用kfree手动释放。
链表遍历
使用宏list_for_each_entry(pos, head, member)进行链表遍历。
- head:链表头节点
- member:数据结构中链表struct list_head的名称
- pos:用于迭代。它是一个循环游标,就像for(i=0; i<foo; i++)中的i。head可以是链表头节点或任一项。(内核开发者只实现了循环双链表)
#define list_for_each_entry(pos, head, member) \
for (pos = list_entry((head)->next, typeof(*pos), member); \
&pos->member != (head); \
pos = list_entry(pos->member.next, typeof(*pos), member))
#define list_entry(ptr, type, member) \
container_of(ptr, type, member)
分类
标签
赞
收藏
回复
相关推荐