目录
一、Linux内核概述
1.1内核与操作系统
编辑1.2Linux层次结构
1.3Linux内核特点
二、Linux内核源码结构
2.1Linux内核源码获取
2.2Linux内核源码结构
三、Linux内核源码的配置和编译
3.1Linux内核源码配置
3.3内核编译(以下命令均在内核源码的顶层目录下执行)
3.4测试内核和设备树
一、Linux内核概述
1.1内核与操作系统
内核是一个操作系统的核心,提供了操作系统最基本的功能,是操作系统工作的基础,决定着整个系统的性能和稳定性
操作系统是在内核的基础上添加了各种工具集、桌面管理器、库、shell、应用程序等
(我们使用的网络协议都是基于TCP/ip或者UDP/IP协议开发的)
(我们使用rm、mv、cp。。。这些命令都不是内核提供的)
这些命令其实都是一个个程序就和a.out一样
那为什么我们开发板上也能执行这些命令呢因为他们被复制一份放到了根文件系统里
shell翻译过来就是贝壳,他把内核很好的保护了起来。Linux内核内有文件管理系统。所以可以操作磁盘。那现在我们要操作一些文件就需要去操作内核让内核再去操作文件。但是内核很复杂,我们学到不透的时候一个误操作可能就会把内核搞坏了。所以我们操作shell让shell再去操作内核就会很安全了。
库这些lib也不是内核包含的。
图形化界面也不属于内核,内核本身只支持大黑框
安卓系统的内核也是Linux。所以学会Linux内核就能直接给手机做驱动,不需要会java。还有麒麟也是Linux内核。加上红旗操作系统也是。
1.2Linux层次结构
1.2.1进程管理
因为Linux是单核的所以不可能真正的并发
Linux基于操作系统时间片轮转调度机制让我们看起来是多进程同时执行。
比如五个进程每个都分别执行一毫秒这个时间非常短调度的很快就像是一起执行一样。
1.2.2内存管理
我们使用的都是虚拟内存其实都是由这块处理的,向下管理硬件,向上提供接口。
1.2.3文件系统
操作磁盘
1.2.4驱动管理
比如寄存器的配置什么的
1.2.5网络协议
管理网卡由linux内部网络协议栈来处理
但是嵌入式不会运行这么庞大的系统就是内核加点简单的东西因为要考虑成本。
我用华为路由器的时候就发现了,他的内存使用一直再75%左右。能省就省降低成本。
1.3Linux内核特点
二、Linux内核源码结构
2.1Linux内核源码获取
https://www.kernel.org/
选择http的下载链接
点击Linux
点击kernel(内核)
我们使用的是3.14点击v3.x
这里有很多直接ctr+F搜索我们需要的就行
主版本号.次版本号.修订版本
支持对应的硬件平台
相对成熟的版本(资料多)
稳定版本(次版本号为偶数的版本一般都是稳定版)
2.2Linux内核源码结构
把源码拖到ubuntu里解压
arch: 与CPU架构相关的源代码
(内核中没有board目录通过设备树来区分)
block:磁盘设备的支持 crypto:加密相关
drivers:设备驱动 firmware:固件
fs:文件系统 include:头文件
一般格式化磁盘都格式化成ntfs
init:内核初始化 ipc:进程间通信
共享内存消息队列什么的都是再ipc目录下实现的
kernel:内核核心调度机制等 lib:库
内核的核心算法。
mm:内存管理 net:网络协议
scripts:工具、脚本等 security:安全
usr:打包与压缩 virt:虚拟
sound:音频驱动不知道为什么没放到dirver里
COPYING: 版权
gpl版权,GNU开源协议
CREDITS: 内核贡献者
能被写进这里也不错。
README: 说明文档
很详细,从什么是Linux开始讲。
Documentation: 帮助文档
Makefile: 编译管理
samples: 示例
tools: 工具
Kconfig:内核自带的图形化界面
... ...
三、Linux内核源码的配置和编译
3.1Linux内核源码配置
在Linux内核源码顶层目录下的Makefile中指定(ARCH、CROSS_COMPILE)
可以通过make去配置,这里我们直接删了让他等于arm就行
下面那个制定成我们的arm-none-linux-gnueabi-
make <soc_name>_defconfig
arm架构下的不一样的架构汇编也不同所以光指定叫arm肯定不行,因为再arc/arm下只有叫exynos的没有exynos4412所以配置这里得按他们有的来
有个警告我看了一下好像是因为定义这个结构体的时候没初值。
def是默认的意思,这个操作是导入默认配置
上面提示写进了.config
看看这里到底是什么
最上面告诉我们这个是这个内核的配置文件,你不要去修改它
这里有2400多行,全是对一些变量进行赋值。
注1:soc_name为当前使用的处理器的名字
注2:内核源码的arch/arm/configs下对各个厂商的soc都有一个默认配置文件
执行该命令后就会将对应的配置文件中的信息导入到源码顶层目录下的.config
文件中CONFIG_xxx=y表示内核选中了该功能,内核编译时就会将该功能对应的
代码编译,内核的体积也会增大。#CONFIG_xxx is not set表示内核没有选中
该功能,内核编译时该功能对应的代码不会被编译,内核的体积也会减小。
默认配置只能保证内核拥有最基本的功能,我们需要根据自己的实际需求对内核做进一步的配置
方法1:
直接修改.config文件(不推荐)
太多了不好找,并且很多功能是有依赖关系的,要很熟,把最上层到最底层所需的全部东西都打开才能实现一共功能。
方法2:
make menuconfig
这些就是一些处理器的默认设置。
3.2make menuconfig
这是一个图形化界面
没配置过会报错,但是我有这个图形化的库
sudo apt-get install libncurses5-dev
[ ] 有两种状态
输入Y,显示“*”,内核中该功能被选中,相关代码会被编译进内核
输入N,显示“ ”,内核中该功能不被选中,相关代码不会被编译进内核
< > 有三种状态
输入Y,显示“*”,内核中该功能被选中,相关代码会被编译进内核
输入N,显示“ ”,内核中该功能不被选中,相关代码不会被编译进内核
输入M,显示“M”,内核中该功能被选为模块(被编译为独立的模块)
注:使用make mnuconfig配置的本质还是修改.config文件
再第一个选项里
() Cross-compiler tool prefix 选择交叉编译工具链。因为咱们前面把它设置的变量直接写成了我们需要的所以这个功能大概是丧失了。
这俩是进程间通信机制和交换文件交换分区做虚拟内存
红色mmu是虚拟内存用的,这S3c是指定用哪个串口打印信息
但是其实改不改都行,因为已经通过bootargs传递了使用串口2
按空格会切换状态
3.3内核编译(以下命令均在内核源码的顶层目录下执行)
make uImage
编译内核(编译选为“*”的选项到内核)
这个编译过程很久因为代码量太大了
cc就是gcc编译会将这些源码生成.o
这些.o会链接成一个vmlinux文件但是这个一个elf文件
然后链接一些自解压代码,因为我们最后装到板子上的其实是个压缩包
然后又通过objcopy命令把这个vmlinux做成zImage.bin文件
这个zImage是不被uboot识别的所以在这基础上要添加一些信息形成uImage
这步由mkimage来完成,如果没有这个工具最后会报错,这时候再uboot的tools目录下会出现这个工具,本来是没有的
把这个命令拷贝到usr/bin中
然后把这个文件改成最高权限再次编译成功就欧克了,根据提示信息在这个文件夹下找这个文件。我们看一下大小只有2.7MB
make modules
编译内核模块(编译选为“M”的选项为独立模块)
把dm9000网卡选择成M
这里就睡dm9000网卡驱动的源码,这里没有.o文件证明刚刚编译的时候没有编译
再来看dm9000的驱动文件
这次有.o文件了。证明被编译了
这个.ko的文件就是内核模块的意思。
make dtbs
编译设备树(将设备树源文件dts编译为二进制文件dtb)
再boot目录下有个dts里面都是设备树文件。
这里面有4412的设备树但是不是我们的
老办法咱们复制一份改一下
cp exynos4412-origen.dts exynos4412-fs4412.dts
修改makefile
我们之前复制了dts现在多了dtb文件
make clean
删除编译过程中产生的中间文件
3.4测试内核和设备树
把内核和设备树复制到tftp目录下
切换成emmc启动
他会卡死再这里
因为内核没有配置nfs,TCP/IP也没打开,网卡也用不了。
有同学可能会好奇这个tftp为什么,因为那时候还在运行uboot。