Linux内核结构分析

Linux内核非常庞大,里面包含了上万个文件,非常的复杂。要想移植或者是修改内核里面的东西,首先需要了解内核的整体架构,知道文件存放的位置以及编译关系,内核源码结构:

  1. arch:存放体系结构相关的代码,里面存放着各个架构CPU的代码。如arch/arm/、 arch/i386/等。
  2. block:存放块设备的通用函数。
  3. crypto:存放常用加密和散列算法,还有一些压缩和CRC校验算法。
  4. drivers:所有的设备驱动程序,里面每一个子目录对应一类驱动程序。
  5. fs:linux支持的文件系统的代码,每个子目录对应一种文件系统。如fs/jffs2、fs/ext2等
  6. init:内核的初始化代码,其main.c文件中的start_kerner是内核引导后运行的第一个函数
  7. ipc:进程间通信代码
  8. include:内核头文件,有基本文件(存放在include/linux目录下)、各种驱动的头文件(如include/mtd/)以及各种体系相关的头文件(include/asm-arm)。配置内核后,include/asm/是个链接文件,指向配制的体系头文件(如include/asm-arm)。
  9. kernel:内核管理的核心代码,与处理器相关的代码位于arch/*/kernel/目录下。
  10. lib:内核使用到的一些库函数代码。
  11. mm:内存管理代码,与处理器相关的内存管理代码位于arch/*/mm/目录下。
  12. net:网络支持代码,每个子目录对应于网络的一个方面。
  13. security:安全、密钥相关的代码。
  14. sound:音频设备的驱动程序。
  15. usr:用来制作一个压缩的cpio归档文件
  16. documentation
  17. scripts

制作内核的流程:修改内核源码——>make menuconfig 配置内核——>make uImage编译生成镜像。make clean清除编译生成的一些中间文件,make disclean 彻底清除配置文件。

要分析内核,首先需要分析的是顶层目录下的Makefile(因为内核是根据Makefile规则来编译生成的)。Makefile会指定哪些文件被编译以及如何编译(是编译进内核还是编译成模块)、指定链接时的顺序。

      在顶层的Makefile中发现 和可以知道编译生成的内核文件依赖于:再次跟踪可以发现vmlinux-init依赖的head-y在arch/arm/Makefile中规定了,使用的是kernel中的head-nommu.S和init_task.c文件。,而vmlinux-main所依赖的$(core-y)、$(libs-y)、$(drivers-y) 、$(net-y),这些依赖

,上述中的所以依赖都会执行相应目录下的Makefile,每个子目录都会生成一个built-in.o文件。编译后链接使用的链接脚本为arch/$(ARCH)/kernel/vmlinux.lds生成的Image、uImage文件存放在arch/$(ARCH)/boot 中。

首先是哪些文件会被编译以及如何编译:

顶层目录Makefile决定内核根目录下哪些子目录将被编译进内核。从上面可以知道根目录中的很多文件(绝大部分)都会被编译进内核,而和架构相关的Makefile也会被包含进来(需要使用架构相关的head.S 以及init_task.c),所以在编译内核时需要指定使用的架构和交叉编译工具(如ARCH = arm CROSS_COMPILE = arm-Linux-)。

arch/$(ARCH)/Makefile决定架构目录下的哪些文件将编译进内核。在架构相关的Makefile中扩展了lib和core的内容,把和架构相关的库文件以及和架构相关的core文件都编译进去。

各级子目录下的Makefile(存放这样的条目)决定所在的目录中哪些文件会将编译进内核,哪些文件编译生成驱动模块。在配置内核后,会在顶层目录下生成配置文件.config.config会生成include/config/auto.conf和include/linux/autoconf.h文件。auto.conf文件基本上和.config相同(把一些注释给去除了),这个文件的作用主要是给各级子目录使用,用来确定(使用宏来代替具体的值y或者是m)子目录中的文件是否要编译以及如何编译。

子目录中的Makefile有着以下的规定:

①obj-y用来定义哪些文件被编译进内核,obj-y定义的.o文件由当前目录下的.c或.S文件编译生成,连同下级子目录的built-in.o文件一起被组合成built-in.o文件供上一层的Makefile使用。

②obj-m是用来定义哪些文件被编译成可加载模块。一个模块可以由一个或多个.o文件文件组成。对于有多个源文件的模块时,除了在obj-m中增加一个.o文件外,还需要定义一个<module_name>-objs变量来告诉Makefile这个.o文件由哪些文件组成。

③lib-用来定义哪些文件被编译成库文件。lib-y中定义的文件编译后会打包成当前目录下的一个库文件lib.a。同时出现在obj-y、lib-y中的.o文件,不会被包含进lib.a中。要把这个lib.a编译进内核,需要在顶层Makefile中libs-y变量中列出当前目录。

obj-y、obj-m还可以用来指定要进入的下一层子目录,Linux中一个Makefile只负责生成当前目录下的目标文件,子目录下的目标文件由子目录的Makefile生成。obj-$(CONFIG_XX) +=subdir/ 编译时会进入subdir中编译

note:Makefile中经常可以看到$(patsubst %/,%/built-in.o,$(net-y))这种类型的文件,patsubst是个字符串处理函数,$(patsubst pattern, repalcement,text)表示寻找text中符合pattern的字符,用replacement替换他们。

