Linux内核的配置和编译

前言

以下内容基于2.6.35.7版本内核,文件资源:
https://download.csdn.net/download/weixin_44705391/15629906


uboot文章连载

Linux文章连载:
2.Linux内核的配置和编译原理
3.Linux内核的启动过程分析
4.Linux内核的移植实验-三星官方内核(了解)
5.根文件系统的原理
6.Linux根文件系统构建实验&busybox的移植


1.内核介绍

1.内核和发行版的区别
操作系统核心功能:内存管理、进程调度、文件系统
操作系统扩展功能:协议栈、有用的应用程序包。
(1)内核只有一个。www.kernel.org
(2)发行版有很多。譬如ubuntu、redhat、suse、centos······

2.内核和驱动的关联
(1)驱动属于内核的一部分。
(2)驱动是内核中的硬件设备管理模块。
(3)工作在内核态,对硬件有最高的使用权限。
(4)驱动程序故障可能导致整个内核崩溃。驱动程序漏洞会使内核不安全

3.内核和根文件系统的关联
(1)根文件系统提供根目录。其他文件系统挂载在根文件系统的节点下。
(2)进程1(用户态和内核态的交界处,可以理解为第一个应用程序,解释从内核态到用户态的细节)存放在根文件系统中
(3)内核启动最后会去装载根文件系统。
(4)总结:根文件系统为操作系统启动提供了很多必备的资源:根目录、进程1

4.linux内核的模块化设计
(1)linux内核很庞大,代码量很大,需要模块化设计
(2)模块化设计就是内核中各个功能模块在代码上是彼此独立的,譬如说调度系统和内存管理系统之间并没有全局变量的互相引用,甚至函数互相调用也很少,就算有也是遵循一个接口规范的。模块化设计的目的就是实现功能模块的松耦合。
(3)配置时可裁剪。linux内核在编译之前可以进行配置。
(4)模块化编译和安装。为了操作方便,逐渐从静态的升级变成了动态的升级(不需要重启系统,更不需要重新烧录系统)。这种动态的升级也是由模块化来支持的。
(5)源码中使用条件编译。这种在uboot中已经见过了。

2.linux内核源码目录结构

解压开源码文件 可看到:(绿色文件夹/文件对我们很重要)
(1)arch。架构。arch目录下是好多个不同架构的CPU的子目录,譬如arm这种cpu的所有文件都在arch/arm目录下,X86的CPU的所有文件都在arch/x86目录下。
(2)block。譬如说SD卡、iNand、Nand、硬盘等都是块设备。可以认为块设备就是存储设备。
(3)drivers。驱动
(4)firmware。固件
(5)fs。file system,文件系统
(6)include。公共的(各种CPU架构共用的)头文件都在这里。每种CPU架构特有的一些头文件在arch/arm/include目录及其子目录下。
(7)init。linux内核启动时初始化内核的代码。
(8)ipc。inter process commuication,进程间通信
(9)kernel
(10)lib。库,和c标准库类似,是内核重新实现供内核使用的,比如在内核中printf变成printk。
(11)mm。memory management,内存管理
(12)net。网络相关的代码,TCP/IP协议栈等
(13)scripts。辅助对linux内核进行配置编译生产的脚本。

(14)Kbuild,kernel build。linux内核特有的内核编译体系(重点,下面会讲)需要用到的文件。
(15)Makefile

简单讲一下linux内核的配置体系
(1)linux内核本身配置项有上千个,所以内核发明了一种体系用来配置:menuconfig方式:kernel文件夹下的Kbuild + 每个子文件夹下的Kconfig + menuconfig = 编译后生成.config文件,也就是linux内核特有的内核编译体系

3.内核配置和编译实验

