当前位置:   article > 正文

Linux内核源码list.h解读_config_debug_list

config_debug_list

#list.h源码阅读
此文章是我阅读list.h后的一些见解,有问题且理解不到位的地方希望大家批评指正。

  • 本次我们阅读的内核版本为4.18.7
    在Linux内核中,list.h是内核为了方便使用链表而自己建立的链表头文件。
    以__开头的是指内核函数。
    ##链表
    ##宏定义
  • 除了调用其它头文件外,首先看到的是两个宏定义。
#define LIST_HEAD_INIT(name) { &(name), &(name) }

#define LIST_HEAD(name) \
	struct list_head name = LIST_HEAD_INIT(name)
  • 1
  • 2
  • 3
  • 4

其实可以写成一句

struct list_head name ={&(name),&(name)};
  • 1

这个结构体在types.中定义了双向链表。
##初始化链表

  • 定义完当然就是初始化链表了。
static inline void INIT_LIST_HEAD(struct list_head *list)
{
	WRITE_ONCE(list->next, list);
	list->prev = list;
}
  • 1
  • 2
  • 3
  • 4
  • 5

将双链表的头尾指向自己(初始化)。
这里有两个问题,1、inline的作用,2、WRITE_ONCE的使用。

  • inline是关键字是把后面的函数定义为内联函数,我们可以认为它是一个static函数加上了inline属性,它大部分表现与static一样,只不过在调用这种函数的时候,gcc会在其调用处将其汇编码展开编译而不为这个函数生成独立的汇编码。我们可以把它理解为在定义和使用函数在同一文件时(无函数指针对函数文件进行间接调用,以及函数递归进行自身调用),inline相当于做了宏定义的替换,这样表面看可能没有什么优势,但如果函数的定义较为简单,但调用的十分频繁,这样调用函数的开销会变的非常大影响性能。
  • 在阅读list.h的过程中我们会碰到WRITE_ONCE()与READ_ONCE(),他们同属于ACCESS_ONCE()宏,WRITE_ONCE (a,b)其实就等价于a=b,READ_ONCE(x)即读取x的值,但是为什么不直接使用呢?由于C语言本身没有并发的概念,但实际情况中并发是不可避免的,ACCESS_ONCE()就是为解决这一问题存在的,该宏确保作为参数传递的值仅由生成的代码访问一次。通俗的讲,如果直接赋值a=b;b的值随时可能被其他进程修改,这样得到的A值是不可靠的,那么ACCESS_ONCE()做了什么呢?先取x的地址,将其转换为x类型的指针,将其强制转换为x类型的volatile(在C中,提醒编译器后面定义的变量随时会改变,需要读取变量时直接从变量地址进行读取)指针,再指向该指针。即将相关变量的类型转为volatile类型,直接对内存地址进行访问。这样成功避免了多线程并发导致变量被修改的问题,在共享变量未上锁的情况下,ACCESS_ONCE()为我们提供了确保读取有效数据的方法。
    ##调试模块
    下面看到的是CONFIG_DEBUG_LIST,这是一个条件调试模块,仅在DEBUG下才会被编译,若未在调试模式下则定义链表增加或删除的可用性。不在DEBUG模式则定义了如下两个函数:
static inline bool __list_add_valid(struct list_head *new,
				struct list_head *prev,
				struct list_head *next)
{
	return true;
}
static inline bool __list_del_entry_valid(struct list_head *entry)
{
	return true;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

而开启DEBUG模式下的两个函数与这里的区别是无返回值,这里定义他们的类型是bool型,而bool的默认返回值为FALUSE,也就是说DEBUG模块定义了__list_add_valid,与 __list_del_entry_valid,他们的返回值为FALUSE而非DEBUG下定义了__list_add_valid与__list_del_entry_valid,他们的返回值为TRUE。我们目前只要明确这一点就好,接着往下看。
##链表插入节点
内核代码真是精妙无比,我们来看它是怎么做的。

static inline void __list_add(struct list_head *new,
			      struct list_head *prev,
			      struct list_head *next)
{
	if (!__list_add_valid(new, prev, next))
		return;

	next-&g
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/不正经/article/detail/128106
推荐阅读
相关标签
  

闽ICP备14008679号