【Linux】编译用于exynos4412(ARM)的Linux-3.14内核
零、准备
1、下载
Linux-3.14内核源代码
- 下载页面:https://www.kernel.org/pub/linux/kernel/v3.x/
- 下载链接:https://www.kernel.org/pub/linux/kernel/v3.x/linux-3.14.tar.xz
下载后得到以下文件:
bash
yu@Yubuntu:~/kernel$ ls -l
总计 76568
-rw-rw-r-- 1 yu yu 78399152 4月 9 01:21 linux-3.14.tar.xz

2、解压
bash
yu@Yubuntu:~/kernel$ tar -vxf linux-3.14.tar.xz
解压后得到如下文件:
bash
yu@Yubuntu:~/kernel$ ls -l
总计 76572
drwxrwxr-x 23 yu yu 4096 3月 31 2014 linux-3.14
-rw-rw-r-- 1 yu yu 78399152 4月 9 01:21 linux-3.14.tar.xz
壹、编译
1、设置CPU架构和交叉编译器
设置CPU架构和交叉编译器的方法有几种,临时设置、通过环境变量设置和修改Makefile
设置。基于实际情况,在本次编译中,我希望我把我修改好的内核发给别人同样有效,而且我只针对一种CPU指令集来配置的,所以我选择修改Makefile
。
使用vi
编辑Makefile
:
bash
yu@Yubuntu:~/kernel$ cd linux-3.14/
yu@Yubuntu:~/kernel/linux-3.14$ vi Makefile
把198、199行的
makefile
ARCH ?= $(SUBARCH)
CROSS_COMPILE ?= $(CONFIG_CROSS_COMPILE:"%"=%)
改为
makefile
ARCH ?= arm
CROSS_COMPILE ?= $(CONFIG_CROSS_COMPILE:"%"=%)

保存并退出~
注:这里关于交叉编译器的安装和配置就不再介绍了。
2、设置处理器
使用如下命令设置处理器:
bash
yu@Yubuntu:~/kernel/linux-3.14$ make exynos_defconfig
难搞,报警告了,具体情况如下:
bash
In file included from scripts/kconfig/zconf.tab.c:2537:
scripts/kconfig/menu.c: In function 'get_symbol_str':
scripts/kconfig/menu.c:587:46: warning: 'jump' may be used uninitialized in this function [-Wmaybe-uninitialized]
587 | jump->offset = strlen(r->s);
| ~~~~~~~~~~~~~^~~~~~~~~~~~~~
scripts/kconfig/menu.c:548:26: note: 'jump' was declared here
548 | struct jump_key *jump;
| ^~~~
没关系,Linux论坛上已有解决方案了:
https://patchwork.kernel.org/project/linux-kbuild/patch/[email protected]/
我们按照这个页面上的来修改我们的代码:
bash
yu@Yubuntu:~/kernel/linux-3.14$ vi scripts/kconfig/menu.c
把548行的struct jump_key *jump;
改为struct jump_key *jump = NULL;
:
把586行的if (head && location && menu == location)
改为if (jump && menu == location)
(由于我上一个修改我是注释掉原有行,再在下面添加的新行,所以这边我的第二个位置显示的是587行了):
保存退出~
重新使用如下命令设置处理器:
bash
yu@Yubuntu:~/kernel/linux-3.14$ make exynos_defconfig

搞定!
3、配置Linux系统内核
Linux系统内核的配置文件在上一个步骤中,被我们写到了.config
文件中了,感兴趣的同学可以打开看看,很复杂,新手不建议修改。对于大多数情况,我们可以使用Linux内核源码这边给我们提供的配置工具来配置,配置工具在README
中有介绍,大致有这么些:
其中,我们比较常用的是make menuconfig
,对于远程使用SSH连接的同学友好些。
但是它需要一些依赖,可以使用如下命令安装对应的依赖:
bash
sudo apt-get install libncurses5-dev
libncurses5-dev
是一个基于文本的GUI开发库,用于支持在C等编程语言中开发基于文本终端的交互式应用程序,提供了屏幕绘制、键盘输入处理等功能。
另外,make menuconfig
对屏幕大小有一定要求,把当前命令窗口拉伸到最大后执行如下命令开始配置:
bash
yu@Yubuntu:~/kernel/linux-3.14$ make menuconfig

