ITPub博客

首页 > Linux操作系统 > Linux操作系统 > 高效学习Linux内核——从源码中的宏下手

高效学习Linux内核——从源码中的宏下手

原创 Linux操作系统 作者:ningmengzier 时间:2020-12-14 10:56:11 0 删除 编辑

在阅读Linux内核代码时,在代码的开头总是有各种各样的宏定义,了解熟悉这些宏定义,对于代码的理解和快速修改代码提供了便利。 有些宏相对简单,一眼便可以了解作用,有些就稍微复杂一些,需要一些逻辑。 今天就给大家总结了一些常见的宏定义,帮助大家更快,更好的理解内核代码。

什么是宏

在 C 语言中,可以采用命令  #define  来定义宏。该命令允许把一个名称指定成任何所需的文本,例如一个常量值或者一条语句。在定义了宏之后,无论宏名称出现在源代码的何处,预处理器都会把它用定义时指定的文本替换掉。

替换列表和标识符列表都是将字符串 token 化以后的列表。区别在于标识符列表使用,作为不同参数之间的分割符。每一个参数都是一个 token 化的列表。在宏中空白符只起到分割 token 的作用,空白符的多少对于预处理器是没有意义的。

内核中常见的宏

__CONCAT宏 

"##"用于粘贴两个参数,"#"用于替换参数:


 BUILD_BUG_ON宏 

!!(e) 对 e 的结果进行两次求非。如果e为0,则结果为0;如果 e 不为0,则结果为1。所以上述表达式的结果有两种:

1. condition为真时,sizeof(char[-1]),产生错误,编译不通过;
2. condition为假时,sizeof(char[1]),编译通过。
例如,在飞凌嵌入式i.MX6Q开发板的3.0.35的内核中,/driver/usb/storage/uas.c/usb接口u盘的驱动中就有使用该宏。

 BUILD_BU G_ON_ZERO(e) 宏

检查表达式e是否为0,为0编译通过且返回0;如果不为0,则编译不通过。

如果e为0,则该结构体拥有一个int型的数据域,并且规定它所占的位的个数为0。

如果e非0,结构体的int型数据域的位域将变为一个负数,产生语法 的错误。

 typecheck宏 
该宏在 /include/linux/typecheck.h中定义

用于检查x是否为type类型,如果不是会抛出(warning: comparison of distinct pointer types lacks a cast)例如,在内核中/include/linux/rwlock.h中便使用到了该宏,用于读写锁的定义中。

__is_constexpr宏

判断 x 是否为整数常量表达式:如果 x 是常量表达式,则 (void )((long)(x) 0l) 是一个空指针常量,就会使用第三个操作数即 ((int *)8) 的类型。如果不是常量表达式,则会使用第二个操作数 void 类型。

 roundup宏

该宏在 /include/linux/kernel.h 中被定义。

返回一个能够整除 y 并且大于 x ,最接近 x 的值,向上取整,可用于地址的内存对齐。

 clamp 宏


判断 val 是否在 lo 和 hi 的范围内,如果小于 lo ,返回 lo ,如果大于 hi 则返回 hi ,如果在 lo 和 hi 之间就返回 val 。

  swap 宏


利用 typeof 获取要交换变量的类型。

 container_of宏 

根据一个结构体变量中的成员变量来获取整个结构体变量的指针。

 ALIGN对齐宏 


对齐是采用上对齐的方式,例如 0x123 以 16 对齐,结果是 0x130 ,因为对齐常在分配内存时使用,所以分配的要比需要的大。

 mdelay宏 


忙等待函数,在延迟过程中无法运行其他任务,会占用 CPU 时间,延迟时间是准确的。

总结

像开头说的,内核源码中有各种各样的宏,在这里不能一一罗列。宏的使用使得代码开发更加标准化,了解更多的宏,无疑可以更好的更深入的理解代码含义,如对此有兴趣,可在网上搜索更多的内核宏,了解更多关于Linux内核的知识。

以上,是飞凌攻城狮给大家分享的关于Linux内核源码中的宏的内容,希望大家看到有所收获,指出问题共同进步,在飞凌的技术支持和分享中获得更多的知识。


来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/69989353/viewspace-2741935/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论

注册时间:2020-11-25

  • 博文量
    327
  • 访问量
    139442