linux中的list

Linux内核提供了list这个数据结构以及操作函数。这个数据结构在内核驱动中使用广泛,而且确实方便使用。为了详细了解这个数据结构的用法,方便以后使用,把这个数据结构里面的功能都试用了一次,清楚了很多。下面是实验程序和自己得出的使用方法,请高手多多指教。

Struct list_head { struct list_head *next, *prev ;};

List结构实际上是一个list_head结构构成的链表。如果想使用这个结构来构造自己的链表,只要把这个struct list_head结构嵌入到自己的结构体中,成为自己结构体的一个成员即可。整个list.h文件的函数都使用这个结构构成一个链表,而自己的结构体成员实际并不在链表上,但是list.h中使用container_of这个宏可以通过结构体中的struct list_head成员的地址来得到整个结构体的地址,这样就可以实现使用list.h文件中的定义实现自己的链表构造了。

list.h提供的函数构造的链表是有一个空头节点的。

如果在用户程序中使用这个结构的话,需要对这个文件做一些改动。主要是找不到如何将这个头文件直接安装到/usr/include目录下,只好直接拷贝。但是这个头文件中同时包含了另外的两个体系相关的头文件,一个是prefetch.h文件,这个文件提供perfetch这个函数用来针对特定的CPU体系做优化;另一个是asm/system.h这两个文件无法提供,只能不拷贝,将list.h中使用到这两个文件的部分直接拷贝到list.h文件中。主要是container_of宏(这个在kernel.h中;另外需要将所有的prefetch注释掉,否则无法链接通过。

LIST_HEAD(name):这个宏可以定义一个struct list_head结构体,并初始化结构体中的两个成员函数

LIST_INIT_HEAD( struct list_head *head) ;这个函数初始化给定的结构体,使的成员指向自己;

List_add ( struct list_head *new , struct list_head *list );new是要添加到list链表中的节点;list是要添加到的链表中的一个节点,new这个节点会添加到这个节点后面。如果提供的list是一个链表的头节点,那么这个函数用来模拟一个LIFO的栈是不错的。

list_add_tail( struct list_head *new , struct list_head *list );和上面的函数一样,只不过是new的位置在list的前面。如果提供的list是一个链表的头节点,那么就是一个FIFO的队列。

list_del (struct list_head *entry , struct list_head *list );从链表中删除entry节点,并将entry节点的成员指针指向无效地址。

list_replace(struct list_head * new , struct list_head *old);用节点new替换old,这个函数完成后,old中的指针仍然指向原来的链表

list_replace_init( struct list_head * new , struct list_head * old );和上面的函数一样,但是会将old中的成员指针初始化为无效地址

list_move (struct list_head * list , struct list_head * head );将list节点从原来的链表上删除,添加到head链表中

list_move_tail(struct list_head *list , struct list_head * head );这个和上面的函数一样,但是添加的位置在head的前面

list_is_last( struct list_head *list);list成员是否是它所在的链表的最后一个成员。是返回1,不是返回0;

list_is_empty( struct list_head *list )list链表是否为空,为空返回1,不为空返回0

list_is_empty_careful(struct list_head * list );和上面的函数一样,但是可以在SMP的情况下,较为准确的的到结构,但是也不很安全,最好使用同步方法来做

list_is_single( struct list_head *list )list链表中是否只有一个成员,是返回1,不是返回0

list_cut_position( struct list_head * list , struct list * head , struct list * entry );将链表head从entry位置分割,entry以后的成员链接到list上

list_splic_init( struct list_head *list , struct list_head * head );将list链表中的成员链接到head中去,并将list头重新初始化。

list_entry( per,type,member) 这个宏用来获得链表中一个节点,per表示要找的链表中的一个节点,是struct list_head *类型的变量,type表示嵌入了struct list_head结构的结构体的定义(是结构体本身的定义,就是那个struct ***{});member,表示嵌入的struct list_head结构体的变量名。返回的值是包含着struct list_head结构的结构体变量的地址。

比如:struct my_struct {

Struct list_head * node ;

Int a;

};

那么list_entry( struct list * ptr , struct my_struct , node )将返回一个struct my_struct *类型的指针,用这个指针可以操作a

List_first_entry( ptr,type,member) 和上面的一样,不过得到的是链表中的第一个成员;

List_for_each(pos, head);这个宏扩展后就是一条for语句,可以用来遍历一个链表。

List_for_each_pre(pos,head);和上面的一样,不过是反向遍历

List_for_each_entry(type * , struct list_head * ,member)这个宏扩展后也是一个for语句,但是可以用这个语句直接得到链表中的每个成员。中间的成员是链表的头

List_for_each_entry_continue( );这个宏可以用来遍历一个链表从给定的任意位置

HASH链表的有待进一步研究

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值