所以Makefile的作用如下|:

  • 根据配置文件.config中定义的一系列变量,决定哪些文件被编译进内核、哪些文件被编译成模块以及涉及哪些子目录。
  • 顶层Makefile和arch/$(ARCH)/Makefile决定根目录下哪些子目录、arch/$(ARCH)/目录下哪些文件和目录将被编译进内核。
  • 各级子目录下的Makefile决定所在目录下哪些文件被编译以及如何编译,进入哪些子目录继续编译他们的Makefile。
  • 最后根据链接脚本arch/$(ARCH)/kernel/vmlinux.lds来生成内核镜像文件vmlinux。

内核配置分析

无论是执行make menuconfig ARCH = arm CROSS_COMPILE=arm-linux还是执行make config ARCH = arm CROSS_COMPILE=arm-linux来配置内核。所有的配置工具都是根据arch/$(ARCH)/Kconfig文件来生成配置界面这个文件是所有配置文件的总入口,它会包含其他目录的Kconfig文件。内核源码每个子目录中都会有一个Makefile和Kconfig文件,Kconfig文件用于配置内核,就是各种配置界面的源文件。内核配置工具读取各个Kconfig文件,生成配置界面供开发人员配置内核,最后生成配置文件.config。

内核的配置界面以树状的菜单形式组织,主菜单下有若干个子菜单,子菜单下又有子菜单或配置选项。每个子菜单或选项可以有依赖关系。依赖关系用来确定它们是否显示。

Kconfig的语法如下:Kconfig文件的基本要素:config条目。config用来配置一个选项。基本的格式如下。下面黑色加粗的是必须存在的:

  1. config是关键字,表示一个配置选项的开始,后面的是配置选项的名称
  2. bool表示变量的类型,即CONFIG_SMDK2440_CPU2440的类型。类型有bool、tristate、string、hex、int五种,其中bool只能取y和n两种,tristate变量可以取值有y、n、m三种。变量后面的字符串是提示信息,完整的格式是<prompt>“prompt” [ "if"  <expr> ]。
  3. depends on ARCH_S3C2440表示依赖关系。只有ARCH_S3C2440选项选中时才会显示当前的配置选项的提示信息。完整的格式是“depends on”/"requires"<expr>,如果依赖条件不满足则使用默认的值。
  4. default  y if ARCH_S3C2440,表示默认值是y。完整的格式:“default” <expr> 【if <expr>】。
  5. select CPU_S3C2440表示当前配置选项被选中时,配置选项CPU_S3C2440也会被自动选中。
  6. help和“---help---”都是帮助信息。help帮助信息结束的条件是,遇到一行的缩进距离比第一行帮助信息的缩进距离小时。
  7. menu条目:是以menu开始,endmenu结束。menu后面接的是菜单名。menu和endmenu之间存放着config条目。这些条目就是进入这个菜单后显示出来的信息。
  8. choice条目,choice将多个类似的配置选项组合在一起,供用户单选或多选。格式是choice .......endchoice。choice条目中定义的变量类型只能有两种:bool和tristate,不能同时有这两种变量类型。bool类型只能在多个选项中选择一个y。对于tristate类型,要么把多个选项都设置为m,要么就选一个y。
  9. comment条目。用来定义一些帮助信息,在配置过程中出现在界面的第一行。格式“comment” <prompt>
  10. source条目。此条目用于读入另一个Kconfig文件。完整格式“source” <prompt>  如source “net/Kconfig”把net/Kconfig配置文件读入。

Linux内核的配置选项多达上千个,一个个地进行选择浪费时间也对开发人员的要求比较高。普通的做法是在某个默认配置文件的基础上进行修改。如先加载arch/arm/donfigs/目录中的默认配置文件,然后在微调整下就可以了。

配置界面主菜单的类别:

  • code maturity level options :代码成熟度选项,用于包含一些正在开发的或者不成熟的代码、驱动程序,一般不设置。
  • general setup:常规设置,如增加附加的内核版本号、支持内存页交换功能、system V进程间通信等。一般使用默认配置。
  • loadable module support:可加载模块支持,通常会选择里面的enable loadable module support、module UNloading、automatic kernel module loading。
  • block layer:块设备层,用来设置块设备的一些总体参数。一般使用默认设置。
  • system type:系统类型,选择CPU的架构、开发板类型等与开发板相关的配置选项。
  • bus support:PCMCIA/CardBus总线的支持。
  • kernel features:用于设置内核的一些参数,比如是否支持内核抢占,是否支持动态修改系统时钟等。
  • boot options:启动参数,比如设置默认的命令行参数等。一般很少修改。
  • floating point emulation:浮点运算仿真功能,一般使用“NWFPE math emulation”。
  • userspace binary formats:可执行文件格式:一般选择支持ELF、a.out格式。
  • power management options:电源管理选项。
  • networking:网络协议选项,一般选择“Networking support”支持网络、“packet socket”支持socket接口功能,“TCP/IP networking”支持TCP/IP网络协议。
  • device driver:设备驱动程序,几乎包含了Linux的所有驱动程序。
  • file system:文件系统,选择要支持的文件系统(如EXT2、JFFS2)。
  • profiling support:对系统的活动进行分析,仅供内核开发者使用。
  • kernel hacking:调试内核时的各种选项。
  • security options:安全选项。
  • crypt options:加密选项。
  • library routines:库子程序。不需要操作。

最后总结下:虽让内核中的文件有着上万个,数量及其的庞大。但是分类归纳之后不算是太复杂。内核中的Makefile是用来指定编译的规则,Kconfig文件是用来提供给用户配置选项的文件,客户编译后会生成客户的配置文件.config。.config决定了哪些目录下的哪些文件将会别编译,以及如何编译。同时在C代码中还会根据.config配置文件决定代码段是否被编译(条件编译)。

 

 

 

 

 

 

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值