1.zImageåuImageçåºå«
2.一文了解Linux内核启动流程
zImageåuImageçåºå«
ä¸ãvmlinuz
vmlinuzæ¯å¯å¼å¯¼çãå缩çå æ ¸ãâvmâ代表âVirtual MemoryâãLinux æ¯æèæå åï¼ä¸åèçæä½ç³»ç»æ¯å¦DOSæKBå åçéå¶ãLinuxè½å¤ä½¿ç¨ç¡¬ç空é´ä½ä¸ºèæå åï¼å æ¤å¾åâvmâã
vmlinuzç建ç«æ两ç§æ¹å¼ãä¸æ¯ç¼è¯å æ ¸æ¶éè¿âmake zImageâå建ï¼ç¶åéè¿:âcp /usr/src/linux-2.4/arch/i/linux/boot/zImage/boot/vmlinuzâ产çãzImageéç¨äºå°å æ ¸çæ åµï¼å®çåå¨æ¯ä¸ºäºååçå ¼å®¹æ§ã
äºæ¯å æ ¸ç¼è¯æ¶éè¿å½ä»¤make bzImageå建ï¼ç¶åéè¿:âcp/usr/src/linux-2.4/arch/i/linux/boot/bzImage /boot/vmlinuzâ产çãbzImageæ¯å缩çå æ ¸æ åï¼éè¦æ³¨æï¼bzImageä¸æ¯ç¨bzip2å缩çï¼bzImageä¸çbz容æå¼èµ·è¯¯è§£ï¼bz表示âbig zImageâã bzImageä¸çbæ¯âbigâææã zImage(vmlinuz)åbzImage(vmlinuz)é½æ¯ç¨gzipå缩çãå®ä»¬ä¸ä» æ¯ä¸ä¸ªå缩æ件ï¼èä¸å¨è¿ä¸¤ä¸ªæ件çå¼å¤´é¨åå åµæ gzip解å缩代ç ãæä»¥ä½ ä¸è½ç¨gunzip æ gzip âdc解å vmlinuzã
äºãinitrd-x.x.x.img
initrdæ¯âinitial ramdiskâçç®åãinitrdä¸è¬è¢«ç¨æ¥ä¸´æ¶çå¼å¯¼ç¡¬ä»¶å°å®é å æ ¸vmlinuzè½å¤æ¥ç®¡å¹¶ç»§ç»å¼å¯¼çç¶æã
initrdæ 象æ件æ¯ä½¿ç¨mkinitrdå建çãmkinitrdå®ç¨ç¨åºè½å¤å建initrdæ 象æ件ãè¿ä¸ªå½ä»¤æ¯RedHatä¸æçãå ¶å®Linuxåè¡çæ许æç¸åºçå½ä»¤ãè¿æ¯ä¸ªå¾æ¹ä¾¿çå®ç¨ç¨åºãå ·ä½æ åµè¯·ç帮å©:man mkinitrdä¸é¢çå½ä»¤å建initrdæ 象æ件ã
æåçæçå æ ¸é象æ两ç§zImage以åuImageãå ¶ä¸zImageä¸è½½å°ç®æ æ¿ä¸åï¼å¯ä»¥ç´æ¥ç¨ubootçå½ä»¤goæ¥è¿è¡ç´æ¥è·³è½¬ãè¿æ¶åå æ ¸ç´æ¥è§£åå¯å¨ãä½æ¯æ æ³æè½½æ件系ç»ï¼å 为goå½ä»¤æ²¡æå°å æ ¸éè¦çç¸å ³çå¯å¨åæ°ä¼ éç»å æ ¸ãä¼ éå¯å¨åæ°æä»¬å¿ é¡»ä½¿ç¨å½ä»¤bootmæ¥è¿è¡è·³è½¬ãBootmå½ä»¤è·³è½¬åªå¤çuImageçé象ã
ubootæºä»£ç çtools/ç®å½ä¸æmkimageå·¥å ·ï¼è¿ä¸ªå·¥å ·å¯ä»¥ç¨æ¥å¶ä½ä¸å缩æè å缩çå¤ç§å¯å¯å¨æ 象æ件ã
mkimageå¨å¶ä½æ 象æ件çæ¶åï¼æ¯å¨åæ¥çå¯æ§è¡æ 象æ件çåé¢å ä¸ä¸ä¸ª0xåèç头ï¼è®°å½åæ°ææå®çä¿¡æ¯ï¼è¿æ ·ubootæè½è¯å«è¿ä¸ªæ 象æ¯é对åªä¸ªCPUä½ç³»ç»æçï¼åªä¸ªOSçï¼åªç§ç±»åï¼å è½½å åä¸çåªä¸ªä½ç½®ï¼ å ¥å£ç¹å¨å åçé£ä¸ªä½ç½®ä»¥åæ 象åæ¯ä»ä¹
ç¨æ³å¦ä¸ï¼
./mkimage -A arch -O os -T type -C comp -a addr -e ep -n name -d data_file[:data_file...] image
-A ==> set architecture to 'arch'
-O ==> set operating system to 'os'
-T ==> set image type to 'type'
-C ==> set compression type 'comp'
-a ==> set load address to 'addr' (hex)
-e ==> set entry point to 'ep' (hex)
-n ==> set image name to 'name'
-d ==> use image data from 'datafile'
-x ==> set XIP (execute in place)
åæ°è¯´æï¼
-A æå®CPUçä½ç³»ç»æï¼
åå¼ è¡¨ç¤ºçä½ç³»ç»æ
alpha Alpha
arm A RM
x Intel x
ia IA
mips MIPS
mips MIPS Bit
ppc PowerPC
s IBM S
sh SuperH
sparc SPARC
sparc SPARC Bit
mk MC
-O æå®æä½ç³»ç»ç±»åï¼å¯ä»¥å以ä¸å¼ï¼
openbsdãnetbsdãfreebsdã4_4bsdãlinuxãsvr4ãesixãsolarisãirixãscoãdellãncrãlynxosãvxworksãpsosãqnxãu-bootãrtemsãartos
-T æå®æ 象类åï¼å¯ä»¥å以ä¸å¼ï¼
standaloneãkernelãramdiskãmultiãfirmwareãscriptãfilesystem
-C æå®æ 象å缩æ¹å¼ï¼å¯ä»¥å以ä¸å¼ï¼
none ä¸å缩
gzip ç¨gzipçå缩æ¹å¼
bzip2 ç¨bzip2çå缩æ¹å¼
-a æå®æ 象å¨å åä¸çå è½½å°åï¼æ 象ä¸è½½å°å åä¸æ¶ï¼è¦æç §ç¨mkimageå¶ä½æ 象æ¶ï¼è¿ä¸ªåæ°ææå®çå°åå¼æ¥ä¸è½½
-e æå®æ 象è¿è¡çå ¥å£ç¹å°åï¼è¿ä¸ªå°åå°±æ¯-aåæ°æå®çå¼å ä¸0xï¼å 为åé¢æ个mkimageæ·»å ç0x个åèç头ï¼
-n æå®æ 象å
-d æå®å¶ä½æ 象çæºæ件
æå¨ç¼è¯æ¶ç¨å°çå½ä»¤å¦ä¸ï¼
# make zImage //çæzImageé象
ï¼/usr/local/arm/k9uboot/tools/mkimage -n 'Linux 2.4.' -A arm -O linux -T
kernel -C none -a 0xfc0 -e 0x -d zImage uImage
å æ ¸é象已ç»åå¤å¥½äºï¼è¿ä¸ªæ¶åæ们就è¦æ¥åå¤æ件系ç»äºãç±äºæ¶é´ç¼æ ï¼æ¬äººææ¶éç¨çæ¯å ¶ä»äººå·²ç»å¥½çæ件系ç»k9.img.gzãè¿ä¸ªæ¶åæ们è¦åçæ¯ï¼èªå·±åä¸ä¸ªç®åhello.cçç¨åºï¼ç¼è¯éè¿åå å ¥å°è¯¥æ件系ç»ä¸ï¼ç¶åä¸è½½å°ç®æ æ¿ä¸è¿è¡ã
å ç¼åhello.cï¼
ç¼è¯ï¼
#/usr/local/arm/2..3/bin/arm-linux-gcc âo start-hello hello.c
ç¼è¯åçæå¯æ§è¡æ件start-hello
ä¸é¢æä»¬å°±å¿ é¡»æ该æ§è¡æ件å å ¥å°æ件系ç»ä¸å»ï¼æ¥éª¤å¦ä¸ï¼
#gunzip k9.img.gz //解å缩
#mount âo loop k9.img /mnt/new_disk //æè½½
#cp start-hello /mnt/new_disk //å°æ件æ·è´å°æ件系ç»ä¸
#cd /mnt/new_disk
#umount /mnt/new_disk //å¸è½½
#gzip âc âv9 k9.img > k9.img.gz //å缩 çææç»çæ件系ç»
ä¸é¢æ们就è¦ä¸è½½å æ ¸ä»¥ååå¤å¥½æ件系ç»äºï¼è¿è¾¹å 说ææçå ååé æ åµå¦ä¸ï¼
Flashï¼
0x âââ 0x boot
0x âââ 0x uboot
0x âââ 0x uboot env
0x âââ 0x kernel
0x âââ 0x ramdisk
Sdramï¼
0xfc0 âââ 0xa kernel
0xa âââ ramdisk
Loadb éè¿ä¸²å£ä¸è½½æ°æ®å°ramä¸
cp.b æ·è´ramä¸çæ°æ®å°flashä¸ã
å°kernel以åæ件系ç»ramdiskä¸è½½å®æ¯ä¹åï¼æ们è¿éè¦è®¾ç½®ubootçç¯å¢åéï¼è¿æ ·ubootæè½å¤å¨ä¸çµå¯å¨çæ¶åå¯å¨å æ ¸çæä½ãç¯å¢åé设置å¦ä¸ï¼
Set cpfltoram cp.b a ffff //æ·è´æ件系ç»å°ramä¸
Set boot bootm fc0 //å¯å¨kernel
Set bootcmd run cpfltoker\;run cpfltoram\;run boot //ubootå¤ä½çæ§è¡æ令
Set cpfltoker cp.b fc0 f4fff //æ·è´å æ ¸å°ramä¸
Set bootargs root=/dev/ram rw initrd=0xa,源码4M init=/linuxrc console=ttyS0,
0,mem=m //ubootä¼ éç»å æ ¸çå¯å¨åæ°
对äºLinuxå æ ¸ï¼ç¼è¯å¯ä»¥çæä¸åæ ¼å¼çæ åæ件ï¼ä¾å¦ï¼
# make zImage
# make uImage
zImageæ¯ARM Linux常ç¨çä¸ç§å缩æ åæ件ï¼uImageæ¯U-bootä¸ç¨çæ åæ件ï¼å®æ¯å¨zImageä¹åå ä¸ä¸ä¸ªé¿åº¦ä¸º0xçâ头âï¼è¯´æè¿ä¸ªæ åæ件çç±»åãå è½½ä½ç½®ãçææ¶é´ã大å°çä¿¡æ¯ãæ¢å¥è¯è¯´ï¼å¦æç´æ¥ä»uImageç0xä½ç½®å¼å§æ§è¡ï¼zImageåuImage没æä»»ä½åºå«ãå¦å¤ï¼Linux2.4å æ ¸ä¸æ¯æuImageï¼Linux2.6å æ ¸å å ¥äºå¾å¤å¯¹åµå ¥å¼ç³»ç»çæ¯æï¼ä½æ¯uImageççæä¹éè¦è®¾ç½®ã
vmlinux ç¼è¯åºæ¥çæåå§çå æ ¸æ件ï¼æªå缩ã
zImage æ¯vmlinuxç»è¿gzipå缩åçæ件ã
bzImage bz表示âbig zImageâï¼ä¸æ¯ç¨bzip2å缩çã两è çä¸åä¹å¤å¨äºï¼zImage解å缩å æ ¸å°ä½ç«¯å å(第ä¸ä¸ªK)ï¼bzImage解å缩å æ ¸å°é«ç«¯å å(1M以ä¸)ãå¦æå æ ¸æ¯è¾å°ï¼é£ä¹éç¨zImageæbzImageé½è¡ï¼å¦ææ¯è¾å¤§åºè¯¥ç¨bzImageã
uImage U-bootä¸ç¨çæ åæ件ï¼å®æ¯å¨zImageä¹åå ä¸ä¸ä¸ªé¿åº¦ä¸º0xçtagã
vmlinuz æ¯bzImage/zImageæ件çæ·è´ææåbzImage/zImageçé¾æ¥ã
initrd æ¯âinitial ramdiskâçç®åãä¸è¬è¢«ç¨æ¥ä¸´æ¶çå¼å¯¼ç¡¬ä»¶å°å®é å æ ¸vmlinuzè½å¤æ¥ç®¡å¹¶ç»§ç»å¼å¯¼çç¶æã
vmlinuxæ¯å æ ¸æ件ï¼
zImageæ¯ä¸è¬æ åµä¸é»è®¤çå缩å æ ¸æ åæ件ï¼å缩vmlinuxï¼å ä¸ä¸æ®µè§£åå¯å¨ä»£ç å¾å°ï¼åªè½ä»0X0å°åè¿è¡ã
bzImageå¨uClinuxä¸å¾å°è§å°ã
uImageæ¯u-boot使ç¨bootmå½ä»¤å¼å¯¼çLinuxå缩å æ ¸æ åæä»¶æ ¼å¼ï¼
使ç¨å·¥å ·mkimage对æ®éçå缩å æ ¸æ åæ件ï¼zImageï¼å å·¥èå¾ãå¯ä»¥ç±bootmå½ä»¤ä»ä»»æå°å解åå¯å¨å æ ¸ã
ç±äºbootloaderä¸è¬è¦å ç¨0X0å°åï¼æ以ï¼uImageç¸æ¯zImageç好å¤å°±æ¯å¯ä»¥åbootloaderå ±åã
å¶ä½uImageçmkimage软件ï¼å¦æuClinux-distæçè¯ï¼ä¸è¬æ¾å¨uClinux-distçtoolsç®å½ä¸ã
一文了解Linux内核启动流程
本文以Linux3.版本源码为例分析其启动流程。不同版本的源码启动代码虽然存在差异,但核心的源码启动逻辑与理念保持不变。
内核映像在内存中加载并获取控制权后,源码vivado源码启动流程启动。源码由于内核映像是源码以压缩形式存储的,而非可执行文件,源码因此首要步骤是源码自解压内核映像。
内核在编译时生成vmliunx,源码通常会被压缩成zImage(小于KB的源码小内核)或bzImage(大于KB的大内核)。这些内核映像的源码品有影院源码头部包含解压缩程序。
通过查找vmlinux文件的源码链接脚本(vmlinux.lds)中的系统启动入口函数,通常在linux/arch/arm/boot/compressed目录下的源码Makefile中找到这一信息。
得到的源码内核入口函数为stext(linux/arch/arm/kernel/head.S),这是源码启动流程的关键环节。
内核启动阶段,dsd 源码 输出 usb通过查找标签__mmap_switched的位置(/linux/arch/arm/kernel/head-common.S),实现内存映射的切换。
从start_kernel函数开始,内核进入C语言部分,执行内核的品有建站源码大部分初始化任务。函数位于/lint/init/Main.c。
start_kernel函数涵盖了大量初始化工作,其中包括系统调用、内存管理、进程调度、先知抓黑马源码设备驱动等核心模块的初始化。最终,函数调用rest_init()函数完成剩余初始化。
kernel_init函数负责设备驱动程序的初始化,并调用init_post函数启动用户进程。现代版本的内核已经将init_post函数的特定任务整合到kernel_init中。
在内核初始化接近尾声时,free_initmem函数清除内存的__init_begin至__init_end区间数据。
内核启动后,运行自己的第一个用户空间应用程序_init,它是使用标准C库编译的第一个程序,进程ID为1。
_init执行其他必需的进程启动,以使系统进入全面可用的状态。
以下是内核启动流程图,以直观展示启动过程的关键步骤和顺序。