第10课 内核启动流程分析

来自百问网嵌入式Linux wiki
跳转至: 导航搜索

1 内核编译

打补丁:

patch 命令, -p 是指需要忽略的目录层数。如果打补丁,在源代码里有显示。

File:Ldd chapter10 001.jpg

  • --- 是指源文件。
  • +++ 是指修改过的文件。
  • -p 1是指忽略一层目录:linux-2.6.22.6这层目录。
  • -p 2是指忽略两层目录:linux-2.6.22.6/arch这两层目录。
patch –p1 < ../linux-2.6.22.6_jz2440.patch

配置:3种方法。

  1. make memuconfig(成千上万配置项要配置,很复杂,不可取)
  2. 使用默认的配置,在此基础上修改。(但现在不知道默认的配置有哪些。可以搜索下)
  3. 使用厂家提供的配置文件。(将厂家提供的 config_厂家 直接复制一份为 .config,然后再 make menuconfig

使用默认的配置,在此基础上修改。
但现在不知道默认的配置有哪些。可以搜索下:

  • a.加了“'通配符”'

结果是 /arch/ 目录下各种架构下的 configs 目录下的 ****_defconfig 文件。

File:Ldd chapter10 002.jpg

在这个 /arch/arm 目录下找,看有没有和我们的单板相似的架构配置。 这里看到 s3c2410_defconfig 这个文件和我们的 2440 单板相像。则可:

  • b. make s3c2410_defconfig以2410作为默认配置。接着Make menuconfig在2410的配置基础上修改
[root@localhost linux-2.6.22.6]# make s3c2440_defconfig

执行完 make s3c2410_defconfig 后,显示'“配置文件”'写到了.config文件中。

File:Ldd chapter10 003.jpg

  • c. make menuconfig

s3c2410_defconfig 的基础上可以修改完善成我们需要的. 这里直接用开发板厂家提供的配置文件 config_ok ,将它改成 .config

[root@localhost linux-2.6.22.6]# cp config_ok .config

File:Ldd chapter10 003.jpg

如何操作 make menuconfig 的说明文件。 Highlighted letters are hotkeys.是指高亮的首字母。在键盘上按下这样的字母可以直接跳到相应的目录上。

File:Ldd chapter10 004.jpg

对于这个目录,直接按下D键盘键就可以跳到这一条配置目录上。 搜索是按下/会出现搜索框,输入要搜索的内容即可搜索。

编译:make

  • 要生成 uImage make uImage

uImage:头部+真正的内核,我们想编译一个内核给 UBOOT 用,则用 make uImage. 上电开发板,接上USB线(装驱动)在UBOOT命令中选:[K]

[k] Download Linux kernel uImage

之后会等待通过USB上传文件。

  • 用工具 dnw.exe

查看下源代码,看看 [k] 对应于哪个命令:在Cmd_menu.c中查找。 首先上传数据:usbslave 1 0x30000000 来接收 dnw.exe 发出来的数据,放到 0x3000 0000地址处。
然后擦除内核分区:nand erase kernel 收到数据后,接着擦除这个kernel内核分区。 最后写到内核分区:nand write.jffs2 0x30000000 kernel $(filesize) 将原来接收到 0x3000 0000处的文件烧到 kernel 分区去。 烧多大$(filesize)由这个宏定义,表示接收到的文件大小。

烧写完后,用 [b] 命令启动。 进入UBOOT后,可以用 nand erase root 是删除文件系统。然后 boot 是UBOOT启动内核。

2 内核分析配置

配置过程:

1. 配置后产生 .config 文件。

里面有很多配置项,等于y、m或某些数值。等于y表示会编译成内核中去。若是编译成了模块,便可以动态加载。

2. 举例说明:
配置项

599 CONFIG_DM9000=y

File:Ldd chapter10 005.jpg

include/linux/autoconf.h

这些都是不同架构的默认配置下的(config是配置文件目录)不用看。

还可以看到源代码中有这个值:

File:Ldd chapter10 006.jpg

还有 drivers\net\Makefile中有:

drivers\net\Makefile
#obj-$(CONFIG_DM9000) += dm9000.o 
#obj-$(CONFIG_DM9000) += dm9ks.o

则:

  • a. C 源代码中用到 CONFIG_DM9000.从 C 语言语法看肯定是个宏。宏只能在C文件或是头文件中定义。

依照这里的情况,应该是在include/linux/autoconf.h 这个头文件中定义。

  • b. 子目录下的Makefile中有 CONFIG_DM9000 配置项(如drivers/net/Makefile)
  • c. include/config/auto.conf 中有。
  • d. include/linux/autoconf.h 中有。从autoconf.h可猜测这个文件是自动生成的。它里面的内容来源于make内核时,make机制会自动根据生成的 .config 配置文件,生成 autconf.h这个文件。

在 autoconf.h 中搜索DM9000得到:#define CONFIG_DM9000 1 可见 CONFIG_DM9000 被定义成一个宏,为1

整个文件 autoconfi.h 中的宏基本都是定义为1,就是说不管在 .config 配置文件中,配置项=y,还是=m,

在这个由 .config 生成的头文件 autoconf.h 中都被定义成1

C语言源码中就只使用这些 宏 了。这些等于y等于m的在 autoconf.h 中定义宏时都定义为1,它们的区别则在使用这些宏的C语言中体现不出来了。这些区别是在 Makefile 中定义。看子目录下的Makefile.

看子目录 dervice/net/Makefile 文件。搜索其中 CONFIG_DM9000 文件。对于内核的Makefile,它的子目录的Makefie很简单。

内核子目录Makefile:

1.格式比较简单:内核子目录下的Makefile中

obj-y += xxx.o
xxx.c的文件最后会被编译进内核中去。
obj-m += yyy.o
yyy.c文件最后会编译成 可加载 的模块 yyy.ko 。

这两种格式。 如下示例:

obj-$(CONFIG_DM9000) += dm9000.o

意思:若CONFIG_DM9000这个变量被定义为 y 的话,这个 dm9000.c 就会被编译进内核中去。
若这个配置项CONFIG_DM9000被定义为 m 的话,这个 dm9000.c 会被编译成 dm9000.ko 模块

y和m的区别就是在内核的子目录下的Makefile中体现的。
子目录下的Makefile中的 CONFIG_DM9000 是谁来定义的呢?

也是由其他来定义的。由 '"include/config/auto.conf '" 来定义(这个文件也是来源于make内核时的 .config)。
auto.conf可知它也是自动生成的。里面的内核和 .config 文件很像。其中的项要么等于y,要么等于m,或其他值。
显然这个 include/config/auto.conf 文件是会被别人包含进去。(被顶层的Makefile包含)

File:Ldd chapter10 007.jpg

配置内核时生成了 .config 文件。然后 make menuconfig 或是 make uImage 时:

  1. .config 被自动来创建生成了一个 include/linuxautoconfig.h 文件 .这个头文件被 C 源代码去对应里面的配置。
  2. .config 也被自动来生成一个 include/config/auto.conf 文件。这个文件由顶层Makefile来包含。由子目录下的Makefile来用它。

3 内核Makefile

  • 分析Makefile:找到第一个目标文件和链接文件。
  • 第一个目标文件(一路跟踪启动过程)
  • 链接文件:它表示内核应该放在哪里,里面的代码是如何排布的。

4 机器ID,启动参数