阅读Linux源码:在一堆同名的头文件中找到正确的头文件

阅读Linux源码:在一堆同名的头文件中找到正确的头文件

1. 提出问题

大家在阅读Linux源码时,是否会遇到类似的问题:#include后面是相对路径,无法确定具体包含的是哪个头文件。

举个例子:arch/arm64/kernel/sys.c包含的#include <asm/unistd.h>头文件,具体是哪个呢?
arch/arm64/include/asm/unistd.h
arch/arm64/include/uapi/asm/unistd.h

在这里插入图片描述

2. 个人经验

分享一下个人经验哈,如果大家有更好的办法可以留言。

  1. 先把内核编译通过,例如
make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- -j16
  1. 修改一下arch/arm64/kernel/sys.c时间戳
touch arch/arm64/kernel/sys.c
  1. 重新编译一次,加上 V=1
make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- -j16 V=1

此次编译会重新编译arch/arm64/kernel/sys.c文件,在编译输出中,搜索关键字sys.c可以找到完整的编译命令,如下图。我是使用mobaxterm进行搜索。
在这里插入图片描述

  1. 从上述输出中整理出-I选项,得到gcc搜索头文件的先后顺序,如下:
  -I./arch/arm64/include 
  -I./arch/arm64/include/generated  
  -I./include 
  -I./arch/arm64/include/uapi 
  -I./arch/arm64/include/generated/uapi 
  -I./include/uapi 
  -I./include/generated/uapi 

在编译Linux内核或用户空间程序时,使用-I选项来指定头文件的搜索路径。这些路径的顺序代表头文件被优先使用的顺序。

3. 优先级特征分析

  1. 本地架构特定头文件:首先搜索的是架构特定(这里是ARM64)的头文件目录,包括生成的和非生成的:

    • -I./arch/arm64/include
    • -I./arch/arm64/include/generated
  2. 通用头文件:接着是通用的头文件路径,适用于所有架构:

    • -I./include
  3. 架构特定用户API头文件:然后是架构特定的用户API头文件,同样分为生成的和非生成的:

    • -I./arch/arm64/include/uapi
    • -I./arch/arm64/include/generated/uapi
  4. 通用用户API头文件:最后是通用的用户API头文件路径:

    • -I./include/uapi
    • -I./include/generated/uapi

优先级特征

  • 先架构后通用:优先考虑架构特定的头文件,之后才是通用的。这保证了针对特定架构的优化和特性可以覆盖掉通用实现。
  • 先非生成后生成:在同一级别的目录中,先查找非生成的头文件,再查找生成的头文件。这是因为生成的文件通常依赖于当前配置,并且可能包含对编译过程至关重要的信息。
  • 先uapi外后uapi内:对于每个级别的目录,先查找标准头文件,然后再查找用户API(uapi)相关的头文件。这是因为uapi文件专为用户空间程序设计,而标准头文件则可能包含了更底层或更广泛的定义。

综上所述,编译器会按照上述顺序依次查找所需的头文件。如果同一个头文件出现在多个路径中,那么最先匹配到的那个会被使用。

4. 解决问题

到这里,就可以回到最初的问题了
arch/arm64/kernel/sys.c包含的#include <asm/unistd.h>头文件,具体是哪个呢?
arch/arm64/include/asm/unistd.h
arch/arm64/include/uapi/asm/unistd.h

一定是先搜索到的arch/arm64/include/asm/unistd.h !

依次类推,层层的包含关系,都会非常清楚:

arch/arm64/kernel/sys.c
->#include <asm/unistd.h>即arch/arm64/include/asm/unistd.h
->#include <uapi/asm/unistd.h>即arch/arm64/include/uapi/asm/unistd.h
->#include <asm-generic/unistd.h>即include/asm-generic/unistd.h
->#include <uapi/asm-generic/unistd.h>即include/uapi/asm-generic/unistd.h

如果你有更好的方法,可以留言讨论!感谢点赞关注!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值