可以在用户空间中使用的内核头是什么?它们的签名或接口是否与不同目录中的标头不同?

可以在用户空间中使用的内核头是什么?它们的签名或接口是否与不同目录中的标头不同?

这可能是一个关于内核头的不连贯的问题,因为我对它以及它的使用地点和方式没有清楚的了解。我认为它可能会被标记。我的问题有 3 个部分:

  1. 我认为内核头提供了一个接口,以便内核的其他部分(例如模块)可以使用它们。这就是我的书本知识。我还没有看到或发现任何使用内核头的代码(如果有人能指出我,我将不胜感激)。它也可以在用户空间中使用吗?任何代码示例将不胜感激。

  2. 我发现使用make headers_install内核头是由用户空间公开的,但同时不鼓励在用户空间中使用内核头。如果不鼓励,那么将其暴露给用户空间有什么用呢?

  3. 按照,内核头文件(.h 文件)应该位于 3 个位置:/usr/include/linux/kernel.h用于用户空间 b./lib/modules/$(uname -r)/build/include/linux/sched.h这是外部模块 c./usr/src/...用于内核模块这是否意味着不同目录中的头文件具有不同的用途或不同的接口或签名?换句话说,#include <linux/xyz.h> 用户空间代码中的含义与#include <linux/xyz.h>内核模块中的含义是否不同?外部模块与内核模块相同吗?

谢谢。

答案1

欢迎来到 Unix 和 Linux StackExchange!

是的,内核头为内核的其他部分提供了一个接口 - 在这一点上你是完全正确的。它们还包括内核和用户空间之间接口的定义 - 但通常不直接使用“原始”内核接口,而是通过 C 库(通常glibc)使用。

出于向后兼容性的原因,用户空间-内核接口可以包括特定系统调用的多个版本。通过 C 库进行系统调用,所有应用程序都会获得相同版本的实际系统调用,从而保证行为的一致性。此外,当内核接口的相关部分更新时,您只需更新 C 库即可利用新功能。

(例如,当 time_t 在 32 位架构中扩展到 64 位以避免 Y2K38 问题时,C 库可能会始终使用 64 位版本的内核接口,但具有用户空间可配置的应用程序映射那时,使用 32 位 time_t 的函数可以被废弃并从内核中删除,并且 C 库可以为仍然使用 32 位类型的遗留应用程序提供更好的解决方法。)

因此,除非您也在 C 库中编译自己的版本,否则您通常应该更喜欢 C 库的开发头文件,而不是直接使用内核头文件。

头文件/usr/include/linux/通常与 C 库的开发头包一起提供,并描述 C 库编译的内核版本。这是用户空间应用程序开发人员通常需要的。

/lib/modules/$(uname -r)/build/usr/src/...通常是指向实际运行的内核版本的标头或完整源代码存储位置的符号链接。它在编译外部(也称为第三方)内核模块时使用,即来自未集成到主内核源代码的源的内核模块。这些标头包含必要的内核 API 版本签名,以便模块可以使用特定于版本的内核内部 API。

相关内容