[toc]
include/linux/once_lite.h: (一次性调用) 提供确保某段代码在多核环境下只被精确执行一次的宏
每个宏仅在第一次使用时,执行函数功能.通过静态变量来实现一次性调用的功能
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 #define DO_ONCE_LITE(func, ...) \ DO_ONCE_LITE_IF(true, func, ##__VA_ARGS__) #define __ONCE_LITE_IF(condition) \ ({ \ static bool __section(".data..once" ) __already_done; \ bool __ret_cond = !!(condition); \ bool __ret_once = false; \ \ if (unlikely(__ret_cond && !__already_done)) { \ __already_done = true; \ __ret_once = true; \ } \ unlikely(__ret_once); \ }) #define DO_ONCE_LITE_IF(condition, func, ...) \ ({ \ bool __ret_do_once = !!(condition); \ \ if (__ONCE_LITE_IF(__ret_do_once)) \ func(__VA_ARGS__); \ \ unlikely(__ret_do_once); \ })
include/asm-generic/bug.h: 提供 BUG() 和 WARN_ON() 等用于内核断言和报告错误的宏 BUG 1 2 3 4 5 6 7 8 9 10 #ifndef HAVE_ARCH_BUG #define BUG() do { \ printk("BUG: failure at %s:%d/%s()!\n" , __FILE__, __LINE__, __func__); \ barrier_before_unreachable(); \ panic("BUG!" ); \ } while (0) #endif
BUG_ON 1 2 3 4 5 6 7 8 9 10 11 #ifndef HAVE_ARCH_BUG #define BUG() do { \ printk("BUG: failure at %s:%d/%s()!\n" , __FILE__, __LINE__, __func__); \ barrier_before_unreachable(); \ panic("BUG!" ); \ } while (0) #endif #ifndef HAVE_ARCH_BUG_ON #define BUG_ON(condition) do { if (unlikely(condition)) BUG(); } while (0) #endif
WARN 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 #ifndef WARN #define WARN(condition, format...) ({ \ int __ret_warn_on = !!(condition); \ if (unlikely(__ret_warn_on)) \ __WARN_printf(TAINT_WARN, format); \ unlikely(__ret_warn_on); \ }) #endif #ifndef __WARN_FLAGS #define __WARN() __WARN_printf(TAINT_WARN, NULL) #define __WARN_printf(taint, arg...) do { \ instrumentation_begin(); \ warn_slowpath_fmt(__FILE__, __LINE__, taint, arg); \ instrumentation_end(); \ } while (0) #else #define __WARN() __WARN_FLAGS(BUGFLAG_TAINT(TAINT_WARN)) #define __WARN_printf(taint, arg...) do { \ instrumentation_begin(); \ __warn_printk(arg); \ __WARN_FLAGS(BUGFLAG_NO_CUT_HERE | BUGFLAG_TAINT(taint));\ instrumentation_end(); \ } while (0) #define WARN_ON_ONCE(condition) ({ \ int __ret_warn_on = !!(condition); \ if (unlikely(__ret_warn_on)) \ __WARN_FLAGS(BUGFLAG_ONCE | \ BUGFLAG_TAINT(TAINT_WARN)); \ unlikely(__ret_warn_on); \ }) #endif
WARN_ON WARN_ON_ONCE 打印一次警告 1 2 3 4 #ifndef WARN_ON_ONCE #define WARN_ON_ONCE(condition) \ DO_ONCE_LITE_IF(condition, WARN_ON, 1) #endif
include/linux/cleanup.h: 提供基于GCC attribute ((cleanup)) 的自动资源清理机制 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103
__cleanup __cleanup
是一个 GCC 提供的属性(attribute),用于在变量的作用域结束时自动调用指定的清理函数。它是一种基于作用域的资源管理机制,能够有效减少手动管理资源释放的复杂性,避免资源泄漏。
工作原理
定义清理函数 :
清理函数是一个普通的 C 函数,用于释放资源或执行其他清理操作。
该函数的参数通常是一个指向需要清理的变量的指针。
声明变量时使用 __cleanup
:
在声明变量时,通过 __cleanup
属性指定清理函数。
当变量超出其作用域时,编译器会自动调用指定的清理函数。
作用域结束时自动调用 :
当变量的作用域结束(如函数返回或代码块结束)时,清理函数会被自动调用,无需显式调用。
DEFINE_FREE 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 #define DEFINE_FREE(_name, _type, _free) \ static inline void __free_##_name(void *p) { _type _T = *(_type *)p; _free; } #define __free(_name) __cleanup(__free_##_name)
no_free_ptr return_ptr 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 #define __get_and_null(p, nullvalue) \ ({ \ __auto_type __ptr = &(p); \ __auto_type __val = *__ptr; \ *__ptr = nullvalue; \ __val; \ }) static inline __must_checkconst volatile void * __must_check_fn(const volatile void *val){ return val; } #define no_free_ptr(p) \ ((typeof(p)) __must_check_fn((__force const volatile void *)__get_and_null(p, NULL))) #define return_ptr(p) return no_free_ptr(p)
CLASS 这段代码定义了一个宏 CLASS
,用于简化特定类型对象的声明和管理,特别是在对象的构造和析构过程中。它结合了 GCC 的 __cleanup
属性和自定义的构造函数与析构函数,为对象的生命周期管理提供了一种自动化的机制。
宏的功能
参数说明 :
_name
: 表示对象的类型名称的一部分,用于生成具体的类型和函数名称。
var
: 表示声明的变量名称。
生成的代码 :
宏会将 _name
拼接成完整的类型名称 class_##_name##_t
,并将其作为变量 var
的类型。
宏会将变量 var
与一个自定义的析构函数 class_##_name##_destructor
关联起来,通过 GCC 的 __cleanup
属性实现。当变量超出作用域时,class_##_name##_destructor
会被自动调用。
宏会将变量 var
初始化为 class_##_name##_constructor
的返回值,表示在声明时自动调用构造函数。
工作原理
使用场景 该宏适用于需要自动管理资源的场景,例如文件句柄、内存分配、锁等。通过这种方式,可以减少手动调用构造和析构函数的代码量,同时降低资源泄漏的风险。
示例 假设有以下构造函数和析构函数:
1 2 3 4 5 6 7 8 9 10 11 12 typedef struct { int value; } class_example_t ; class_example_t class_example_constructor () { class_example_t obj = { .value = 42 }; return obj; } void class_example_destructor (class_example_t *obj) { printf ("Cleaning up: %d\n" , obj->value); }
可以使用 CLASS
宏如下:
1 2 3 CLASS(example, my_obj); printf ("Value: %d\n" , my_obj.value);
总结 CLASS
宏通过结合 GCC 的 __cleanup
属性和自定义的构造/析构函数,为 C 语言提供了一种类似于 C++ RAII(资源获取即初始化)的机制。它简化了资源管理的代码,同时提高了代码的安全性和可维护性,非常适合需要自动管理资源的场景。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 #define DEFINE_CLASS(_name, _type, _exit, _init, _init_args...) \ typedef _type class_##_name##_t; \ static inline void class_##_name##_destructor(_type *p) \ { _type _T = *p; _exit; } \ static inline _type class_##_name##_constructor(_init_args) \ { _type t = _init; return t; } #define EXTEND_CLASS(_name, ext, _init, _init_args...) \ typedef class_##_name##_t class_##_name##ext##_t; \ static inline void class_##_name##ext##_destructor(class_##_name##_t *p)\ { class_##_name##_destructor(p); } \ static inline class_##_name##_t class_##_name##ext##_constructor(_init_args) \ { class_##_name##_t t = _init; return t; } #define CLASS(_name, var) \ class_##_name##_t var __cleanup(class_##_name##_destructor) = \ class_##_name##_constructor #define DEFINE_LOCK_GUARD_1(_name, _type, _lock, _unlock, ...) \ __DEFINE_CLASS_IS_CONDITIONAL(_name, false); \ __DEFINE_UNLOCK_GUARD(_name, _type, _unlock, __VA_ARGS__) \ __DEFINE_LOCK_GUARD_1(_name, _type, _lock)
scoped_guard 这段代码定义了两个宏 __scoped_guard
和 scoped_guard
,它们是用于实现一种基于作用域的资源管理机制(类似于 C++ 中的 RAII)。这些宏的主要目的是在特定作用域内自动管理资源(如锁的获取和释放),从而减少手动管理资源的复杂性和潜在的错误。
__scoped_guard
的功能__scoped_guard
是一个底层的辅助宏,用于实现基于作用域的资源管理。它的核心逻辑是通过一个 for
循环和条件判断来确保资源在作用域结束时被正确释放。以下是它的关键部分:
CLASS(_name, scope)(args)
:
这是一个构造函数调用,创建了一个临时对象 scope
,该对象的类型由 CLASS(_name, scope)
决定。
这个对象通常会在构造函数中获取资源(如加锁),并在析构函数中释放资源(如解锁)。
循环条件 :
__guard_ptr(_name)(&scope)
:检查资源是否需要被管理(例如,锁是否已经被获取)。
!__is_cond_ptr(_name)
:确保对于无条件的资源管理(如无条件加锁),编译器不会跳过循环体。
这两个条件的组合确保了资源管理逻辑的正确性。
goto
和 _label
:
goto _label
是一种跳转机制,用于在作用域结束时退出循环并触发资源释放。
_label
是一个唯一的标签,由调用者提供,用于标记循环的退出点。
if (0)
和 else
:
if (0)
的作用是确保循环体的代码不会被执行。
else
子句中包含调用者提供的代码,这些代码会在资源被正确管理的情况下执行。
scoped_guard
的功能scoped_guard
是对 __scoped_guard
的封装,简化了调用方式。它通过 __UNIQUE_ID(label)
自动生成唯一的标签 _label
,避免了手动指定标签的麻烦。
使用场景 这些宏通常用于以下场景:
锁管理 :在进入某个作用域时自动加锁,在离开作用域时自动解锁。
资源清理 :在作用域结束时自动释放资源(如文件句柄、内存等)。
异常安全 :确保即使在异常或错误路径中,资源也能被正确释放。
设计细节
作用域管理 :通过 for
循环和临时对象的生命周期,确保资源的获取和释放与作用域绑定。
条件判断 :通过 __guard_ptr
和 __is_cond_ptr
的组合,支持条件和无条件的资源管理。
灵活性 :调用者可以通过 args
传递参数,灵活地配置资源管理的行为。
总结 这段代码实现了一种高效且灵活的基于作用域的资源管理机制,类似于 C++ 的 RAII 模式。它通过宏和临时对象的结合,简化了资源管理的代码,同时减少了手动管理资源可能引入的错误。这种设计在需要严格控制资源生命周期的场景(如多线程编程中的锁管理)中非常有用。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 #define __guard_ptr(_name) class_##_name##_lock_ptr #define __is_cond_ptr(_name) class_##_name##_is_conditional #define __scoped_guard(_name, _label, args...) \ for (CLASS(_name, scope)(args); \ __guard_ptr(_name)(&scope) || !__is_cond_ptr(_name); \ ({ goto _label; })) \ if (0) { \ _label: \ break; \ } else #define scoped_guard(_name, args...) \ __scoped_guard(_name, __UNIQUE_ID(label), args)
include/linux/err.h: 提供 IS_ERR()、PTR_ERR() 等用于处理和判断指针中编码的错误码 IS_ERR_VALUE 判断指针是否是错误指针 1 2 3 4 5 6 7 #define IS_ERR_VALUE(x) unlikely((unsigned long)(void *)(x) >= (unsigned long)-MAX_ERRNO)
ERR_PTR 将错误码转换为指针 1 2 3 4 5 6 7 8 9 10 11 12 static inline void * __must_check ERR_PTR (long error) { return (void *) error; }
include/linux/args.h: 提供用于处理可变参数的宏 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 #define __COUNT_ARGS(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _n, X...) _n #define COUNT_ARGS(X...) __COUNT_ARGS(, ##X, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0) #define __CONCAT(a, b) a ## b #define CONCATENATE(a, b) __CONCAT(a, b)