linux——list.h

在Linux内核中,为了提供统一的链表操作,减少结构体的额外开支,提供了 list.h 文件,绝对路径为 /usr/src/kernels/include/linux/list.h。

list.h中,表头的声明如下:

#define LIST_HEAD_INIT(name) {&(name),&(name)}
#define LIST_HEAD(name) \
struct list_head name=LSIT_HEAD_INIT(name)   

实际为:
struct list_head name={&(name),&(name)};    

另外,INIT_LIST_HEAD() 操作和上述宏定义相同。

list_head 结构体声明如下:

struct list_head {
	struct list_head *next,*prev;	// 双链表结构
}

链表操作如下:

_ _list_add(),将新的节点插入链表中,其他插入接口都间接调用该接口来完成。插入的过程如下图:
插入的顺序

_ _list_del,删除链表中的某一个节点,其他的删除函数调用该函数完成。删除的的过程如下图:
删除的顺序
注意,删除操作虽然改变了前后节点的指针指向,但是被删除节点的指针指向并未改变,因此该节点可用做位置记录。

list_replace(),将新的节点替换掉旧的节点。替换的顺序如图所示:
替换的顺序
被替换掉的节点没有被释放,且指针指向也没有改变,因此可用作位置记录。

list_move(),是将节点取出后,再插入到指定的位置。移动的过程如下:

先用 __list_del() 将节点取出。然后再用 list_add() 将节点插入指定位置。关于节点的插入,提供了两种形式,一种是头插:list_add();另一种是尾插:list_add_tail()。

__list_cut_position(),将链表分割成两个链表。函数操作如图所示:
一分为二的顺序

__list_splice() 则是将两个链表合并成一个链表。

关于链表的遍历,内核提供了list_for_each_entry()来遍历链表中的元素。

#define list_for_each_entry(pos, head, member)				\
	for (pos = list_first_entry(head, typeof(*pos), member);	\
	     &pos->member != (head);					\
	     pos = list_next_entry(pos, member))

#define list_first_entry(ptr, type, member) \
	list_entry((ptr)->next, type, member)

#define list_next_entry(pos, member) \
	list_entry((pos)->member.next, typeof(*(pos)), member)

#define list_entry(ptr, type, member) \
	container_of(ptr, type, member)

#define container_of(ptr, type, member) ({				\
	void *__mptr = (void *)(ptr);					\
	BUILD_BUG_ON_MSG(!__same_type(*(ptr), ((type *)0)->member) &&	\
			 !__same_type(*(ptr), void),			\
			 "pointer type mismatch in container_of()");	\
	((type *)(__mptr - offsetof(type, member))); })

#define offsetof(TYPE, MEMBER)	((size_t)&((TYPE *)0)->MEMBER)

分析 container_of 函数,container_of 函数返回了一个地址。offsetof 函数主要返回结构体中某一成员的相对偏移量。随后,利用成员当前实际的地址减去偏移量,便可以获得当前结构体的首地址。整个计算如下图所示:

|--------struct AAA--------|--- ptr - offsetof(TYPE, MEMBER)
|                          | |  offsetof(TYPE, MEMBER)
|              			   | |
|--struct list_head *head--|--- ptr
|                          |
|--------------------------|

按照上述的计算过程,便可遍历链表中所关联的结构体对象。

  • 5
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
这个错误是因为在编译过程中找不到apue.h文件导致的。通常情况下,apue.h是一个头文件,用于包含在C程序中使用的一些函数和定义。在Linux下,这个头文件通常是由一个库文件提供的。根据你提供的信息,你可能没有正确设置编译环境,或者没有将apue.h头文件包含在你的编译命令中。 为了解决这个问题,你可以按照以下步骤进行操作: 1. 确保你已经正确安装了apue库文件。可以使用命令`apt-get install libapue-dev`来安装这个库文件。 2. 确保你的编译命令中包含了正确的头文件路径。你可以使用`-I`选项来指定头文件的路径。例如,`gcc -o myprogram myprogram.c -I/path/to/apue/include`。 3. 如果你已经安装了apue库文件,但是还是找不到apue.h文件,那么可能是因为头文件没有正确地安装到系统目录中。你可以手动将apue.h文件复制到/usr/include/目录下。可以使用命令`cp /path/to/apue/include/apue.h /usr/include/`来复制文件。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [Unix环境高级编程——解决第一个问题“apue.h: No such file or directory”](https://blog.csdn.net/qq_41899773/article/details/107376991)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *2* [unix高级编程时遇到apue.h 报错问题](https://blog.csdn.net/zhuqinfeng/article/details/50468178)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值