内核回顾

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Peter_tang6/article/details/77505690

起初只是简单的了解了内核移植的一个过程,现在再来梳理一下个人的理解。对于Linux内核,其功能之强大,结构之复杂,没有个几年的时光估计是搞不明白的,本篇文章主要是理解一下内核的一个启动流程以及一些关于内核的问题解答。

Linux内核启动过程

1、架构/开发板相关的引导过程,通常使用汇编来编写,首先检查内核是否支持当前架构的CPU处理器,然后检查是否支持当前的开发板,只有通过这两部分的确认,为调用下一步C代码做准备

2、这是一个所有内核的通用启动过程,因为无关硬件信息了,这一阶段用C语言编写,进行内核的初始化全部工作,最后调用rest_init函数启动init进程,创建系统的第一个用户进程:init进程

Linux内核目录代码

Arch:与体系架构相关的目录,对于每个架构的CPU,arch下面都有一个对应的子目录
Block:块设备的通用函数
Drivers:设备驱动程序(此部分占用内核大部分空间)
Firmware:硬件驱动,闭源设备的代码
Sound:声卡驱动
FS:支持的文件系统类型代码
Include:头文件
Init:内核的初始化代码
IPC:进程间通信的代码,管道,共享内存,消息队列,信号量等
Kernel:内核管理的核心代码,与处理器相关的核心代码在arch/* /kernel
Mm:与硬件无关的内存管理代码,与硬件相关的内存管理代码在arch/* /mm
Net:网络协议
Lib:库文件,内核中使用的库都是自己实现的,不会使用C库
Doucumention:当前版本内核文档,对于英语基础好的有较强的参考价值

Arch/arm/boot下是存放编译好的内核镜像文件,关于镜像文件,有三种:
1、Image:未压缩,经过arm-linux-objcopy处理后生成只包含内核数据的内核镜像文件
2、zlmage:内核的映像压缩文件,文件大小为Image的一半
3、uImage:64字节头 + zImage,前64字节说明内核的版本,加载位置,生成时间和大小等信息<
4、Vmlinux:在内核的根目录下,未压缩的ELF 格式的内核映像/font>

那么为什么有这么多镜像文件呢?为什么要压缩映像文件?其实这里主要是从内核启动的时间来考虑,Image加载内存的时间要大于zImage加载内存(包括解压缩的时间),zImage运行之前,会有一个自解压的工作,相关代码在arch/arm/boot/compressed下。

在arm目录下每一个mach-*.c都对应一个开发板的平台文件,在做移植的时候要将这个文件通读,看看支持哪些硬件外设。在每个目录下基本上都有Makefile和Kconfig之类的文件,可见内核的代码就是这样一个一个搭起来的,在顶层的Makefile中,我们要指定交叉编译器,便于我们编译。内核的自解压工作在arch/arm/boot/compressed/head.S中,这里是一段汇编代码,关于协处理器以及一些寄存器的操作,因为本人不懂汇编,这里就不述说,有兴趣的朋友可以去看看,内核真正的开始运行是在Arch/arm/kernel/head.S中进行的,这里还是汇编代码。。。。。。。很尴尬。最后就开始挂载根文件系统,启动init进程

在内核源码目录下执行make menuconfig时能看见配置菜单,当然,别忘了配置一下显示:export TERM=vt100。这里进行内核的裁剪,配置内核的功能,配置完成后,将结构保存到配置文件.config中(执行Save an Alternate Configuration File即可),然后编译。

关于我们如何添加一个自己的配置文件,Kconfig文件用于生成配置内核的界面,是各种配置文件的源文件,内核的配置工具通过读取各个目录下的Kconfig文件

这里用cramfs文件系统做个例子:

File systems —>
[*] Miscellaneous filesystems —>
<*> Compressed ROM file system support (cramfs)
CONFIG_CRAMFS=y

扫描二维码关注公众号,回复: 3048702 查看本文章

然后进入/fs/cramfs/Kconfig

1 config CRAMFS
2 tristate “Compressed ROM filesystem support (cramfs)”
3 depends on BLOCK
4 select ZLIB_INFLATE
5 help
6 Saying Y here includes support for CramFs

1.config CRAMFS
//生成变量CONFIG_CRAMFS
2.tristate “Compressed ROM filesystem support (cramfs)”
//CONFIG_CRAMFS的取值范围 <*><>
3.depends on
//当前定义CONFIG_CRAMFS依赖于BLOCK变量
4.select
// ZLIB_INFLATE变量依赖CONFIG_CRAMFS
5.help
帮助信息

Kconfig语法规则:
1. config条目:用于生成一个配合选项,这个会连同它的值一起被写入配置文件.config中,生成工程中默认添加CONFIG_
2. 变量类型
bool:只有选和不选
tristate:三态,有选、不选和模块化
string:字符串
int:整型
hex:十六进制
3. depends on:依赖关系,如果依赖的配置选项没有被选中,那么当前的选项也无法配置
4. select:反向依赖,如果当前选项被选中,那么也选中select后面的选项。

Menu条目:生成菜单
Choice条目:将多个类似的配置选项组合在一起,供用户多选
Comment条目:用于定义一些帮助信息,配置过程中出现界面的第一行

新增一个配置的话,我们先在本目录的Kconfig中根据上面的语法添加我们的信息,在我们的.config中定义源文件的编译规则,即在当前目录下的Makefile中增加我们的编译规则,最后编译,在当前目录看是否有我们刚才添加的目标文件 xxx.o

下面谈一谈内核这块相关的问题

问题

谈谈Linux的两种模式

ARM&Linux有两种工作模式:SVC(管理)模式和USR(用户)模式,管理模式在硬件中已经写死了,只有开发人员才能有权限去修改,此模式是依赖于硬件的。因此用户不能直接操作硬件资源,硬件资源只能由内核去访问,用户不能访问内核的地址空间,包括代码和数据,因为用户一旦破坏了内核,那整个系统都会奔溃,用户可以通过系统调用实现访问,通过硬件中断实现两者转移,用户和内核都有自己独立的栈(内核的进程栈只有8K,因此局部变量定义不能太大),按照我的理解就是一个系统有root权限和普通权限。

用户空间和内核空间权限不一样,内核(3~4G)所有进程共享这1G,用户应用软件(0~3G)进程各有各的,内核相当于服务器端。

这里提一下VFS:提供统一的操作接口,隐藏各文件系统细节,不用考虑文件出处和文件类型是否相同。

系统调用工作原理

用户不能直接访问内核空间,只能通过系统调用,Linux系统提供系统调用函数,内核为他们分配了系统调用号,应用程序调用时,用C库的相应函数实现,将对应的系统调用号放到寄存器里面去,然后调用swi指令触发一个软中断,触发异常,CPU跳到内核事先定义好的异常向量表的入口(FFFF0000),进一步对此调用的异常进行处理。进入软中断异常路口(ENTRY(vector_swi))(新的处理器为svc(内核)指令),检查系统调用号,根据系统调用号,在事先准备好的系统调用表里面查找,内核根据系统调用号找到相应的函数实现,再进一步处理,完了之后原路返回用户空间。系统调用表事先由内核定义
ex:open->sys_open

int open(const char *name, int flags)
{
__syscall(open);
}

这里写图片描述

这里写图片描述

系统调用时C程序里面内嵌汇编,应用程序的转换靠的是软中断。

猜你喜欢

转载自blog.csdn.net/Peter_tang6/article/details/77505690