内核头文件

来源:互联网 发布:matlab行程01矩阵 编辑:程序博客网 时间:2024/05/08 17:31

英文的原来的网址:http://kernelnewbies.org//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 namedglibc-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.

Tell others about this page:

翻译后:中文

网址:http://blog.chinaunix.net/uid-28663607-id-3552656.html

昨天,同事在编译应用层程序(V4L2相关)的时候出现了一个这样的警告:


  1. */2.6.37/include/linux/types.h:13:2: warning: #warning "Attempt to use kernel headers from user space, seehttp://kernelnewbies.org/KernelHeaders"
     然后问我这个怎么消除。我也是第一次注意到这个警告(以前可能有出现,可能我没有注意吧)。然后我根据后面提供的网址,研读了一下这份英文资料,发现这个原来是头文件的使用不当产生的。英文资料翻译如下:

  1. 内核头文件

  2. Linux内核中的头文件用于两个目的:

  3. 1、定义内核组件间的接口,和
  4. 2、定义内核与用户空间的接口

  5. 内部模块

  6. 模块间的内部接口在linux/include/ 或 linux/arch/*/include/ 下都有定义。一个单独模块的源文件间的接口应该同模块源码置于同一目录下,避免污染全局头文件空间。

  7. 外部模块

  8. 为了编译外部内核模块,你需要来自该模块所针对内核的头文件。Driver porting: compiling external modules 解释了如何编写一个外置的Makefile来使用这些头文件。照此做法,内核Makefile将为源码和编译目录自动选择正确的包含路径,并从正确的构架中使用include/asm头文件。

  9. 传统的内核源码安装在/usr/src/linux下,这不再支持外部模块的编译。相反,你的Makefile应该指向/lib/modules/${kver}/build,其中${kver}是内核确切的版本字符串,例如:对于当前正在运行的内核,就是“uname -r”的输出。

  10. 用户空间程序

  11. 一般来说,用户空间程序是针对发行版提供的头文件编译的,通常源于glibc-devel、glibc-kernheaders 或 linux-libc-dev。这些头文件通常来源于旧版内核,并不能安全地在不重新编译glibc的情况下被替换。特别地,作为一个到/usr/src/linux/include或/lib/modules/*/build/include/linux的符号链接/usr/include/linux,是极不推荐使用的。因为它经常使重新编译的应用程序损坏。例如,旧内核使用include/asm-${arch}存放架构特定的头文件,而不是现在的arch/${arch}/include/asm ,且没有符号链接到架构特定的目录。

  12. 为一个发行版打包头文件正确的方法是在内核源码目录下运行 'make headers_install'来安装头文件到/usr/include,并依赖这个刚刚安装的特定版本的内核头文件重新编译C库包。

  13. 如果你正在发布一个依赖某个特定版本内核头文件的用户空间程序,比如因为你的程序只运行在打过补丁或者最新的内核上,你不能依赖/usr/include中的头文件。你也不能使用来自/usr/src/linux/include 或/lib/modules/*/build/include/的头文件,因为他们还没有为用户空间的包含做好准备。若你尝试这么做了,内核会警告你并指引你到这个Wiki页。解决这个问题的正确方法是独立出你需要的特定接口,比如一个打过补丁的新内核并为你的应用程序提供字符设备ioctl号的独立头文件。在你自己的程序中添加一份这个源文件的拷贝,并说明这个应该和新内核版本保持一致。如果你的程序不遵循GPLv2证书,请保证你得到了这个文件作者的许可:可在你自己程序的证书下发布它。因为你的程序现在依赖的内核接口并不在常规内核中。在这种情况下,一个推荐的做法是通过运行时检测来保证内核知道这个接口并在无法向下兼容旧接口的时候给出有用的错误信息。

   看了这个说明,我就明白了,我同事直接使用了内核源码中没有处理过的头文件。而我一般都是使用编译器中自动包含的头文件,那个是通过'make headers_install'安装的,所以一般不会出这样的警告。

   后来,我让同事使用以下的方法解决了这个警告

  1. 1、在内核源码根目录下运行: 'make headers_install',这样内核Makefile会把提供给应用程序的头文件提取并放在内核源码的“usr/include”目录下。
  2. (请勿担心git会发现文件增加了,usr目录中的.gitignore文件已经让git忽略了其下的include文件夹)

  3. 2、在编译应用程序的时候,在GCC的CFLAG参数中添加“-I(内核源码路径)/usr/include”,这样编译器就知道在编译时找到相关的头文件了。
----------------------------------------------------------------------------------------------
  平时我们在编译应用程序的时候,不可避免的会使用内核头文件,比如v4l2,字符驱动等等。此时直接的使用内核源码中include目录下的头文件,可能就会有警告。这个警告现在看来仅在"include/linux/types.h"中存在,因为这个文件中包含了很多内核自定义的类型,你的应用程序如果也做了这样的定义就可能出现问题。此时你就应该使用内核帮你处理过的专门提供给用户空间的头文件,这个就是为什么'make headers_install'会将头文件(默认)放在usr(用户)目录下的原因。

  关于这个头文件的问题,其实是有一段历史故事的:《内核头文件传奇》。挺有意思的,大家看过后就知道内核头文件的使用为什么是这样了。