先确认Makefile
(1)主要是检查交叉编译工具链有没有设置对。CROSS_COMPILE ?= /usr/local/arm/arm-2009q3/bin/arm-none-linux-gnueabi-
(2)确认ARCH = arm。为了编译时能找到arch/arm目录。
make x210ii_qt_defconfig
(1)最后只要出现:configuration written to .config,就证明操作是正确的。
make menuconfig
(1)可能出现的错误1:ncurses库没装
解决方案: apt-get install libncurses5-dev(参考了:http://blog.csdn.net/yao_qinwei/article/details/8805101
(2)可能出现的错误2:屏幕太小
解决方案:全屏,或者是把字体调小。
进入图形化界面,用来配置内核,EXIT按回车退出。
make
(1)可能出现的错误1:莫名其妙的错误,可以试试先make distclean
(2)代码本身的错误:具体问题具体分析
make之后出现

Can't use 'defined(@array)' (Maybe you should just omit the defined()?) at kernel/timeconst.pl line 373.

删掉kernel/timeconst.pl 文件中 373行的if (!defined(@val)) { 改为if (!@val) {
(3)编译完成后得到的内核镜像不在源码树的根目录下,在arch/arm/boot这个目录下。得到的镜像名是zImage

4.内核的配置原理

烧写测试:得到的镜像文件在kernel/arch/arm/boot/文件夹下
配置的关键是得到.config文件
和uboot配置时自动生成的autoconf.mk很像
make xx_defconfig和make menuconfig相配合
(1)第一步:make xxx_defconfig解决的问题是大部分的配置项(这一步结束后99%的配置项就已经正确了),之后就是针对开发板进行细节调整,通过make menuconfig来完成。
(2)make menuconfig其实就是读取第一步得到的.config,然后给我们一个图形化的界面,让我们可以更加容易的找到自己想要修改的配置项,然后更改配置他。
make menuconfig用来模块化编译,也就是剪裁一些需要的模块。
make xx_defconfig到底做了什么?
(1)make x210ii_qt_defconfig其实相当于:cp arch/arm/configs/x210ii_qt_defconfig .config
(2)arch/arm/configs目录下的这么多个xxx_defconfig哪里来的?其实这些文件都是别人手工配置好适合一定的开发板的.config文件后自己把.config文件保存过去的。

5.menuconfig

用法翻译:
(1)箭头按键导航整个菜单,回车按键选择子菜单(注意选项后面有 —>的选项才是有子菜单的,没有这个标识的没有子菜单),高亮的字母是热键(快捷键),键盘按键Y、N、M三个按键的作用分别是将选中模块编入、去除、模块化。双击ESC表示退出,按下?按键可以显示帮助信息,按下/按键可以输入搜索内容来全局搜索信息(类似于vi中的搜索),[]不可以模块化,<>的才可以模块化。
(2)注:linux内核中一个功能模块有三种编译方法:一种是编入、一种去去除、一种是模块化。所谓编入就是将这个模块的代码直接编译连接到zImage中去,去除就是将这个模块不编译链接到zImage中,模块化是将这个模块仍然编译,但是不会将其链接到zImage中,会将这个模块单独链接成一个内核模块.ko文件,将来linux系统内核启动起来后可以动态的加载或卸载这个模块。
(3)在menuconfig中选项前面的括号里,*表示编入,空白表示去除,M表示模块化

menuconfig本身由一套软件支持
(1)linux为了实现图形化界面的配置,专门提供了一套配置工具menuconfig。
(2)ncurses库是linux中用来实现文字式的图形界面,linux内核中使用了ncurses库来提供menuconfig
(3)scripts\kconfig\lxdialog目录下的一些c文件就是用来提供menuconfig的那些程序源代码。

menuconfig读取Kconfig文件
(1)menuconfig本身的软件只负责提供menuconfig工作的这一套逻辑(譬如在menuconfig中通过上下左右箭头按键来调整光标,Enter ESC键等按键按下的响应),而并不负责提供内容(菜单里的项目)。
(2)menuconfig显示的菜单内容(一方面是菜单的目录结构,另一方面是每一个菜单项目的细节)是由 内核源码树各个目录下的Kconfig文件来支持的 。Kconfig文件中按照一定的格式包含了一个又一个的配置项,每一个配置项在make menuconfig中都会成为一个菜单项目。而且menuconfig中显示的菜单目录结构和源码目录中的Kconfig的目录结构是一样的。
menuconfig读取/写入.config文件
(1)刚才已经知道menuconfig的菜单内容来自于Kconfig文件,但是每一个菜单的选择结果(Y、N、M)却不是保存在Kconfig文件中的。Kconfig文件是不变的,Kconfig文件只是决定有没有这个菜单项,并不管这个菜单项的选择结果。
(2)menuconfig工作时在我们make menuconfig打开时,他会读取.config文件,并且用.config文件中的配置选择结果来初始化menuconfig中各个菜单项的选择值。
总结:菜单项的项目内容从Kconfig文件来,菜单项的选择值从.config文件来

6.Kconfig文件详解

Kconfig的格式
例子:

config OPROFILE
	tristate "OProfile system profiling"
	depends on PROFILING
	depends on HAVE_OPROFILE
	select RING_BUFFER
	select RING_BUFFER_ALLOW_SWAP
	help
	  OProfile is a profiling system capable of profiling the
	  whole system, include the kernel, kernel modules, libraries,
	  and applications.

	  If unsure, say N.

(1)#开头的行是注释行
(2)menuconfig表示菜单(本身属于一个菜单中的项目,但是他又有子菜单项目)、config表示菜单中的一个配置项(本身并没有子菜单下的项目)。
(3)menuconfig或者config后面空格隔开的大写字母表示的类似于 NETDEVICES 的就是这个配置项的配置项名字,这个字符串前面 添加CONFIG_ 后就构成了.config中的配置项名字。
(4)一个menuconfig后面跟着的所有config项就是这个menuconfig的子菜单。这就是Kconfig中表示的目录关系。
(5)内核源码目录树中每一个Kconfig都会source引入其所有子目录下的Kconfig,从而保证了所有的Kconfig项目都被包含进menuconfig中。这个也告诉我们:如果你自己在linux内核中添加了一个文件夹,一定要在这个文件夹下创建一个Kconfig文件,然后在这个文件夹的上一层目录的Kconfig中source引入这个文件夹下的Kconfig文件。

tristate和bool的含义
(1)tristate意思是三态(3种状态,对应Y、N、M三种选择方式),bool是要么真要么假(对应Y和N)。
depends的含义
(1)depends中文意思是“取决于”或者“依赖于”,所以depends在这里的意思是:本配置项依赖于另一个配置项。如果那个依赖的配置项为Y或者M,则本配置项才有意义;如果依赖的哪个配置项本身被设置为N,则本配置项根本没有意义。
(2)depends项目会导致make menuconfig的时候找不到一些配置项。所以在menuconfig中如果找不到一个选项,但是这个选项在Kconfig中却是有的,则可能的原因就是这个配置项依赖的一个配置项是不成立的(被配置为N)。
(3)depends并不要求依赖的配置项一定是一个,可以是多个,而且还可以有逻辑运算。这种时候只要依赖项目运算式子的逻辑结果为真则依赖就成立。
select
A
select B
则在A被选中的情况下,B自动被选中
help
(1)帮助信息,告诉我们这个配置项的含义,以及如何去配置他。

Kconfig和.config文件和Makefile三者的关联
(1)配置项被配置成Y、N、M会影响.config文件中的CONFIG_XXX变量的配置值。
(2)这个.config中的配置值(=y、=m、没有)会影响最终的编译链接过程。如果=y则会被编入(built-in),如果=m会被单独连接成一个ko模块,如果没有则对应的代码不会被编译。那么这是怎么实现的?都是通过makefile实现的。
(3)obj-$(CONFIG_DM9000) += dm9000.o
如果CONFIG_DM9000变量值为y,则obj += dm9000.o,因此dm9000.c会被编译;如果CONFIG_DM9000变量未定义,则dm9000.c不会被编译。如果CONFIG_DM9000变量的值为m则会被连接成ko模块(这个是在linux内核的Makefile中定义的规则)

7.menuconfig的实验

验证menuconfig和.config的关系
(1)make menuconfig时,会读取.config中的配置值来初始化menuconfig中的配置项。
验证:如果理论正确的,那么我自己手工修改了.config的配置后,再次make menuconfig时看到的初始值就应该是我手工修改的。
(2)menuconfig中修改了(按Y、N、M)配置项的值,然后退出时保存,则这个保存结果会修改.config文件中的相应行。
验证:如果结论是正确的,那么在menucofig中修改了配置后保存退出,再次去手工打开.config文件则可以看到相应配置的一行内容被修改了。

7.2、验证menuconfig和Kconfig的关系
(1)menuconfig读取Kconfig的内容作为菜单项目内容。
验证1:在Kconfig中删除一个config项,则再次make menuconfig时就看不到这个项目了。
验证2:在Kconfig中自己添加创建一个config项,则再次make menuconfig时就能看到多了一个项目。

7.3、验证menuconfig和Makefile的关系
(1)我找一个模块,把他配制成y,然后去make编译连接,最后得到的zImage中这个模块就应该被编译连接进去到zImage中了。
验证:
方法一:去这个模块对应的源代码目录看一下这个源码有没有被编译
方法二:去zImage对应的elf格式的vmlinux中查看符号
方法三:将vmlinux反编译(objdump)后得到的文件中找模块对应的符号
方法四:将zImage下载到开发板中启动,启动后看你的模块能不能工作

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值