一.Linux内核介绍
1.内核介绍
1)Linux内核基本概念
Linux内核源码下载地址:https://www.kernel.org/
Linux内核指的是一个提供硬件抽象层、磁盘及文件系统控制、多任务等功能的系统软件。
注:通常我们使用的Linux系统是一个集Linux内核、工具集、各种库、桌面管理器、应用程序等一体的一个发布包(发行版)。
2)Linux核心功能
进程管理、内存管理、设备管理、文件系统、网络协议
3)Linux顶层目录介绍
COPYING:版权信息
CREDITS:光荣版,记录贡献
Kbuild:编译内核的相关脚本
Kconfig:配置内核的时候使用到脚本
MAINTAINERS:记录维护人员的信息
README:这个文档提供给开发者想要知道的如何编译内核的信息。
REPORTING-BUGS:这个文档提供如何报告问题的信息。
顶层目录文件夹介绍:
arch:包含和硬件体系结构相关的代码,每种架构占一个相应的目录
block:存放一些Linux存储体系中关于块设备管理的代码
crypto:存放内核本身所用的加密API,实现了常用的加密和散列算法,还有一些压缩和CRC校验算法
Documentation:帮助文档
drivers:驱动目录,这个目录是内核中最庞大的一个目录,里面分门别类的列出了Linux内核支持的所有硬件设备的驱动源代码
firmware:存放许多固件,一些硬件模块需要烧录固件才能运行。
fs:文件系统代码,里面列出了linux支持的各种文件系统的实现
include:头文件目录,公共的(各种CPU架构共用的)头文件都在这里。每种CPU架构特有的一些头文件在arch/***/include目录及其子目录下
init:存放linux内核启动时初始化内核的代码
ipc:进程间通信,存放linux支持的IPC的代码实现
kernel:内核中最核心的部分,包括进程的调度(sched.c),以及进程的创建和撤销(fork.c和exit.c)和平台相关的另外一部分核心代码在arch/***/kernel目录下
lib:lib是库的意思,这里面都是一些公用的库函数,注意这里的库函数和C语言的库函数不一样的。在内核编程中是不能用C语言标准库函数,这里的lib目录下的库函数就是用来替代那些标准库函数的。譬如在内核中要打印信息时不能用printf,而要用printk,这个printk就是我们这个lib目录下的
mm:内存管理代码,此目录包含了与体系无关的部分内存管理代码,与体系结构相关的内存管理代码位于arch/***/mm下
net:网络协议相关代码,譬如TCP/IP协议栈等都在这里
scripts:存放脚本文件,辅助对linux内核进行配置编译
security:系统安全相关代码
sound:音频处理相关代码
tools:编译内核的工具
usr:实现用于打包和压缩的cpio等
virt:此文件夹包含了虚拟化代码,它允许用户一次运行多个操作系统。通过虚拟化,客户机操作系统就像任何其他运行在Linux主机的应用程序一样运行。
2.一些概念
1)操作系统
宏内核:Linux将所有功能和代码封装在一起
微内核:功能和代码不封装在一起(鸿蒙)
2)关系
ios基于unix(购买了unix版权加以修改)
Linux基于unix
Ubuntu属于虚拟机
android = Linux内核+JAVA虚拟机+JAVA程序
3).config
Y:编译内核
M:编译并加载内核
N:不编译内核
二.Linux内核配置步骤
1.导入配置文件
Linux源码顶层终端输入:make exynos4_defconfig ,当导入配置文件后,会生成 .config 文件,.config是配置文件,编译内核时会根据该配置文件来进行选择编译。
我们使用的是Tiny4412开发板,开发板厂商(友善之臂公司)已经为我们提供了针对该开发板的配置文件,就是在Linux源码顶层目录下的tiny4412_linux_defconfig文件。
我们导入这个配置文件,将tiny4412_linux_defconfig文件放在arch/arm/configs目录下,然后在顶层目录下输入命令:make tiny4412_linux_defconfig,生成配置文件。我们也可以直接将tiny4412_linux_defconfig文件拷贝到当前目录,重名为.config,即输入:cp tiny4412_linux_defconfig .config,也可以生成配置文件。
2.二次配置
sudo apt-get install ncurses-dev
make menuconfig
tiny4412开发板来说,要去掉一个内核编译选项(内核的一个保护机制),然后保存退出
System Type -->
[ ] Support TrustZone-enabled Trusted Execution Environment
3.编译内核
在编译内核映像之前,我们需要执行以下两个操作:
指定交叉编译工具
打开顶层目录下的Makefile,将第197行代码改成如下所示:
修改kernel/timeconst.pl文件
打开kernel/timeconst.pl文件,将第373行代码的defined去掉,然后保存退出。
注:如果不修改该文件,编译时会报错
编译生成内核镜像
输入命令:make zImage -j4
注:Linux内核源码编译过程大概需要20~30分钟。
4.烧写LInux内核
将SD卡连接Linux系统,跳转到Linux源码arch/arm/boot/目录下,然后执行以下命令:
dd iflag=dsync oflag=dsync if=./zImage of=/dev/sdb seek=1057(扇区)(因为使用movi指令是从1057开始读,如果不使用movi,只需要从uboot后(BL1+BL2+270 以后开始搬))
5.引导加载内核
将SD卡插入到Tiny4412开发板上,启动u-boot,进入交互模式,对环境变量bootcmd进行修改,输入以下命令:set bootcmd "movi read kernel 0 0x40008000;bootm 0x40008000";然后输入save命令保存环境变量,重启u-boot或直接输入命令boot,来引导加载内核。
注意:movi指令是对mmc指令的封装。Linux内核不是二进制文件,不能使用go,只能使用bootm(解析bootcmd命令)
下列三者等价
set bootcmd "movi read kernel 0 0x40008000;bootm 0x40008000"; 。
set bootcmd "mmc read 0 0x40008000 0x421 0x244F;bootm 0x40008000" (从0x421开始读0x244F加载到0x40008000)
set bootcmd " fatload mmc 0 0x40008000 zImage;bootm 0x40008000"
三.通过menu菜单编译新的内核驱动
General setup(常规设置):
交差编译器:Cross-compiler tool prefix
内核子版本号:Local version - append to kernel release 配置后在主版本号添加子版本号
该选项的下一个配置为是否自动添加子版本号到主版本号后面
配置PANIC超时时间:Default panic timeout //配置内核死掉时候多长时间会重启,一般为默认5s
配置嵌入式系统支持:Embedded system
Enable loadable module support
配置支持模块强制加载功能: //配置第二项即可
System Type(系统类型):
处理器配置:ARM system type //选择不同的处理器,会出现不同的子菜单
开发板配置:SAMSUNG EXYNOS SoCs Support //这里的每个选项其实对应着一块开发板支持文件:
arch/arm/mach-exynos/mach-xxx.c文件,选中后对应的文件会被编译
处理器特征配置:Processor Features//与配套的uboot有关
Kernel Features(处理器特征):
配置内核空间和用户的比例:Memory split //用户空间与内核空间是可以配置的
配置CPU的处理器数量:Maximum number of CPUs //单核CPU就没有该选项
配置EABI接口支持:Use the ARM EABI to compile the kernel
//嵌入式应用二进制接口,(很重要,ARM芯片都要求选择)
Boot options(启动选项):
配置内核启动参数:Default kernel comma string
//u-boot如果传递bootargs参数,则会覆盖这里的设置,没够传递bootargs,就使用这里定义的参数。
FLoating point emulation(浮点仿真):
配置浮点数仿真库支持:至少选择一种仿真支持//arm芯片不支持硬浮点时,程序运行到fpa硬浮点指令,会出现指令异常,便会陷入到内核里,这时这个模拟浮点处理器就来模拟这些浮点指令
Userspace binary formats(用户空间二进制格式):
配置系统支持ELF格式可执行文件(可选):Kernel support for ELF binaries //默认
配置系统支持a.out格式可执行文件(可选):Kernel support for a.out and ECOFF binaries //默认
Device Drivers (设备驱动):
Device Drivers菜单描述设备驱动:
根据自己需要配置,也是工作重心,
里面的菜单都是驱动配置,根据自己硬件情况选择。
File systems(文件系统):
配置文件系统类型支持(ext3支持):Ext3 journalling file system support
配置文件系统类型支持(ext4支持):The Extended 4(ext4)filesystem
配置文件系统类型支持(fat支持):DOS/FAT/NT Filesystems/VFAT(Windows-95) fs support
配置文件系统类型支持(NTFS支持)DOS/FAT/NT Filesystems/NTFS file system support
配置网络文件系统支持(NFS文件系统):Network File Systems/NFS client support
配置本地语言编码支持(配置简体中文):Native language support/ Simplified Chinese charset (CP936, GB2312)
配置utf-8编码支持(这个一般要选择):Native language support/NLS UFT-8
Kernel hacking
printk打印时间戳:Show timing information on printks
注:Linux内核可以根据自己的需要自主裁剪。配置菜单中,每一个选项都对应一块内核源码。
1.Linux内核菜单概述
在内核源码每一层目录下都会有两个文件:
Kconfig:组成make menuconfig 的菜单选项,以及.config中的宏名(Kconfig中定义,体现在.config)
Makefile:引用.config配置(最终使用的)Kconfig中定义菜单,Makefile根据菜单名对应的宏名抽取对应的C代码进行编译。
最终定义了三个变量obj-y obj-m obj-
这三个变量保存了一堆的文件名
obj-y所代表的文件一律被编译进内核
obj-m所代表的文件一律被编译成模块
obj-所代表的文件一律不参与编译。
在menuconfig进行配置并保存退出后,会影响到.config中变量的值
子Makefile添加变量影响到.config
最终生成make zImage
2.菜单项语法
config <symbol>
<config options>
<symbol>为一符号,就好像代码中的局部变量x一样,可用于后边的表达式中,该行都是以关键字开始。“config”为定义了一新的配置选项。下面的几行<config options>定义了该配置选项的属性,属性可以是该配置选项的类型,输入提示,帮助信息和默认值等。
在顶层目录下Kconfig追加以下信息
添加以上菜单后,配置选中,再打开.config文件,可以发现其中多了一项CONFIG_XYD_TEST=y
当不选择时,会在.config文件中生成# CONFIG_XYD_TEST is not set
所以,Kconfig和.config的关系是:在Kconfig中定义的每一项菜单中的config关键字后面的宏名在.config文件中都会自动添加CONFIG_做前缀。
注:每个Kconfig菜单项都会产生一个配置选项CONFIG_XXX,XXX即为<symbol>。此配置选项的值记录在内核根目录下的隐藏文件.config。除了.config文件,在内核源码子目录下的Makefile中,也会使用到这些配置选项CONFIG_XXX(CONFIG_XXX在Makefile不会自动生成,是提前定义好的),子目录的Makefile通过这些配置选项与源码c文件进行相关联。
3.菜单选项类型
bool:y 和 n
tristate:y m n
string类型表示需要用户输入一串字符串。
int类型表示用户输入一个整型。
hex类型则需要用户输入一个16进制数。
4.编译新的驱动到内核
1) 新建驱动文件
cp tiny4412_hello_module.c csy4412_hello_module.c
2)在makefile内加入该驱动文件对应选项
3)在Kconfig内加入该驱动文件对应选项
4)make menuconfig配置把该驱动直接加载到内核
5)执行make zImage
四.设置开机LOGO
开机启动logo;
先拿一张图片(1024*600 x710 ),改224(imge->mode->index) 改成ppm格式(选择ASCII启动),将这样logo移动到/home/xyd/tool/linux-3.5/drivers/video/logo
打开该目录下的Kconfig,添加一个菜单 在顶级目录make menuconfig选择这个图片对应的y(driver-graphics-bootuplogo) 保存退出,查看顶级目录下的.config 对应的宏是否y
修改logo 下的logo.c
#ifdef CONFIG_LOGO_BACK_CLUT224
/* Generic Linux logo */
logo = &logo_back_clut224;
#endif
跳到include linux/linux_logo.h
加入extern const struct linux_logo logo_back_clut224;
在logo.c 的打开Makefile,追加obj-$(CONFIG_LOGO_BACK_CLUT224) += logo_back_clut224.o
顶层目录编译make zImage -j2