KernelHeaders 内核头文件

KernelHeaders

Header files in the Linux kernel are used for two purposes: 
1.to define interfaces between components of the kernel, and

2.to define interfaces between the kernel and user space

Internal modules

Internal interfaces between modules are defined anywhere in below linux/include/ or linux/arch/*/include/. Interfaces between source files in a single module should be put into the same directory as the module source code, which avoids polluting the global header space.

External modules

In order to build external kernel modules, you need the exact version of the headers from the kernel that the modules are built for.

http://lwn.net/Articles/21823/ explains how to write an external Makefile to use those headers. When you do this, the kernel Makefiles will automatically choose the correct include path for both source and build directory and for using the include/asm headers from the right architecture.

While traditionally the kernel source was installed in /usr/src/linux, this is no longer supported for building external modules. Instead, your Makefile should point to /lib/modules/${kver}/build, where ${kver} is the exact version string of the kernel, e.g. the output of uname -r for the currently running kernel.

User space programs

In general, user space programs are built against the header files provided by the distribution, typically from a package named glibc-devel, glibc-kernheaders or linux-libc-dev. These header files are often from an older kernel version, and they cannot safely be replaced without rebuilding glibc as well. In particular, installing /usr/include/linux as a symbolic link to /usr/src/linux/include or /lib/modules/*/build/include/linux is highly discouraged as it frequently breaks rebuilding applications. For instance, older kernels had the architecture specific header files in include/asm-${arch} instead of arch/${arch}/include/asm and had on a symlink to the architecture specific directory.

The correct way to package the header files for a distribution is to run 'make headers_install' from the kernel source directory to install the headers into /usr/include and then rebuild the C library package, with a dependency on the specific version of the just installed kernel headers.

If you are distributing a user space program that depends on a specific version of some kernel headers, e.g. because your program runs only on patched or very recent kernels, you cannot rely on the headers in /usr/include. You also cannot use the header files from /usr/src/linux/include or /lib/modules/*/build/include/ because they have not been prepared for inclusion in user space. The kernel should warn you about this if you try it and point you to this Wiki page. The correct way to address this problem is to isolate the specific interfaces that you need, e.g. a single header file that is patched in a new kernel providing the ioctl numbers for a character device used by your program. In your own program, add a copy of that source file, with a notice that it should be kept in sync with new kernel versions. If your program is not licensed under GPLv2, make sure you have permission from the author of that file to distribute it under the license of your own program. Since your program now depends on kernel interfaces that may not be present in a regular kernel, it's a good idea to add run-time checks that make sure the kernel understands the interface and give a helpful error message if there is no fallback to an older interface. 

=======================================================================================

译文:

内核的头文件有两个用途:
1.定义内核组件之间的接口
2.定义内核和用户空间之间的接口

内部模块

模块之间的内部接口在 linux/include 或者 linux/arch/*/include 处定义。一个模块自身的接口定义文件,应该被放在与自身源文件相同的一个目录里,以防止弄乱全局头文件空间中的头文件。(译者注:比如模块里有个头文件叫做types.h,定义的是模块自身中的某种应用类型,但这个名字的头文件也是一个标准头文件,如果把模块自身的这个头文件放在全局头文件空间的目录中,则在使用标准types.h头文件的程序在包含types.h时,编译器会不确定到底要包含那一个types.h头文件)

外部模块

为了构建外部模块,你需要确定精确的目标内核头文件版本号。http://lwn.net/Articles/21823/ 解释了如何编写一个使用这些头文件的外部模块的Makefile。当你做这件事的时候,内核的Makefiles会在操作内核代码树目录和模块构建目录时自动的选择正确的include/asm硬件体系结构的包含路径。传统的内核代码树被安装在/usr/src/linux中,这已经不再支持构建外部模块了。取而代之的是,你的Makefile应该指向/lib/modules/${kver}/build,${kver}是精确的内核版本字符串,比如使用 uname -r 命令输出的就是你当前正在运行的系统的内核版本号。

用户空间程序

一般而言,用户空间程序使用发行版提供的头文件来构建,典型的是由一个叫做glibc-devel,glibc-kernheaders或者linux-libc-dev的软件包提供。这些头文件经常是一个老版本内核的头文件,如果这些头文件被替换了,而不重新构建你的glibc,那将会是不安全的。特别是把/usr/include/linux作为一个符号连接到/usr/src/linux/include或者/lib/modules/*/include/linux时,那将会在重新构建一些应用程序时会频繁的报错中断。举个例子,老版本内核的硬件体系结构声明头文件在include/asm-${arch},而不是arch/${arch}/include/asm,并且也没有到硬件体系结构声明目录的符号连接。

给一个发行版设置正确内核头文件的方式是在你的内核代码树中运行 make headers_install命令,这会把头文件放置于/usr/include中,并且重新构建C库,以解决对指定版本内核头文件的依赖问题。

如果你正在发布一个依赖特定版本内核的用户空间应用程序,例如你的应用程序只可以运行于打过补丁的内核或者只可运行于较新的内核,那样你就不能使用/usr/include中的头文件。

你也不能用/usr/src/linux/include 或者 /lib/modules/*/build/include中的头文件,因为他们不是为用户空间应用程序包含而准备的。

如果你试图这样做,内核就会警告你,并引导你访问这个Wiki页面。正确解决这个问题的方法是将你需要的头文件分离出来,例如你程序中使用的一个新内核补丁中提供的为字符设备提供ioctl号的头文件。在你自己的程序中,加入这个源文件的拷贝。当然注意要保持这个文件与新版本内核中的保持相同。如果你的程序不遵循GPLv2,就要确保在得到这个源文件作者的许可的情况下发布你的应用程序。一旦你的应用程序依赖的内核接口在某个版本的内核中不支持时,有一个运行时的检查将会是个好的做法,那样确保了内核如果不向后兼容这个接口,可以给出详细的错误消息。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值