为您推荐:
精华内容
最热下载
问答
  • 内核编译完成后会生成zImage内核镜像文件。关于bootloader加载zImage到内核,并且跳转到zImage开始地址运行zImage的过程,相信大家都很容易理解。但对于zImage是如何解压的过程,就不是那么好理解了。本文将结合部分...

    内核编译完成后会生成zImage内核镜像文件。关于bootloader加载zImage到内核,并且跳转到zImage开始地址运行zImage的过程,相信大家都很容易理解。但对于zImage是如何解压的过程,就不是那么好理解了。本文将结合部分关键代码,讲解zImage的解压过程。

    先看看zImage的组成吧。在内核编译完成后会在arch/arm/boot/下生成zImage。

    在arch/armboot/Makefile中:

    $(obj)/zImage: $(obj)/compressed/vmlinux FORCE

    $(call if_changed,objcopy)

    由此可见,zImage的是elf格式的arch/arm/boot/compressed/vmlinux二进制化得到的

    在arch/armboot/compressed/Makefile中:

    $(obj)/vmlinux: $(obj)/vmlinux.lds $(obj)/$(HEAD) $(obj)/piggy.o

    $(addprefix $(obj)/, $(OBJS)) FORCE

    $(call if_changed,ld)

    $(obj)/piggy.gz: $(obj)/../Image FORCE

    $(call if_changed,gzip)

    $(obj)/piggy.o: $(obj)/piggy.gz FORCE

    其中Image是由内核顶层目录下的vmlinux二进制化后得到的。注意:arch/arm/boot/compressed/vmlinux是位置无关的,这个有助于理解后面的代码。,链接选项中有个 –fpic参数:

    EXTRA_CFLAGS := -fpic

    总结一下zImage的组成,它是由一个压缩后的内核piggy.o,连接上一段初始化及解压功能的代码(head.o misc.o),组成的。

    下面就要看内核的启动了,那么内核是从什么地方开始运行的呢?这个当然要看lds文件啦。zImage的生成经历了两次大的链接过程:一次是顶层vmlinux的生成,由arch/arm/boot/vmlinux.lds(这个lds文件是由arch/arm/kernel/vmlinux.lds.S生成的)决定;另一次是arch/arm/boot/compressed/vmlinux的生成,是由arch/arm/boot/compressed/vmlinux.lds(这个lds文件是由arch/arm/boot/compressed/vmlinux.lds.in生成的)决定。zImage的入口点应该由arch/arm/boot/compressed/vmlinux.lds决定。从中可以看出入口点为‘_start’

    OUTPUT_ARCH(arm)

    ENTRY(_start)

    SECTIONS

    {

    . = 0;

    _text = .;

    .text : {

    _start = .;

    *(.start)

    *(.text)

    ……

    }

    在arch/arm/boot/compressed/head.S中找到入口点.。

    看看head.S会做些什么�

    展开全文
    weixin_36099503 2021-05-13 21:51:13
  • 可以看到,在顶层makefile的第278行,包含了scripts/Kbuild.include文件,在这里定义了大量的函数和变量,供顶层makefile和其他makefile文件使用。    在顶层makefile文件的第412行,包含了arch/arm/Makefile。...
    可以看到,在顶层makefile的第278行,包含了scripts/Kbuild.include文件,在这里定义了大量的函数和变量,供顶层makefile和其他makefile文件使用。 
    
      
    在顶层makefile文件的第412行,包含了arch/arm/Makefile。这个是体系结构相关makefile文件。它定义了体系结构相关的一些变量及规则。 
      
    当执行”make”时,arch/arm/Makefile中的185行的规则将是make遇到的第一个规则: 
      
    all:   $(KBUILD_IMAGE) 
      
    KBUILD_IMAGE这个变量是arch/arm/Makefile的第182行定义。 
      
    KBUILD_IMAGE := zImage 
      
    然后看zImage的构建规则,在arch/arm/Makefile的第212行开始定义 
      
    zImage Image xipImage bootpImage uImage: vmlinux 
           $(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) $(boot)/$@ 
      
    build变量在scripts/Kbuild.include文件中第114行定义: 
      
    build := -f $(if $(KBUILD_SRC),$(srctree)/)scripts/Makefile.build obj 
      
    boot变量在arch/arm/Makefile的187行定义: 
      
    boot := arch/arm/boot 
      
    MACHINE变量的值在arch/arm/Makefile的147行开始定义 
      
    ifneq ($(machine-y),) 
    MACHINE  := arch/arm/mach-$(machine-y)/ 
    else 
    MACHINE  := 
    endif 
      
    这里machine-y := s3c2410,所以变量MACHINE的值为 
      
    MACHINE  := arch/arm/mach-s3c2410 
      
    所以上面的规则可写为如下形势 
      
      
    zImage: vmlinux 
           $(Q)$(MAKE) -f $(if $(KBUILD_SRC),$(srctree)/)scripts/Makefile.build obj= / 
           arch/arm/boot MACHINE= arch/arm/mach-s3c2410 arch/arm/boot/ zImage 
      
    这个规则的依赖是vmlinux,下面先看看这个依赖目标的创建规则。 
      
    vmlinux目标的规则在顶层Makefile的第738行定义。 
      
    vmlinux: $(vmlinux-lds) $(vmlinux-init) $(vmlinux-main) $(kallsyms.o) FORCE 
    ifdef CONFIG_HEADERS_CHECK 
           $(Q)$(MAKE) -f $(srctree)/Makefile headers_check 
    endif 
           $(call if_changed_rule,vmlinux__) 
           $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modpost $@ 
           $(Q)rm -f .old_version 
      
    这里涉及到几个变量,先看看这几个变量的定义,前三个变量分别在605、602、603行定义。 
      
    vmlinux-init := $(head-y) $(init-y) 
    vmlinux-main := $(core-y) $(libs-y) $(drivers-y) $(net-y) 
    vmlinux-lds  := arch/$(ARCH)/kernel/vmlinux.lds 
      
    其中head-y在arch/arm/Makefile中第89行定义, 
      
    head-y            := arch/arm/kernel/head$(MMUEXT).o arch/arm/kernel/init_task.o 
      
    init-y在顶层makefile的433行定义 
      
    init-y              := init/ 
      
    后又在第567行进行处理 
      
    init-y              := $(patsubst %/, %/built-in.o, $(init-y)) 
      
    所以变量init-y应为 
      
    init-y              := init/built-in.o 
      
    因此 
      
    vmlinux-init := arch/arm/kernel/head$(MMUEXT).o arch/arm/kernel/init_task.o init/built-in.o 
      
    同理,其他几个变量也可通过类似方法进行分析,这里不一一分析了。vmlinux-init这个变量的构建规则在748行定义: 
      
    $(sort $(vmlinux-init) $(vmlinux-main)) $(vmlinux-lds): $(vmlinux-dirs) ; 
      
    这里是一个空命令的规则。空命令行可以防止make在执行时试图为重建这个目标去查找隐含命令。其依赖为vmlinux-dirs,这个变量在顶层Makefile第558行定义: 
      
    vmlinux-dirs   := $(patsubst %/,%,$(filter %/, $(init-y) $(init-m) / 
                       $(core-y) $(core-m) $(drivers-y) $(drivers-m) / 
                       $(net-y) $(net-m) $(libs-y) $(libs-m))) 
      
    这个变量指定了一系列要进入的下层目录。他的规则在顶层Makefile第757行定义 
      
    $(vmlinux-dirs): prepare scripts 
           $(Q)$(MAKE) $(build)=$@ 
      
    这里的两个依赖就不分析了,主要看一下这个规则的命令,build和$@变量展开后如下 
      
           $(Q)$(MAKE) -f $(if $(KBUILD_SRC),$(srctree)/)scripts/Makefile.build  / 
            obj =$(vmlinux-dirs) 
      
    这里会再一次进入scripts/Makefile.build执行83行规则 
      
    __build: $(if $(KBUILD_BUILTIN),$(builtin-target) $(lib-target) $(extra-y)) / 
            $(if $(KBUILD_MODULES),$(obj-m)) / 
            $(subdir-ym) $(always) 
           @: 
      
    因为KBUILD_BUILTIN在顶层Makefile中被初始化为1,所以这个规则的依赖有一个builtin-target变量。这个变量在scripts/Makefile.build的78行定义 
      
    ifneq ($(strip $(obj-y) $(obj-m) $(obj-n) $(obj-) $(lib-target)),) 
    builtin-target := $(obj)/built-in.o 
    endif 
      
    变量obj就是vmlinux-dirs变量指定的目录。所以这里会构建$(vmlinux-dirs)/built-in.o目标,在scripts/Makefile.build文件的261行开始,有这个目标的规则及命令的定义 
      
    ifdef builtin-target 
    quiet_cmd_link_o_target = LD      $@ 
    # If the list of objects to link is empty, just create an empty built-in.o 
    cmd_link_o_target = $(if $(strip $(obj-y)),/ 
                        $(LD) $(ld_flags) -r -o $@ $(filter $(obj-y), $^),/ 
                        rm -f $@; $(AR) rcs $@) 
      
    $(builtin-target): $(obj-y) FORCE 
           $(call if_changed,link_o_target), 
      
    scripts/Makefile.build在第16行开始包含了vmlinux-dirs变量指定目录中的Makefile文件,在这些makefile文件中会指定obj-y变量,它指定的都是一些*.o目标文件, 
      
    kbuild-dir := $(if $(filter /%,$(src)),$(src),$(srctree)/$(src)) 
    include $(if $(wildcard $(kbuild-dir)/Kbuild), $(kbuild-dir)/Kbuild, $(kbuild-dir)/Makefile) 
      
    这些*.o文件的生成方法由scripts/Makefile.build文件202行的模式规则指定 
      
    %.o: %.c FORCE 
           $(call cmd,force_checksrc) 
           $(call if_changed_rule,cc_o_c) 
      
    通过上面这一系列的步骤,就编译链接出由变量vmlinux-init指定的目标,vmlinux-main变量指定的目标的构建与此类似。再看看vmlinux的构建规则 
      
    vmlinux: $(vmlinux-lds) $(vmlinux-init) $(vmlinux-main) $(kallsyms.o) FORCE 
    ifdef CONFIG_HEADERS_CHECK 
           $(Q)$(MAKE) -f $(srctree)/Makefile headers_check 
    endif 
           $(call if_changed_rule,vmlinux__) 
           $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modpost $@ 
           $(Q)rm -f .old_version 
      
    现在vmlinux的依赖都处理好了,开始执行这个规则的命令,命令 
      
    $(Q)$(MAKE) -f $(srctree)/Makefile headers_check 
      
    是进行头文件的相关检测,这里不作详细分析。看第二条命令 
      
           $(call if_changed_rule,vmlinux__) 
      
    这里通过函数调用,执行rule_vmlinux__,在顶层Makefile第636行开始定义 
      
    define rule_vmlinux__ 
           : 
           $(if $(CONFIG_KALLSYMS),,+$(call cmd,vmlinux_version)) 
      
           $(call cmd,vmlinux__) 
           $(Q)echo 'cmd_$@ := $(cmd_vmlinux__)' > $(@D)/.$(@F).cmd 
      
           $(Q)$(if $($(quiet)cmd_sysmap),                                      / 
             echo '  $($(quiet)cmd_sysmap)  System.map' &&)                     / 
           $(cmd_sysmap) $@ System.map;                                         / 
           if [ $$? -ne 0 ]; then                                               / 
                  rm -f $@;                                                    / 
                  /bin/false;                                                  / 
           fi; 
           $(verify_kallsyms) 
    endef 
      
    这里主要还是调用cmd_vmlinux__,定义在顶层Makefile的610行 
      
          cmd_vmlinux__ ?= $(LD) $(LDFLAGS) $(LDFLAGS_vmlinux) -o $@ / 
          -T $(vmlinux-lds) $(vmlinux-init)                          / 
          --start-group $(vmlinux-main) --end-group                  / 
          $(filter-out $(vmlinux-lds) $(vmlinux-init) $(vmlinux-main) FORCE ,$^) 
      
    通过这个命令将变量vmlinux-init和vmlinux-main指定的目标链接成vmlinux文件。链接脚本由vmlinux-lds指定。在顶层 Makefile 605行定义: 
      
    vmlinux-lds  := arch/$(ARCH)/kernel/vmlinux.lds 
      
    现在再看一下zImage的构建规则 
      
    zImage: vmlinux 
           $(Q)$(MAKE) -f $(if $(KBUILD_SRC),$(srctree)/)scripts/Makefile.build obj= / 
           arch/arm/boot MACHINE= arch/arm/mach-s3c2410 arch/arm/boot/ zImage 
      
    其依赖vmlinux已经构建完成,它的命令同样是执行scripts/Makefile.build文件,它的开头包含了arch/arm/boot/Makefile文件,在这个文件的第56行开始就是arch/arm/boot/zImage的构建规则: 
      
    $(obj)/zImage: $(obj)/compressed/vmlinux FORCE 
           $(call if_changed,objcopy) 
           @echo '  Kernel: $@ is ready' 
      
    变量obj的值就是arch/arm/boot,前面已经分析过。其依赖  $(obj)/compressed/vmlinux的构建规则在arch/arm/boot/Makefile的53行开始定义的 
      
    $(obj)/compressed/vmlinux: $(obj)/Image FORCE 
           $(Q)$(MAKE) $(build)=$(obj)/compressed $@ 
      
    这个规则的依赖$(obj)/Image的构建规则在arch/arm/boot/Makefile的49行开始定义: 
      
    $(obj)/Image: vmlinux FORCE 
           $(call if_changed, objcopy) 
           @echo '  Kernel: $@ is ready' 
      
    在这个规则中,将前面创建的vmlinux文件通过二进制工具objcopy进行处理,在scripts/Makefile.build的第19行包含了scripts/Makefile.lib 
      
    include scripts/Makefile.lib 
      
    在这个makefile文件中,有cmd_objcopy的定义,在156行开始定义 
      
    quiet_cmd_objcopy = OBJCOPY $@ 
    cmd_objcopy = $(OBJCOPY) $(OBJCOPYFLAGS) $(OBJCOPYFLAGS_$(@F)) $< $@ 
      
    变量OBJCOPY在顶层Makefile中289行定义: 
      
    OBJCOPY             = $(CROSS_COMPILE)objcopy 
      
    OBJCOPYFLAGS变量在arch/arm/Makefile中第15行定义 
      
    OBJCOPYFLAGS  :=-O binary -R .note -R .comment –S 
      
    所以命令cmd_objcopy可扩展为 
      
    cmd_objcopy = $(CROSS_COMPILE)objcopy -O binary -R .note -R .comment –S $< $@ 
      
    这就是处理vmlinux的命令。然后看看规则 
      
    $(obj)/compressed/vmlinux: $(obj)/Image FORCE 
           $(Q)$(MAKE) $(build)=$(obj)/compressed $@ 
      
    的命令行,变量扩展后为: 
      
    $(Q)$(MAKE) -f $(if $(KBUILD_SRC),$(srctree)/)scripts/Makefile.build obj= / 
                 $(obj)/compressed $(obj)/compressed/vmlinux 
      
    于是在scripts/Makefile的开头会包含arch/arm/boot/compressed/Makefile文件,并执行其中的$(obj) /vmlinux目标所在的规则,在这个Makefile文件的第98行开始定义: 
      
    $(obj)/vmlinux: $(obj)/vmlinux.lds $(obj)/$(HEAD) $(obj)/piggy.o / 
                 $(addprefix $(obj)/, $(OBJS)) FORCE 
           $(call if_changed,ld) 
           @: 
      
    这里先看$(obj)/piggy.o,在arch/arm/boot/compreseed/Makefile的103行开始 
      
    $(obj)/piggy.gz: $(obj)/../Image FORCE 
           $(call if_changed,gzip) 
      
    $(obj)/piggy.o:  $(obj)/piggy.gz FORCE 
      
    这两个规则的第一个就是把由vmlinux生成的Image进行压缩生成piggy.gz,然后生成piggy.o 
      
    cmd_ld命令在scripts/Makefile.lib文件149行定义: 
      
    quiet_cmd_ld = LD      $@ 
    cmd_ld = $(LD) $(LDFLAGS) $(EXTRA_LDFLAGS) $(LDFLAGS_$(@F)) / 
                  $(filter-out FORCE,$^) -o $@ 
      
    这里根据链接脚本arch/arm/boot/compressed/vmlinux.lds链接生成了arch/arm/boot/compressed/vmlinux文件。然后在arch/arm/boot/Makefile的第56行的规则中 
      
    $(obj)/zImage: $(obj)/compressed/vmlinux FORCE 
           $(call if_changed,objcopy) 
           @echo '  Kernel: $@ is ready' 
      
    经过objcopy处理后便生成的最终的zImage 。 
      
      
      
    下面看一下顶层Makefile生成的vmlinux以及arch/arm/boot/compressed/makefile生成的vmlinux的起始地址。 
      
    通过顶层Makefile中的规则生成vmlinux是根据arch/arm/kernel/vmlinux.lds这个脚本链接生成的。arch/arm/kernel/vmlinux.lds是由arch/arm/kernel/vmlinux.lds.S生成的,其生成规则在scripts/Makefile.build的第246行开始定义 
      
    quiet_cmd_cpp_lds_S = LDS     $@ 
          cmd_cpp_lds_S = $(CPP) $(cpp_flags) -D__ASSEMBLY__ -o $@ $< 
      
    %.lds: %.lds.S FORCE 
           $(call if_changed_dep,cpp_lds_S) 
      
    在arch/arm/kernel/vmlinux.lds.S的开始处有 
      
    #ifdef CONFIG_XIP_KERNEL 
           . = XIP_VIRT_ADDR(CONFIG_XIP_PHYS_ADDR); 
    #else 
           . = PAGE_OFFSET + TEXT_OFFSET; 
    #endif 
      
    我们这里的起始地址就是PAGE_OFFSET + TEXT_OFFSET。 
      
    在include/asm-arm/memory.h的49行开始有 
      
    #ifndef PAGE_OFFSET 
    #define PAGE_OFFSET        UL(0xc0000000) 
    #endif 
      
    而arch/arm/kernel/vmlinux.lds.S的开头有 
      
    #include <asm/memory.h> 
      
    asm是一个符号,链接到asm-arm上的 
      
    在arch/arm/Makefile第140行,有 
      
    TEXT_OFFSET := $(textofs-y) 
      
    第90行有 
      
    textofs-y := 0x00008000 
      
    所以TEXT_OFFSET := 0x00008000 
      
    在153行有export TEXT_OFFSET将此变量输出。这样arch/arm/kernel/vmlinux.lds.S也就获得了PAGE_OFFSET + TEXT_OFFSET的值。 
      
      
    现在看看arch/arm/boot/compressed/makeflie生成的vmlinux。它是根据arch/arm/boot/compressed/vmlinux.lds链接脚本生成的。这个脚本由arch/arm/boot/compressed/vmlinux.lds.in生成,在这个文件的开始处有 
      
      . = TEXT_START; 
      
    现在看arch/arm/boot/compressed/Makefile,在110行有 
      
    $(obj)/vmlinux.lds: $(obj)/vmlinux.lds.in arch/arm/boot/Makefile .config 
           @sed "$(SEDFLAGS)" < $ $@ 
      
    这就是由vmlinux.lds.in生成vmlinux.lds的规则,在它的命令中有个变量SEDFLAGS,在74行定义 
      
    SEDFLAGS    = s/TEXT_START/$(ZTEXTADDR)/;s/BSS_START/$(ZBSSADDR)/ 
      
    这里就把TEXT_START换成了ZTEXTADDR。再往上看从66行起 
      
    ifeq ($(CONFIG_ZBOOT_ROM),y) 
    ZTEXTADDR := $(CONFIG_ZBOOT_ROM_TEXT) 
    ZBSSADDR    := $(CONFIG_ZBOOT_ROM_BSS) 
    else 
    ZTEXTADDR := 0 
    ZBSSADDR    := ALIGN(4) 
    endif 
      
    如果zImage是从ram中启动ZTEXTADDR      := 0,否则从rom或flash启动时ZTEXTADDR := $(CONFIG_ZBOOT_ROM_TEXT),这里要在配置时设定CONFIG_ZBOOT_ROM_TEXT的值。 
      
    到这里,关于zImage的生成过程算是可以结束了。
    展开全文
    skyflying2012 2014-06-27 10:35:07
  • 这里不只是讲怎样编译、安装Linux内核的,更主要的是介绍内核的编译系统和各个重要的文件。最后还利用学到的编译、安装Linux内核去修改Linux的01调度变成随机调度。如果你只是需要编译、安装内核的几条指令,那么翻...

    这里不只是讲怎样编译、安装Linux内核的,更主要的是介绍内核的编译系统和各个重要的文件。最后还利用学到的编译、安装Linux内核去修改Linux的01调度变成随机调度。如果你只是需要编译、安装内核的几条指令,那么翻到文章中后部分吧。如果有哪里写错或者写得不太清楚的请指正。谢谢你的阅读!

    内核嘛,就是Linux的核心,如果你用Linux只是为了听听歌,看看电影,上上网,那么我想Linux是不太适合你的。但能打开这篇文章,那么你应该就是对Linux有兴趣了。这里我们一起编译下这个世界上IT里最完美的艺术品!----Linux内核

    编译前先来看看Linux内核的源码目录结构。有助于认识Linux内核,熟悉了她,就不会再有恐惧与无助的感觉。

    内核源码录目结构:

    1)    Documentation    这里没有代码,有的只是一些各种各样文档,但可以给我们足够多的帮助。

    2)    arch    所有与体系结构有关的源代码都在这里,还有在include/asm-*/目录里。所支持的体系结构都在arch目录下有对应的子目录,而且最少都包含3个子目录。

    kernel:支持体系结构特有的如信号处理、SMP等的实现。

    lib:体系结构特有的对strlen、memcpy之类的通用函数的实现。

    mm:很明显啦,这个是体系结构相关的内存管理的实现。

    大多数的子目录都包含boot这个子目录,在硬件平台上启动内核的所使用的部分或全部代码。

    3)    drivers    这里有显卡、scsi适配器pic总线、usb总线和其他的linux支持的外围设备和总线的驱动程序。是内核中最大的一个目录。

    4)    fs    文件系统。这里有VFS、各个不同文件系统的代码都在这里。

    5)    include    包含了内核中大部分的头文件。

    6)    ipc    进程间通信,包含了信号量、共享内存和其他形式的ipc的代码。

    7)    kernel    包括了进程的调度、创建、撤销和平台相关的的另一部分的核心代码。是内核最核心的部分。

    8)    init    内核初始化部分的代码。包括main.c及创建早期用户空间的代码等。

    9)    lib    库代码

    10)    mm    与体系结构无关的内存管理部分的代码。

    11)    net    网络部分的实现代码,常见的协议如TCP/IP、IPX。

    12)    scripts    这里没有代码,只有一些用来配置内核的脚本文件。当我们编译内核的时候,运行make menuconfig 之类的命令时我们就是与这个目录下的脚本在交互。

    13)    block    block层的实现。

    14)    security    linux安全模型的代码。

    15)    crypto。    内核本身的加密API,实现了常用的加密算法和散列算法,和一些压缩、CRC校验算法。

    16)    sound    声卡驱动及其他声音相关的代码。

    17)    usr    用于打包的与压缩的cpio等。

    各个文件如图:

    686159c66d940a710dd4f902d809499e.png

    到这里,当你打开linux源代码时就不会再觉得那么无助了。下面我们继续。

    下面介绍几个重要文件。

    1)    vmlinuz  内核引导文件

    vmlinuz是可引导的压缩内核,“vm”代表“Virtual Memory”。Linux能够使用硬盘空间作为虚拟内存,因此得名“vm”。vmlinuz不是可执行 的Linux内核(网上说是可以执行的内核,可能有误。因为是压缩的,要执行必须解压。望大神指教!),因此在启动阶段首要的工作就是自解压内核映像,它位于/boot/vmlinuz,它一般是一个软链接。zImage(vmlinuz,小内核小于512kb)和bzImage(vmlinuz,大内核大于512kb)都是用gzip压缩的。它们不仅是一个压缩文件,而且在这两个文件的开头部分内嵌有gzip解压缩代码。所以你不能用gunzip 或 gzip –dc解包vmlinuz。内核文件中包含一个微型的gzip用于解压缩内核并引导它。两者的不同之处在于,老的zImage解压缩内核到低端内存(第一个640K),bzImage解压缩内核到高端内存(1M以上)。如果内核比较小,那么可以采用zImage或bzImage之一,两种方式引导的系统运行时是相同的。大的内核采用bzImage,不能采用zImage。

    2)    vmlinux

    vmlinuz 是vmlinux的压缩版。

    vmlinuz结构如图:

    b2db8bc5bb173adf8f23de4a9f25f3f5.png

    3)    initrd.img

    initrd.img,即"initrd RAM disk",是一个小的映象,包含一个最小的linux系统。通常的步骤是先启动内核,对vmlinuz内核文件解压后但在真正根文件系统启动前,initrd.img文件会被加载到内存中。内核挂载initrd.img,并执行里面的脚本来进一步挂载各种各样的模块,然后发现真正的root分区,挂载并执行/sbin/init。如果没有initrd.img,那么内核就试图直接挂载root分区。

    linux的根文件系统可以存储在很多的介质上,如SCSI、IDE、USB等,如果将这些驱动都编译进了内核,那么内核将会变得非常臃肿、庞大啊!所以linux的kernel只保留了最基本的启动代码,而把各种的硬件设备的支持以模块的形式放在了initrd.img中。这样的好处是在启动的过程中可以从initrd所挂载的根文件系统中装载所需要的模块,从而可以在kernnel不变的情况下,修改initrd的内容达到灵活地支持不同的硬件。在启动完成的最后阶段,根文件系统重新挂载到其他设备上去。

    举个例子,你的硬盘是SCSI接口但你的内核又不支持这种接口,你的内核就没有办法访问硬盘,也就没法加载硬盘上的文件系统,这个怎么办呢?? initrd.img是个ram disk的映像文件。ram disk是占用一部分的内存模拟成磁盘,让我们的操作系统访问。ram disk是标准内核文件认识的设备(/dev/ram0)文件系统也是标准内核认识的文件系统。内核加载这个ram disk作为根文件系统并开始执行其中的某个文件--init(2.6以上的内核是 init文件,位于/sbin/)来加载各种模块,服务等。经过一些配置和运行后,就可以去物理磁盘加载真正的root分区了,然后又是一些配置等,最后启动成功。

    所以initrd.img的作用就是将一些驱动程序和命令工具打包到img里从而简化内核,这完全符合linux的设计思想和linux的哲学思想啊!

    4)    system.map,内核符号表,位于/boot/System.map 。当你编译一个新的内核的时候,内核的各个符号的地址就会变化,旧的内核符号表的信息对于新的内核来说是错误的,如果还用旧的内核符号表就会出错,所以会产生一个新的内核符号表即system.map

    0b1331709591d260c1c78e86d0c51c18.png

    展开全文
    weixin_36057489 2021-05-11 03:23:03
  • 等漫长的编译完成后,如下是编译结果,vmlinux生成在目录arch/arm/boot/compressed/下,内核文件生成在目录 arch/arm/boot/下;如下图 到目录/arch/<CPU>/boot下查看生成的内核文件,打开对应目录查看 ,确实生成了...

    Linux内核代码的组成

    源码目录目录分析
    /arch不同CPU架构下的核心代码。其中的每一个子目录都代表Linux支持的CPU架构
    /block块设备通用函数
    /crypto常见的加密算法的C语言实现代码,譬如crc32、md5、sha1等
    /Documentation说明文档,对每个目录的具体作用进行说明/drivers内核中所有设备的驱动程序,其中的每一个子目录对应一种设备驱动
    /firmware固件代码
    /fsLinux支持的文件系统代码,及各种类型的文件的操作代码。每个子目录都代表Linux支持的一种文件系统类型
    /include内核编译通用的头文件
    /init内核编译通用的头文件
    /init内核初始化的核心代码
    /ipc内核中进程间的通信代码
    /kernel内核的核心代码,此目录下实现了大多数Linux系统的内核函数。与处理器架构相关的内核代码在/kernel/$ARCH/kernel
    /lib内核共用的函数库,与处理器架构相关的库在/kernel/$ARCH/lib
    /mm内存管理代码,譬如页式存储管理内存的分配和释放等。与具体处理器架构相关的内存管理代码位于/arch/$ARCH/mm目录下
    /net网络通信相关代码
    /samples示例代码
    /scripts用于内核配置的脚本文件,用于实现内核配置的图形界面
    /security安全性相关的代码
    /toolsLinux中的常用工具
    /usr内核启动相关的代码
    /virt内核虚拟机相关的代码

    Linux内核配置和编译
    1,工具链
    根据相关的工具链安装好自己开发板的工具链(ACROSS_COMPILE).否则在配置编译内核时会找不到arm-linux-等交叉编译工具,而导致无法编译。工具链的安装可以参考我之前发表的交叉编译工具的安装:https://blog.csdn.net/weixin_38251305/article/details/104109723
    2,配置内核就是决定需要编译的代码
    3,编译内核就是生成可执行文件vmlinux,zimage和uImage的过程

    Linux内核具有可制定的有点,具体的内核配置步骤如下:
    1)清除临时文件,中间文件和配置文件

    2)从www.kernel.org上下载Linux内核代码,




    点击进入下一个界面,下拉找到linux内核源码压缩包

    也可以在ubuntu下用命令: wget进行下载,如

    3)我下的是linux-3.8.3版本的,然后拷贝到ubuntu目录下进行减压

    4) 进入到减压后lnux内核文件的顶层(根)目录,执行make clean或make distclean,make rmclean进行清除相关做过的配置(前提:如果做过的一些配置想清除就执行这三个命令清除掉就好了)

    如图,是我已经做过的配置然后编译产生了vmImage可执行文件,这时若我想重新配置里内核,我就会执行make distclean将之前做过的配置清除。如

    在执行make distclean等清除命令时,可能要切换到root用户。
    5)内核配置
    <1>确定目标系统的硬件配置情况,比如CPU(处理器,可在内核文件目录arch/下查看)的类型,网卡的型号,所需支持的网络协议等。

    如图,目录arch/下的各个 类型处理器。
    <2>可使用如下命令之一进行配置内核:

    注:当在Ubuntu下运行命令make menuconfig时可能会出错,如下   
    
    * Unable to find the ncurses libraries or the
        * required header files.
        * ‘make menuconfig’ requires the ncurses libraries.
        * Install ncurses (ncurses-devel) and try again.
        make[1]: * [scripts/kconfig/dochecklxdialog] Error 1
        make: * [menuconfig] Error 2
    

    解决办法是,安装相应的库,执行如下命令

    $sudo apt-get install lncurses-dev
    $sudo apt-get install libncurses5-dev
    

    再运行make menuconfig时就可以了,如下图是成功运行跳出的配置界面

    这里我推荐用make menuconfig配置内核


    Make menuconfig有3种相应的选择:
    Y--将该功能编译进内核
    N--不将该功能编译进内核
    M--将该功能编译成可以在需要时动态插入到内核中的模块
    Make menuconfig工具菜单里如何选择配置内核的配置详解
    https://blog.csdn.net/xuyuefei1988/article/details/8635539

    除此外,运行make xconfig时可能也会出错,因为缺少一些qt相关的包,出错如下

    解决办法:安装以下依赖库

    sudo apt-get install kernel-packagesudo 
    apt-get install build-essentialsudo
    apt-get install libqt3-headers libqt3-mt-dev
    

    安装完,再执行make xconfig就可以了。
    <3>这里我选择用make menuconfig工具来进行内核的相关配置,配置完后选择Exit进行退出,如下:

    当保持退出时,你所做的相关配置就会生效,此时这些配置会自动生成一个.config文件,如下

    在内核文件顶层目录下运行:ls -a亦可查看到,如下

    <4>清除配置的相关文件,make distclean

    6)在第5)的内核配置完,在内核顶层文件里生成.config配置文件之后。因为要确保生成.config文件后编译内核才能生成相应的,vmlinux,zImage,uImage文件否则编译内核会因为缺少.config文件而报错,报错如下:

    7)获取.config文件,.config文件可以由配置内核时生成,也可以从linux内核代码里提供的已有的.config获取;在内核目录 arch/arm/configs/下可以找到与你开发板的处理器型号相应的config(配置文件)文件,如下图

    将里面的配置文件拷贝到顶层目录即可,若你的板子是其他处理器型的,不是arm处理器,你只需在/arch目录下找到相应的处理器文件,进入到相应的/configs目录下拷贝相对应的config文件即可。这里以arm处理器的s5pv210为例演示,如下

    进入confis目录将相应的config 文件拷贝到顶层目录

    拷贝成功如下

    8)得到了.config后,还需要修改顶层的Makefile文件,否则会默认为x86平台,
    需改的地方如下,打开Makefile文件


    配置完Makefile文件就可以开始编译内核了;如图选择相应的编译方式进行内核的编译

    我选择用,make zImage V=1;大V=1的作用:编译过程中会显示相应的编译信息,如下图


    等漫长的编译完成后,如下是编译结果,vmlinux生成在目录arch/arm/boot/compressed/下,内核文件生成在目录 arch/arm/boot/下;如下图

    到目录/arch/<CPU>/boot下查看生成的内核文件,打开对应目录查看 ,确实生成了相应的vmlinux ,zImage 文件我编译好的内核如下:

    【注意】如果.config文件是由make menuconfig 等配置方式生成的,在运行make zImage 编译时不会出现 相关的配置选项信息。若是从内核提供中复制cp过来的 ,在运行make zImage 编译时会出现相关的配置选项信息。此时 根据自己的配置需求选择即可 。
    【提示】

    • vmlinux是原始的,未经压缩的可执行文件
    • zImage是压缩的可执行文件:压缩vmlinux后,加上一个头,这个头由一些程序组成,这些程序是用来解压的。
    • uImage其实就是用于给uboot引导的zImage
      **9)编译内核模块 **
    $make modules 
    

    编译成功,如下

    10)安装内核模块

    $make modules_install
    

    将编译好的内核模块从内核代码目录coopy 至/lib/modules下 。
    编译成功,结果如下图

    11)制作init ramdisk

    init ramdisk 的解析https://blog.csdn.net/xys0610/article/details/52613149
    在用命令mkinitrd 编译时,由于ubuntu 找不到命令mkinitrd, 因为ubunut下没有这个命令,取而代之的是mkinitramfs,使用mkinitramfs命令就可以,命令格式:

    #将/lib/modules/下的内核模块3.8.3 编译成ramDisk文件 initrd.img.3.8.3
    $mkinitramfs -o initrd.img.3.8.3  /lib/modules/3.8.3
    

    3.8.3 是刚才编译生成的内核模块,在/lib/modules/下。

    【补充】关于Ramdisk 的介绍

    先介绍一下什么是RamDisk。RamDisk实际是从内存中划出一部分作为一个分区使用,换句话说,就是把内存一部分当做硬盘使用,你可以向里边存文件。那么为什么要用RamDisk呢?假设有几个文件要频繁的使用,你如果将它们加到内存当中,程序运行速度会大副提高,因为内存的读写速度远高于硬盘。况且内存价格低廉,一台PC有2G已不是什么新鲜事。划出部分内存提高整体性能不亚于更换新的CPU。何乐而不为呢?象WEB服务器这样的计算机,需要大量的读取和交换特定的文件,因此,在WEB服务器上建立RamDisk会大大提高网络读取速度。在进行内核编译时,需要进行制作initrd.img.在Fedora下面一般是用mkinitrd,而在Ubuntu/Debian下是用mkinitramfs.**
    

    12) 安装内核(这里以x86平台为例,其他平台同理)

    $cp arch/x86/boot/bzImage /boot/vmlinuz-$version 
    $cp initrd.img.3.8.3  /boot/
    

    ** $version为编译的内核版本号**
    ** 再将生成initrd.img.3.8.3复制到 /boot/,作为新的initrd.img即可 **
    然后修改/etc/grub.conf 或者 /etc/lilo.cong ,但是ubuntu下没有这两个配置文件,
    RedHat的开机系统选择配置文件是/etc/grub.conf!!!!!后来查了查发现ubuntu11.10没有grub.conf文件取而代之的是/boot/grub/grub.cfg

    以上便是内核的配置和编译过程,希望对你有帮助

    展开全文
    weixin_38251305 2020-02-11 19:28:13
  • csdn__lc 2017-06-30 22:32:14
  • weixin_39800957 2021-05-28 08:19:02
  • weixin_36089077 2021-05-11 03:24:12
  • sean_8180 2018-08-18 19:34:30
  • weixin_42067188 2020-07-19 03:19:50
  • hongbochen1223 2015-08-18 15:51:10
  • Ace_Shiyuan 2020-06-09 16:30:49
  • weixin_34390105 2017-08-04 15:56:35
  • manongxianfeng 2021-03-18 15:50:04
  • weixin_39809140 2021-05-10 20:08:03
  • qq_37363920 2020-04-08 13:59:38
  • weixin_29446845 2021-06-02 19:44:33
  • HowieXue 2017-08-05 00:23:23
  • dahailantian1 2017-11-20 17:50:53
  • akpar00 2017-02-03 15:15:14
  • qq_33511280 2017-03-12 09:42:27
  • qq_21792169 2018-12-19 15:17:09
  • zyllong 2014-08-13 15:56:49

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 8,129
精华内容 3,251
关键字:

文件编译完成的zimage