一、为什么须要内核编译
二、电脑的开发环境
三、源码编译过程
四、源码包的构架
五、内核源码目录与重点文件
六、drviers目录
一、为什么须要内核编译
内核源码的Documentationkbuildmodules.txt说明文档有以下日文描述:
=== 2. How to Build External Modules
To build external modules, you must have a prebuilt kernel available
that contains the configuration and header files used in the build.
Also, the kernel must have been built with modules enabled. If you are
using a distribution kernel, there will be a package for the kernel you
are running provided by your distribution.
翻译如下:
假如须要编译外部的内核模块,这时侯我们必须拥有一个早已预先成功编译好的内核,在编译内核过程当中,它会生成内核模块所须要的头文件和配置文件。
当前使用了一个发布版本的内核,如当前的内核为linux-3.4.39-gec,这么这个时侯开发板的内核也得是linux-3.4.39-gec,若版本不一致,内核模块难以进行加载。
二、电脑的开发环境
虚拟机:VMWare12.0以上
操作系统:Ubuntu16.04
芯片源码包:6818_kernel_wen.tar.gz,包含交叉编译工具、kernel源码、镜像制做工具。
三、源码编译过程
对于源码包的编译,切换到root用户进行操作。
#sudo -s
(一)解压6818_kernel_wen.tar.gz到ubuntu的家目录
root@ubuntu:~# tar -zxvf /mnt/hgfs/share/6818_kernel_wen.tar.gz -C ~
root@ubuntu:~# ls
6818GEC
(二)编译kernel
1.编译命令
./mk -k
2.成功编译后的输出信息
Kernel: arch/arm/boot/Image is ready //生成内核的Image
Kernel: arch/arm/boot/zImage is ready //将Image压缩为zImage镜像
UIMAGE arch/arm/boot/uImage //编译内核的时候,调用uboot的工具生成uboot专用的内核镜像
Image Name: Linux-3.4.39-gec //镜像的版本
Created: Tue Oct 30 19:14:55 2020 //创建时间
Image Type: ARM Linux Kernel Image (uncompressed)
Data Size: 5532560 Bytes = 5402.89 kB = 5.28 MB //镜像的大小
Load Address: 40008000 //uboot加载内核到内存的地址
Entry Point: 40008000 //内核运行的入口地址
Image arch/arm/boot/uImage is ready
boot.img -> /home/gec/6818GEC/out/release //烧写到emmc中的内核镜像
(三)问题汇总
问题1
生成boot.img文件出现错误,make_ext4fs说没有这个文件或目录,问题如下:
Image arch/arm/boot/uImage is ready
boot.img -> /home/arm/6818GEC/out/release
'/home/arm/6818GEC/kernel/arch/arm/boot/uImage' -> '/home/arm/6818GEC/out/target/product/GEC6818//boot/uImage'
make_ext4fs -s -T -1 -l 67108864 -a boot /home/arm/6818GEC/out/target/product/GEC6818//boot.img /home/arm/6818GEC/out/target/product/GEC6818//boot
/home/arm/6818GEC/out/host/linux-x86/bin/mkuserimg.sh:
line 84: /home/arm/6818GEC/out/host/linux-x86/bin/make_ext4fs: No such file or directory //没有这个文件或目录
'/home/arm/6818GEC/out/target/product/GEC6818//boot.img' -> '/home/arm/6818GEC/out/release/boot.img'
解决如下:
才能从里面见到make_ext4fs为32位程序,所以我们需要让64位机支持执行32位应用。运行以下两条命令就可以解决这个问题:
sudo apt-get install lib32c-dev lib32stdc++6
接着重新编译内核,显示如下正确的信息:
Image arch/arm/boot/uImage is ready
boot.img -> /home/arm/6818GEC/out/release
'/home/arm/6818GEC/kernel/arch/arm/boot/uImage' -> '/home/arm/6818GEC/out/target/product/GEC6818//boot/uImage'
make_ext4fs -s -T -1 -l 67108864 -a boot /home/arm/6818GEC/out/target/product/GEC6818//boot.img /home/arm/6818GEC/out/target/product/GEC6818//boot
Creating filesystem with parameters:
Size: 67108864
Block size: 4096
Blocks per group: 32768
Inodes per group: 4096
Inode size: 256
Journal blocks: 1024
Label:
Blocks: 16384
Block groups: 1
Reserved block group size: 7
Created filesystem with 18/4096 inodes and 4134/16384 blocks
'/home/arm/6818GEC/out/target/product/GEC6818//boot.img' -> '/home/arm/6818GEC/out/release/boot.img'
问题2
若ubuntu空间不够,会造成编译提示硬碟空间不够,提示关键字为“....Nospace”。
.................
/home/gec/6818GEC/prebuilts/gcc/linux-x86/arm/arm-eabi-4.8/bin/arm-eabi-ld: final link failed: No space left on device
Makefile:873: recipe for target '.tmp_vmlinux1' failed
make: *** [.tmp_vmlinux1] Error 1
使用"df-h"命令详尽如下,可以晓得/dev/sda1硬碟空间不够。
gec@ubuntu:~/6818GEC$ df -h
Filesystem Size Used Avail Use% Mounted on
udev 955M 0 955M 0% /dev
tmpfs 198M 3.2M 194M 2% /run
/dev/sda1 20G 19.9G 8.0K 99.9% /
tmpfs 986M 0 986M 0% /dev/shm
.............
解决方式1:
删掉ubuntu多余的文件
解决方式2:
使用虚拟机拓展ubuntu的硬碟空间
四、源码包的构架
(一)mk脚本文件
root@ubuntu:~/6818GEC# file mk
mk: Bourne-Again shell script, ASCII text executable
该mk是一个脚本文件,通过这个shell脚本就才能编译内核。
(二)拓展剖析
1.关于路径
#
# Some Directories
#
BS_DIR_TOP=$(cd `dirname $0` ; pwd) ---->取 $0参数当前的路径,给BS_DIR_TOP变量进行赋值
BS_DIR_RELEASE=${BS_DIR_TOP}/out/release
BS_DIR_TARGET=${BS_DIR_TOP}/out/target/product/GEC6818/
BS_DIR_KERNEL=${BS_DIR_TOP}/kernel
2.关于kernel的配置文件
#
# Target Config
#
BS_CONFIG_KERNEL=GEC6818_defconfig //编译kernel的配置文件
配置文件的作用:告诉编译器应该按照配置文件的配置信息来进行编译
3.功能函数
build_kernel()
{
#添加tools路径到环境变量PATH,生成uImage依赖该目录下的mkimage
export PATH=${BS_DIR_TOP}/tools:$PATH
# Compiler kernel
#进入内核源码的目录
cd ${BS_DIR_KERNEL} || return 1
#编译内核生成最原始的内核镜像:uImage
make -j${threads} ARCH=arm CROSS_COMPILE=${BS_CROSS_TOOLCHAIN_KERNEL} uImage || return 1
# Copy uImage to release directory
#cp -v ${BS_DIR_KERNEL}/arch/arm/boot/uImage ${BS_DIR_RELEASE}
# generate boot.img
#生成最终的内核镜像文件boot.img
cd ${BS_DIR_TOP} || return 1
echo 'boot.img ->' ${BS_DIR_RELEASE}
# Make boot.img with ext4 format, 64MB
cp -v ${BS_DIR_KERNEL}/arch/arm/boot/uImage ${BS_DIR_TARGET}/boot
#利用mkuserimg.sh脚本文件来把原有内核镜像文件转换成以 ext4格式的内核镜像:boot.img
mkuserimg.sh -s ${BS_DIR_TARGET}/boot ${BS_DIR_TARGET}/boot.img ext4 boot 67108864
#拷贝boot.img到输出目录下
cp -av ${BS_DIR_TARGET}/boot.img ${BS_DIR_RELEASE} || return 1;
return 0
}
4.关于功能函数的调用
#分析传入的参数1,即./mk -k,-k就是参数1
while [ "$1" ]; do
case "$1" in
-j=*)
x=$1
threads=${x#-j=}
;;
-k|--kernel)
kernel=yes
;;
esac
shift
done
#如果变量kernel的值为yes,则build_kernel函数会被调用
if [ "${kernel}" = yes ]; then
build_kernel || exit 1
fi
root@ubuntu:~/6818GEC# ls
kernel mk out prebuilts prototype tools
5.kernel
内核源码
6.out
编译成功后输出镜像的目录
7.prebuilts
编译uboot和内核使用到的交叉编译工具
8.prototype
三星公司提供的一些底层源码,拿来支持编译uboot和内核源码
9.tools
一些工具linux内核烧写,如mkimage(专门将zImage制作为uImage的工具,在内核测试的时侯可以使用uImage)。
五、内核源码目录与重点文件
1.目录
/arch。arch是architecture的简写。arch目录下是很多个不同构架的CPU的子目录,例如arm这些cpu的所有文件都在arch/arm目录下,X86的CPU的所有文件都在arch/x86目录下。
/block。是块的意思,在linux中block表示块设备,块设备是以数据块形式接收和发送的数据的设备。比如说SD卡、iNand、Nand、硬盘等都是块设备。几乎可以觉得块设备就是储存设备。block目录下放的是一些linux储存体系中关于块设备管理的代码。
/crypto。是加密的意思。这个目录下放了内核本身所用的加密API,实现了常用的加密和散列算法,还有一些压缩和CRC校验算法。
/Documentation。上面放了一些帮助文档。
/drivers。驱动目录,这个目录是内核中最庞大的一个目录,上面分门别类的列举了linux内核支持的所有硬件设备的驱动源代码。
/firmware。固件。哪些是固件?固件似乎是软件,不过这个软件是固化到IC上面运行的,为了了让计算机读取和理解从设备发来的讯号的代码,如同S55PVPV210里的iROM代码。
/fs。fs就是filesystem,文件系统,上面列举了linux支持的各类文件系统的实现。
/include。头文件目录,公共的(各类CPU构架共用的)头文件都在这儿。每种CPU构架特有的一些头文件在arch/***/include目录及其子目录下。
/init。init是初始化的意思,这个目录下的代码就是linux内核启动时初始化内核的代码。
/ipc。ipc就是interprocesscommuication,进程间通讯linux更改ip地址,上面都是linux支持的IPC的代码实现。
/kernel。kernel就是内核,内核中最核心的部份,包括进程的调度(sched.c),以及进程的创建和撤消(fork.c和exit.c)和平台相关的另外一部份核心代码在arch/***/kernel目录下。
/lib。lib是库的意思,这儿面都是一些公用的库函数,注意这儿的库函数和C语言的库函数不一样的。在内核编程中是不能用C语言标准库函数,这儿的lib目录下的库函数就是拿来取代这些标准库函数的。例如要把字符串转成数字用atoi,内核编程中只能用lib目录下的atoi函数linux内核烧写,不能用标准C语言库中的atoi。诸如在内核中要复印信息时不能用printf,而要用printk,这个printk就是我们这个lib目录下的。
/mm。mm是memorymanagement,显存管理,此目录包含了与体系无关的部份显存管理代码。与体系结构相关的显存管理代码坐落arch/***/mm下。
/net。该目录下是网路相关的代码,例如TCP/IP合同栈等都在这儿。
/scripts。脚本,这个目录下全部是脚本文件,这种脚本文件不是linux内核工作时使用的,而是拿来辅助对linux内核进行配置编译生产的。当运行makemenuconfig或则makexconfig之类的命令配置内核时,用户就是和坐落这个目录下的脚本进行交互的。
/security。安全相关的代码。对计算机免予遭到病毒和黑客的侵犯很重要。
/sound。音频处理相关的。
/tools。linux中用到的一些有用工具
/usr。实现用于打包和压缩的cpio等。这个文件夹中的代码在内核编译完成后创建这种文件。
/virt。此文件夹包含了虚拟化代码,它容许用户一次运行多个操作系统。通过虚拟化,顾客机操作系统如同任何其他运行在Linux主机的应用程序一样运行。
2.根目录下的一些单独文件:
COPYING:许可和授权信息。Linux内核在GPLv2许可证下授权。该许可证授予任何人有权免费去使用、修改、分发和共享源代码和编译代码。但是,没有人可以转让源代码。
CREDITS:贡献者列表。
Kbuild:是kernelbuild的意思,就是内核编译的意思,设置一些内核设定的脚本。打个比方,这个脚本设定一个ARCH变量,这是开发者想要生成的内核支持的处理器类型。
Kconfig:这个脚本会在开发人员配置内核的时侯用到。
MAINTAINERS:这是一个目前维护者列表,她们的电子电邮地址,主页,和她们负责开发和维护的内核的特定部份或文件。当一个开发者在内核中发觉一个问题linux修改文件名,并希望才能报告给才能处理这个问题的维护者时,这是是很有用的。
Makefile:这个脚本是编译内核的主要文件。这个文件将编译参数和编译所需的文件和必要的信息传给编译器。
README:这个文档提供给开发者想要晓得的怎么编译内核的信息。
REPORTING-BUGS:这个文档提供怎样报告问题的信息。
六、drviers目录
熟悉各种驱动在源码树中的大约位置,能帮助在开发过程中快速进行驱动源码查找和定位。一个系统究竟用了什么代码,与系统本身外设相关,也与显卡配置文件相关。
drivers/gpio 系统 GPIO 子系统和驱动目录,包括处理器内部 GPIO 以及外扩 GPIO 驱动。遵循 GPIO 子系统的驱动,可通过/sys/class/gpio 进行访问
drivers/hwmon 硬件监测相关驱动,如温度传感器、风扇监测等
drivers/i2c I2C子系统驱动。各 I2C 控制器的驱动在 i2c/busses 目录下
drivers/input 输入子系统驱动目录
drivers/input/keyboard 非HID键盘驱动,如GPIO键盘、矩阵键盘等
drivers/input/touchscreen 触摸屏驱动,如处理器的触摸屏控制器驱动、外扩串行触摸屏控制器驱动、串口触摸屏控制器驱动等
drivers/leds LED 子系统和驱动,如 GPIO 驱动的 LED。遵循 LED 子系统的驱动 ,可通过/sys/class/leds 进行访问
drivers/mfd 多功能器件驱动。如果一个器件能做多种用途,通常需要借助 MFD 来完成。例如 am3352 的 adc 接口,可同时做 adc 和触摸屏控制器,所以需要实现MFD接口驱动
drivers/misc 杂项驱动。特别需要关注目录,提供了i2c和spi接口的EEPROM 驱动范例,所驱动的设备可通过/sys 系统访问
drivers/mmc sd/mmc卡驱动目录
drivers/mtd MTD子系统和驱动,包括NAND、oneNAND等。注意,UBI的实现也在MTD中
drivers/mtd/nand NAND FALSH的MTD驱动目录,包括NAND的基础驱动和控制器接口驱动
drivers/net 网络设备驱动,包括MAC、PHY、CAN、USB网卡、无线、PPP协议等
drivers/net/can CAN设备驱动。Linux 已经将 CAN 归类到网络中,采用 socket_CAN 接口
drivers/net/ethernet 所支持的 MAC 驱动。常见厂家的 MAC 驱动都能找到,如 broadcom、 davicom、
marvell、 micrel、 smsc 等厂家的 MAC,处理器自带 MAC 的驱动也在该目录下
drivers/net/phy PHY 驱动,像 marvell、 micrel 和 smsc 的一些 PHY 驱动
drivers/rtc RTC 子系统和 RTC 芯片驱动
drivers/spi SPI子系统和 SPI 控制器驱动,含 GPIO 模拟 SPI 的驱动
drivers/tty TTY 驱动
drivers/tty/serial 串口驱动,包括 8250 串口以及各处理器内部串口驱动实现
drivers/uio 用户空间 IO 驱动
drivers/usb USB 驱动,包括 USB HOST、 Gadget、 USB 转串口以及 OTG 等支持
drivers/video Video 驱动,包括 Framebuffer 驱动、显示控制器驱动和背光驱动等。有的移植代码会将液晶屏配置通放在显卡控制器驱动目录下,例如 omap2 系列的 LCD 配置代码在目录下
drivers/video/backlight 背光控制驱动
drivers/video/logo Linux 内核启动 LOGO 图片目录
drivers/watchdog 看门狗驱动,包括软件看门狗和各种硬件看门狗驱动实现
记录点点嘀嘀的笔记欢迎关注,共同学习
小浩笔记