内核头文件使用

原地址:http://blog.chinaunix.net/uid-20543672-id-3162485.html

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


  1. */2.6.37/include/linux/types.h:13:2: warning: #warning "Attempt to use kernel headers from user space, see http://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(用户)目录下的原因。

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值