linux内核链表使用
来源:互联网 发布:希特勒南极 知乎 编辑:程序博客网 时间:2024/04/19 06:37
Linux内核链表的核心思想是:在用户自定义的结构A中声明list_head类型的成员p,这样每个结构类型为A的变量a中,都拥有同样的成员p,如下:
struct A{
int property;
struct list_head p;
}
其中,list_head结构类型定义如下:
struct list_head {
struct list_head *next,*prev;
};
list_head拥有两个指针成员,其类型都为list_head,分别为前驱指针prev和后驱指针next。
假设:
(1)多个结构类型为A的变量a1...an,其list_head结构类型的成员为p1...pn
(2)一个list_head结构类型的变量head,代表头节点
使:
(1)head.next= p1 ; head.prev = pn
(2)p1.prev = head,p1.next = p2;
(3)p2.prev= p1 , p2.next = p3;
…
(n)pn.prev= pn-1 , pn.next = head
以上,则构成了一个循环链表。
因p是嵌入到a中的,p与a的地址偏移量可知,又因为head的地址可知,所以每个结构类型为A的链表节点a1...an的地址也是可以计算出的,从而可实现链表的遍历,在此基础上,则可以实现链表的各种操作。
下面是从linux内核中移植出来的简单链表,list.h和list.c:
list.h:
#ifndef _INIT_LIST_H_#define _INIT_LIST_H_#ifndef offsetof/* Offset of member MEMBER in a struct of type TYPE. */#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)#endifstruct listnode{ struct listnode *next; struct listnode *prev;};#define node_to_item(node, container, member) \ (container *) (((char*) (node)) - offsetof(container, member))#define list_declare(name) \ struct listnode name = { \ .next = &name, \ .prev = &name, \ }#define list_for_each(node, list) \ for (node = (list)->next; node != (list); node = node->next)#define list_for_each_reverse(node, list) \ for (node = (list)->prev; node != (list); node = node->prev)void list_init(struct listnode *list);void list_add_tail(struct listnode *list, struct listnode *item);void list_remove(struct listnode *item);#define list_empty(list) ((list) == (list)->next)#define list_head(list) ((list)->next)#define list_tail(list) ((list)->prev)#endif
list.c:
#include "list.h"void list_init(struct listnode *node){ node->next = node; node->prev = node;}void list_add_tail(struct listnode *head, struct listnode *item){ item->next = head; item->prev = head->prev; head->prev->next = item; head->prev = item;}void list_remove(struct listnode *item){ item->next->prev = item->prev; item->prev->next = item->next;}
测试代码list_test.c:
#include<stdio.h>#include<stdlib.h>#include "list.h"#define STUDENT_FREE_MEMORY//声明链表节点typedef struct {int id;char *name;struct listnode _list;}student;//遍历函数指针typedef void (*student_foreach_fun)(student *stu,void *data);//声明链表static list_declare(student_list);//添加节点int student_add(struct listnode *list,student *stu){list_init(&stu->_list);list_add_tail(list,&stu->_list);}//删除节点,释放节点空间int student_del(struct listnode *list,int id){struct listnode *node;student *stu;list_for_each(node,list){stu = node_to_item(node,student,_list);if(id == stu->id){printf("list_del, id:%d,name:%s\n",stu->id,stu->name);list_remove(node);#ifdef STUDENT_FREE_MEMORY//释放节点空间free(stu);stu = NULL;#endifreturn 1;}}return 0;}//节点遍历void student_foreach(struct listnode *list,student_foreach_fun fun,void *data){struct listnode *node;student *stu;list_for_each(node,list){stu = node_to_item(node,student,_list);fun(stu,data);}}//打印节点信息void student_print(student *stu,void *data){printf("id:%d,name:%s\n",stu->id,stu->name);}int main(){int i,len;student *stu;char *stu_name[]={"tonny","andy","michael","leslie","john"};len = sizeof(stu_name)/sizeof(stu_name[0]);//添加节点for(i=0;i<len;i++){stu = calloc(1,sizeof(student));stu->id = i + 1;stu->name = stu_name[i];student_add(&student_list,stu);}//打印所有节点student_foreach(&student_list,student_print,(void *)0);//删除节点student_del(&student_list,1);student_foreach(&student_list,student_print,(void *)0);//删除节点student_del(&student_list,5);student_foreach(&student_list,student_print,(void *)0);return 0;}
Makefile:
TARGET=list_testSRC=list_test.c list.c#SRC=$(wildcard *.c)OBJ=$(SRC:.c=.o)CFLAGS=-g -Wall -o$(TARGET):$(SRC)gcc $(SRC) $(CFLAGS) $(TARGET)clean:rm $(OBJ) $(TARGET)
- linux内核链表使用
- linux内核链表使用
- linux内核链表使用
- linux内核链表使用
- Linux内核---60.linux内核链表list的使用
- Linux 内核链表使用举例
- linux内核链表使用示例
- linux内核链表
- linux内核链表
- Linux内核链表
- linux内核链表
- linux内核链表
- Linux内核链表
- linux内核链表
- Linux内核链表
- linux内核链表
- linux内核链表
- Linux内核链表
- LaTeX/尺寸
- sql的 INNER JOIN, left join,right join语法
- ROC曲线-阈值评价标准
- jQuery双色表格
- 一日一点RakNet(20)--NetworkIDObject
- linux内核链表使用
- 函数返回局部变量(转)
- Windows远程关机和shutdown命令双保服务器重启
- MFC文件操作之CArchive
- extern用法总结
- 提高人体自身免疫力,从健康生活方式开始
- 过客的心
- 23种设计模式(3):抽象工厂模式
- Xcode4.3安装目录