界面上方的文本即是使用帮助,同学们可以自己阅读一下,本文不介绍如何配置Linux内核,同学们根据自己的需要在此界面修改好Linux内核配置后再往下。

配置并保存成功~
4、编译Linux系统内核
因为是针对的exynos4412编译的Linux内核,而exynos4412使用的引导程序是U-Boot,所以把编译好的Linux内核文件封装成uImage格式是比较好的选择。
uImage是一种经过封装的内核镜像格式,它在嵌入式系统中较为常用,特别是使用U-Boot作为引导加载器的系统。这种格式在普通的内核镜像基础上添加了一个头部信息,该头部信息包含了镜像的加载地址、入口地址、镜像大小等内容,便于U-Boot识别和加载内核。
命令make uImage
的意思是让make
工具依据Makefile
里的规则来构建uImage格式的内核镜像。
那么,我们执行如下代码开始编译Linux系统内核:
bash
yu@Yubuntu:~/kernel/linux-3.14$ make uImage
难搞,刚开始编译就报错了:
bash
/usr/bin/ld: scripts/dtc/dtc-parser.tab.o:(.bss+0x50): multiple definition of `yylloc'; scripts/dtc/dtc-lexer.lex.o:(.bss+0x0): first defined here
collect2: error: ld returned 1 exit status
make[2]: *** [scripts/Makefile.host:127:scripts/dtc/dtc] 错误 1
make[1]: *** [scripts/Makefile.build:455:scripts/dtc] 错误 2
make: *** [Makefile:527:scripts] 错误 2
经查询,是因为GCC版本太高了导致的,我们可以稍作修改,使用如下命令编辑dtc-lexer.lex.c_shipped
文件:
bash
yu@Yubuntu:~/kernel/linux-3.14$ vi scripts/dtc/dtc-lexer.lex.c_shipped
在640行,在YYLTYPE yylloc;
前面加上extern
,即把YYLTYPE yylloc;
改为extern YYLTYPE yylloc;
:
保存并退出。
重新编译:
bash
yu@Yubuntu:~/kernel/linux-3.14$ make uImage
好,这次编译了大概3分钟,现在又又出错了:
bash
"mkimage" command not found - U-Boot images will not be built
make[1]: *** [/home/yu/kernel/linux-3.14/arch/arm/boot/Makefile:80:arch/arm/boot/uImage] 错误 1
make: *** [/home/yu/kernel/linux-3.14/arch/arm/Makefile:305:uImage] 错误 2
本次出错的原因在于找不到mkimage
命令,我们需要安装U-Boot工具(u-boot-tools
),这个是用于U-Boot引导加载程序的辅助工具集,可帮助我们进行U-Boot的配置、编译、调试以及映像文件处理等工作。
我们使用如下命令安装U-Boot工具:
bash
sudo apt-get install u-boot-tools

好,继续编译:
bash
yu@Yubuntu:~/kernel/linux-3.14$ make uImage
经过大约4分钟,编译完成~
编译好的文件在arch/arm/boot
目录下:
5、编译内核模块
在使用make menuconfig
配置Linux内核时,有的功能被设置为模块(M
),模块不会在上一个步骤被编译进内核,我们需要单独编译,使用如下命令开始编译内核模块:
bash
yu@Yubuntu:~/kernel/linux-3.14$ make modules
编译内核模块成功:
其中,以.ko
结尾的即为内核模块(Kernel Object)文件。
我们将来在Linux中可以使用insmod
或modprobe
命令来加载.ko
内核模块,使用rmmod
命令卸载内核模块。
6、查看编译耗时
使用如下命令可以查看编译耗时:
bash
yu@Yubuntu:~/kernel/linux-3.14$ $(which time) -v make uImage
