CONFIG_HZ在哪里定义的?

CONFIG_HZ在哪里定义的?

我正在阅读全文Linux 5.0.7源代码,我注意到一些奇怪的事情。我将linux在这里称为父目录,如果社区在文献中使用其他命名约定,请纠正我。

在文件中,使用linux/include/asm-generic/param.h该值。CONFIG_HZ该值未在前面的行中定义,唯一包含的文件是uapi/asm-generic/param.h.我相信这是指linux/include/uapi/asm-generic/param.h,如果我错了,请再次纠正我。

在该文件中,没有CONFIG_HZ定义过这样的值。现在,在普通的 C 程序中,这会导致错误。我们这里有 3 个选择:

  • 我误解了一些东西,linux/include/asm-generic/param.h实际上包含了定义该值的另一​​个文件。
  • 这是一个错误,我是发现它的天才(最不可能的选择)。
  • 有一些“魔法”正在发生,比如 Linux 之前定义的一些宏,或者内核之前包含的一些文件,包括linux/include/asm-generic/param.h定义值的位置,这样当linux/include/asm-generic/param.h调用时值就已经定义了。在这种情况下,请告诉我这个文件是什么。

如果这些都不成立,那么为什么这是一个正确的 C 程序?

答案1

与其他CONFIG_值一样,CONFIG_HZ是一个配置设置;你会发现它在kernel/Kconfig.hz,以及其他Kconfig文件中的各种特定于架构的覆盖。它的值在构建期间确定并存储在生成的配置文件include/generated/autoconf.h.

后者包含在内核的构建命令中。要查看其实际效果,请选择一个包含 的文件asm/param.h,并详细地构建其后处理后的等效项;例如

make drivers/atm/suni.i V=1

在构建的某个时刻你会看到

gcc -E -Wp,-MD,drivers/atm/.suni.i.d  -nostdinc \
    -isystem /usr/lib/gcc/x86_64-redhat-linux/8/include \
    -I./arch/x86/include -I./arch/x86/include/generated \
    -I./include -I./arch/x86/include/uapi \
    -I./arch/x86/include/generated/uapi -I./include/uapi \
    -I./include/generated/uapi \
    -include ./include/linux/kconfig.h \
    -include ./include/linux/compiler_types.h ...
    -DMODULE  -DKBUILD_BASENAME='"suni"' -DKBUILD_MODNAME='"suni"' \
    -o drivers/atm/suni.i drivers/atm/suni.c

您可以在 中看到结果drivers/atm/suni.i,并且展开HZCONFIG_HZ

-include ./include/linux/kconfig.h指令确保始终包含内核配置。include/linux/kconfig.h包括generated/autoconf.h.

答案2

许多程序(例如 vim 或 firefox)都有许多编译选项。由于不同的原因你可以或必须在编译时选择一些选项。

对于 Linux,你有一个完整的系统:config家族make 配置目标以逻辑分层方式配置 Kconfig“符号”,并提供良好的解释(在线帮助)。因为存在很多平台内和平台外的依赖关系。即使只是通过分页或 grep 这些“散布”各处的 Kconfig* 文件,您也可以获得基本信息(“如果不确定,请说是”,“如果您从未听说过 X,只需选择否”)

我很难从里面找到这个“HZ” make nconfig。最后是F8“SymSearch”,输入“HZ”(有或没有 CONFIG_ 它说 - 这非常用户友好!),你会得到如下搜索结果:

    | Symbol: HZ_100 [=n]                                                                                                                                                                                                                                                                         
    | Prompt: 100 HZ                                                                                                                                             
    |   Location:                                                                                                                                             
    |     -> Processor type and features                                                                                                                       
    |       -> Timer frequency (<choice> [=y])                                                                                                                 
    |   Defined at kernel/Kconfig.hz:19

所以定时器频率是“处理器类型...”的子菜单。此 ncurses 弹出“窗口”包含“HZ 定义在哪里”的相关信息。 (“位置:”和“定义于”)


只需检查这 19 个 Kconfig 所在的位置(它们的目录名称),您就会得到一个好印象。Kconfig.hz./kernel/其中之一。

  ]# find kernel mm block init ipc -name "Kconfig*" |wc
     19      19     376

因此,在您从 kernel/Kconfig.hz (一个单独的文件!)中选择时间片(“jiffy”)值后,make将以某种方式(Kbuild)为实际的编译器gcc调用做好准备。 (详情请参阅其他答案)。

所以是的,某种魔法,一个用于 gcc 预处理器的自制预处理器(部分是 C 源代码!)。

CONFIG_xxx 主要用作布尔#ifdefs(条件编译——与 if...else 正交)。


...阅读整个 Linux 5.0.7 源代码的中间

]# find arch/x86/ include -name param.h   

arch/x86/include/uapi/asm/param.h
include/uapi/linux/param.h
include/uapi/asm-generic/param.h
include/asm-generic/param.h

“创造魔法”和“头汤”之间有一条微妙的界限。感谢您的提示,我找到了一个不错的 find-prune-grep 序列。了解#preprocessor 和 CONFIG_ 是一回事。有时需要一些蛮力;对于完整搜索,修剪 drivers/ 通常是一个好主意。通过包含所有 arch/* 目录,这表明 alpha 是多么特殊。

以及 param.h 中的 asm 通用“#define HZ”的精确度:

]# find -name drivers -prune -o -name '*.[ch]' -exec grep "\<CONFIG_HZ\>" {} +  

./arch/alpha/kernel/time.c:     clockevents_config_and_register(ce, CONFIG_HZ, 0, 0);
./arch/alpha/kernel/time.c:#if CONFIG_HZ == 1024 || CONFIG_HZ == 1200
./arch/alpha/kernel/time.c:#elif CONFIG_HZ == 256 || CONFIG_HZ == 128 || CONFIG_HZ == 64 || CONFIG_HZ == 32
./arch/alpha/kernel/time.c:     sel = RTC_REF_CLCK_32KHZ + __builtin_ffs(32768 / CONFIG_HZ);
./arch/alpha/kernel/time.c:                    CONFIG_HZ, sel);
./arch/alpha/kernel/setup.c:#if CONFIG_HZ == 1024 || CONFIG_HZ == 1200
./arch/alpha/kernel/setup.c:    timer_freq = 100UL * CONFIG_HZ;
./arch/alpha/include/asm/param.h:# define HZ  CONFIG_HZ

./arch/ia64/include/asm/param.h:# define HZ  CONFIG_HZ

./include/asm-generic/param.h:# define HZ  CONFIG_HZ  /* Internal kernel timer frequency */

(我只触及了空白)

结果make config(直接和间接 Kconfig 选择)最终在 /proc 中(如果此选项为 Y ;):

]# zcat /proc/config.gz |grep CONFIG_HZ

# CONFIG_HZ_PERIODIC is not set
# CONFIG_HZ_100 is not set
# CONFIG_HZ_250 is not set
CONFIG_HZ_300=y
# CONFIG_HZ_1000 is not set
CONFIG_HZ=300

相关内容