uClinux 启动过程详细分析.docx

上传人:b****5 文档编号:7645398 上传时间:2023-01-25 格式:DOCX 页数:21 大小:77.99KB
下载 相关 举报
uClinux 启动过程详细分析.docx_第1页
第1页 / 共21页
uClinux 启动过程详细分析.docx_第2页
第2页 / 共21页
uClinux 启动过程详细分析.docx_第3页
第3页 / 共21页
uClinux 启动过程详细分析.docx_第4页
第4页 / 共21页
uClinux 启动过程详细分析.docx_第5页
第5页 / 共21页
点击查看更多>>
下载资源
资源描述

uClinux 启动过程详细分析.docx

《uClinux 启动过程详细分析.docx》由会员分享,可在线阅读,更多相关《uClinux 启动过程详细分析.docx(21页珍藏版)》请在冰豆网上搜索。

uClinux 启动过程详细分析.docx

uClinux启动过程详细分析

uClinux启动过程详细分析

级别:

中级

余涛(yut616@),高级软件工程师

2007年6月28日

uclinux启动的详细过程有着诸多的信息可以给我们巨大的启发,我们在这里讨论的就是要对这些信息做一个具体细致的分析,通过我们的讨论,大家会对uclinux启动过程中出现的、以前感觉熟悉的、但却又似是而非的东西有一个确切的了解,并且能了解到这些输出信息的来龙去脉。

uclinux的启动过程,它是一幅缩影图,对它有了一个详细的了解后,有助于指导我们更加深入地了解uclinux的核心。

大家对uclinux的启动应该都比较熟悉,作为一名嵌入系统开发者,你一定遇到过下面的情景:

在某论坛上看到一篇帖子,上面贴着uclinux开发板启动时的一堆信息,然后大家在帖子里讨论着这个启动过程中出现的问题,随机举例如下:

Linuxversion2.4.20-uc1(root@Local)(gccversion2.95.3

20010315(release)(ColdFirepatches-20010318fromhttp:

//f

(uClinuxXIPandsharedlibpatchesfrom#20三6月1

800:

58:

31CST2003

Processor:

SamsungS3C4510Brevision6

Architecture:

SNDS100

Onnode0totalpages:

4096

zone(0):

0pages.

zone

(1):

4096pages.

zone

(2):

0pages.

Kernelcommandline:

root=/dev/rom0

Calibratingdelayloop...49.76BogoMIPS

Memory:

16MB=16MBtotal

Memory:

14348KBavailable(1615Kcode,156Kdata,40Kinit)

Dentrycachehashtableentries:

2048(order:

2,16384bytes)

Inodecachehashtableentries:

1024(order:

1,

Mount-cachehashtableentries:

512(order:

0,4096bytes)

Buffer-cachehashtableentries:

1024(order:

0,4096bytes)

Page-cachehashtableentries:

4096(order:

2,16384bytes)

POSIXconformancetestingbyUNIFIX

LinuxNET4.0forLinux2.4

BaseduponSwanseaUniversityComputerSocietyNET3.039

InitializingRTnetlinksocket

Startingkswapd

SamsungS3C4510Serialdriverversion0.9(2001-12-27)withnoserialoptionsen

abled

ttyS00at0x3ffd000(irq=5)isaS3C4510B

ttyS01at0x3ffe000(irq=7)isaS3C451

Blkmemcopyright1998,1999D.JeffDionne

Blkmemcopyright1998KennethAlbanowski

Blkmem1diskimages:

0:

BE558-1A5D57[VIRTUALBE558-1A5D57](RO)

RAMDISKdriverinitialized:

16RAMdisksof1024Ksize1024blocksize

SamsungS3C4510Ethernetdriverversion0.1(2002-02-20)

eth0:

00:

40:

95:

36:

35:

34

NET4:

LinuxTCP/IP1.0forNET4.0

IPProtocols:

ICMP,UDP,TCP

IP:

routingcachehashtableof512buckets,4Kbytes

TCP:

Hashtablesconfigured(established1024bind1024)

VFS:

Mountedroot(romfs

Freeinginitmemory:

40K

上面的这些输出信息,也可能包括你自己正在做的uclinux开发板的输出信息,其中的每一行,每一个字的含义,你是否深究过,或者说大部分的含义你能确切地知道的?

本人想在这里结合本人在实践中一些体会来和广大uclinux的开发者一起读懂这些信息。

我们在这里将以一个真实的uclinux系统的启动过程为例,来分析这些输出信息。

启动信息的原始内容将用标记标出,以区别与注释。

uclinux的启动主要分为两个阶段:

∙①第一部分bootloader启动阶段

∙②第二部分linux内核初始化和启动阶段

o第一节:

start_kernel

o第二节:

用户模式(user_mode)开始,start_kernel结束

o第三节:

加载linux内核完毕,转入cpu_idle进程

第一部分:

bootloader启动

图1:

uclinux启动状态转移示意图

Bootloaderv0.12

NOTE:

thisbootloaderisdesignedtobootkernelsmadewiththe

2.4.xxreleases

bootloaderforXV

BuiltatNov20200510:

12:

35

Bootloader头信息,版本,编译时间等,这个因不同的bootloader的设计而有所不同,由此你能看出bootloader的版本信息,有很多使用的是通用的bootloader,如u-boot,redboot等。

Loadedto0x90060000

将bootloader加载到内存ram中的0x90060000处,即将bootloader加载到内存的高端地址处。

Linux内核将被bootloader加载到0x90090000处。

Foundbootconfiguration

查找到了启动boot的配置信息。

Bootedfromparallelflash

从flash中启动代码,此处的flash为并行闪存。

注意:

任何flash器件的写入操作只能在空或已擦除的单元内进行,所以大多数情况下,在进行写入操作之前必须先执行擦除。

NAND器件执行擦除操作是十分简单的,而NOR则要求在进行擦除前先要将目标块内所有的位都写为0。

从上面的信息,我们可以对flash类型特点有个比较明确的了解。

CPUclockrate:

200MHz

开发板上所使用的CPU的主频为200MHZ。

DRAMsizeis128MB(128MB/0MB)

动态内存ram大小为128M。

在嵌入式系统中使用DRAM内存的设计比较广泛。

在uclinux的系统中,系统运行时间较长后,会出现内存碎片的问题,导致再分配大块内存时会失败。

这是在uclinux系统中经常遇到的问题,解决的办法通常有使用静态内存、应用程序启动时预先分配大内存、使用内存池等。

地址辅助说明:

先说明一下内存地址数字情况,主要是为了方便记忆。

可以访问的内存为4G。

0x40000000是1GB处;

0x00040000是256K处,

0x00020000是128K处,

0x90000000是2GB多的地方。

1M->0x00100000,

2M->0x00200000,

8M->0x00800000,

16M->0x01000000,

32M->0x02000000,

256M->0x10000000,

64K->0x00010000,

4K->0x00001000

这个是个快速记忆的方法,你可以根据地址中1的位置和其后0的个数来快速知道换算后的地址是在多少兆的地方。

比如,1的后面5个0,代表1M的大小,6个0,代表16M,以此类推。

ROMFSfoundat0x46040000,Volumename=rom43f291aa

romfs,只读文件系统所在的地址为:

0x46040000(flash映射后的第3分区)。

卷名为rom。

romfs和rootfs概念上有所区别。

flash在内存中的的起始地址为0x46000000,而ROMFS在flash分区上的起始位置为0x00040000,所以ROMFS在内存地址中的位置就为0x46040000。

这个细节的部分可以参考flash分区时的地方,Creating3MTDpartitions。

romfs中包括kernel和app应用,不包括bootloader和firmware信息头。

romfs只读文件系统里的内容有很多种分类方法,我们可以将kernel和app同时放里面,作为根文件系统下的一个文件,也可以在flash上另外划分区域来分别存放。

注意:

rootfs并不是一个具体的文件系统类型,如jffs。

它只是一个理论上的概念。

在具体的嵌入系统实例中,可以将某种具体的文件系统设置为根文件系统rootfs,如我们可以设置romfs为根文件系统,也可以设置jffs为根文件系统。

这里的ROMFS只读文件系统只是一种具体的文件系统类型,也是在嵌入系统中经常使用到的类型。

看完了上面的内容,以后你对出现的类似“kernelPanic:

VFS:

Unabletomountrootfson0:

00”的含义应该已经了解了。

其中“VFS:

”就是虚拟文件系统管理器操作时的输出信息了。

Filelinux.bin.gzfound

linuxkernel内核文件名,它是在只读文件系统romfs上的一个组成部分。

Unzippingimagefrom0x4639DE60to0x90090000,size=1316021

将romfs中的linuxkernel解压缩到0x90090000,之后会从这个内存地址启动内核。

romfs为压缩格式文件,使用压缩的只读文件系统,是为了保持制作出来的整个系统所占用的flash空间减小。

这个内核的大小为1.3M左右,这也是目前大多数嵌入系统所使用的方法。

Inptr=0x00000014(20)

Inflating....

释放……

Outcnt=0x0030e7c8(3205064)

FinalInptr=0x001414ad(1316013)

OriginalCRC=0xcbd73adb

ComputedCRC=0xcbd73adb

做释放后的CRC检查。

Bootkernelat0x90090000withROMFSat0x46040000

kernel已经被从romfs中释放到内存地址0x90090000处,可以跳转到此处启动kernel了,这里是指定的kernel的起始地址。

Press'enter'toboot

系统等待启动,后面将看到linuxkernel的启动过程了。

第二部分:

linux内核初始化以及启动

第一节:

start_kernel

Linux的源代码可以从www.kernel.org得到,或者你可以查看linux代码交叉引用网站:

http:

//lxr.linux.no/进行在线的代码查看,这是一个很好的工具网站。

在start_kernel中将调用到大量的init函数,来完成内核的各种初始化。

如:

图2:

kernelstartup初始化过程

具体内容可以参考[http:

//lxr.linux.no/source/init/main.c]

Linuxversion2.4.22-uc0(root@local)(gccversion2.95.320010315(release))#33.?

1..2012:

09:

106

上面的代码输出信息,是跟踪linux代码分析后得到的,进入init目录下的main.c的start_kernel启动函数。

uclinux使用的是linux内核版本为2.4.22。

linuxsourcecode代码中start_kernel中输出的linux_banner信息。

这个信息是每个linuxkernel都会打印一下的信息,如果你没有把这句去掉的话。

Foundbootloadermemorymapat0x10000fc0.

bootloader经过内存映射后的地址为:

0x10000fc0,按上面的地址换算方法,1后面有7个0,那么虚拟地址256M左右处。

Processor:

ARMpt110revision0

pT110是ARM微处理器arm核的一种,另一种为pT100。

此处为显示ARM的类型。

Onnode0totalpages:

20480

zone(0):

20480pages.

zone(0):

Setminimummemorythresholdto12288KB

Warning:

wrongzonealignment(0x90080000,0x0000000c,0x00001000)

zone

(1):

0pages.

zone

(2):

0pages.

预留内存大小,在节点0上总共20页,zone(0)设置最小内存为12MB,zone

(1)和zone

(2)为0页。

警告:

对齐不正确。

Kernelcommandline:

root=/dev/mtdblock3

Kernel启动命令设为:

/dev/mtdblock3(在后面的说明中会看到mtdblock3是指的flash上的romfs分区。

),用来指定根文件系统所在的位置,kernel会将块设备mtdblock3当作文件系统来处理。

也就是说,内核会根据上面的kernel命令行,知道只读文件系统romfs将是根文件系统rootfs。

start_kernel(void)中输出的上面的这句信息。

这行命令是在linux内核启动过程中都会输出的一句。

Console:

colourdummydevice80x30

代码中console_init()的输出信息,显示控制台属性:

一般使用VGAtextconsole,标准是80X25行列的文本控制台,这里是对属性进行了设置。

serial_xx:

setup_console@115

串口设置值为115200,此为波特率输出信息。

对串口设置的信息做一个打印的动作,在调试时会非常有用。

Calibratingdelayloop...82.94BogoMIPS

Calibrate:

校准,进入时延校准循环。

检查CPU的MIPS(每秒百万条指令),Bogo是Bogus(伪)的意思。

这里是对CPU进行一个实时测试,来得到一个大体的MIPS数值。

上面这个输出,在所有的linux系统启动中都会打印出来。

进入内存初始化:

mem_init(void),[arch/i386/mm/init.c]

Memory:

80MB=80MBtotal

Memory:

76592KBavailable(1724Kcode,2565Kdata,72Kinit)

当前内存使用情况,将列出总的内存大小,及分配给内核的内存大小:

包括代码部分,数据部分,初始化部分,总共刚好4M。

请留意此处的内核的内存大小的各个值。

进入虚拟文件系统VFS初始化:

vfs_caches_init()

Dentrycachehashtableentries:

16384(order:

5,131072bytes)

Inodecachehashtableentries:

8192(order:

4,65536bytes)

Mountcachehashtableentries:

512(order:

0,4096bytes)

Buffercachehashtableentries:

4096(order:

2,16384bytes)

Page-cachehashtableentries:

32768(order:

5,131072bytes)

在内存中建立各个缓冲hash表,为kernel对文件系统的访问做准备。

VFS(virtualfilesystemswitch)虚拟文件切换目录树有用到类似这样的结构表。

上面的输出信息,在一般的linux启动过程中都会看到。

POSIXconformancetestingbyUNIFIX

conformance:

顺应,一致。

即POSIX适应性检测。

UNIFIX是一家德国的技术公司,Linux原本要基于POSIX.1的,但是POSIX不是免费的,而且POSIX.1证书相当昂贵.这使得Linux基于POSIX开发相当困难.Unifix公司(Braunschweig,德国)开发了一个获得了FIPS151-2证书的Linux系统.这种技术用于Unifix的发行版UnifixLinux2.0和Lasermoon的Linux-FT。

在2.6的内核中就将上面的这句输出给拿掉了。

第二节:

用户模式(user_mode)开始,start_kernel结束

图3:

用户模式初始化

PCI:

bus0:

Fastbacktobacktransfersdisabled

PCI:

ConfiguredXXasaPCIslavewith128MBPCImemory

PCI:

EachRegionsizeis16384KB

PCI:

Reservedmemoryfrom0x10080000to0x15080000forDMAandmappedto0x12000000

设备的初始化init()--->do_basic_init()--->pci_init(),初始化PCI,检测系统的PCI设备。

LinuxNET4.0forLinux2.4

BaseduponSwanseaUniversityComputerSocietyNET3.039

英国威尔士,斯旺西大学的NET3.039,TCP/IP协议栈。

此信息,在linux启动过程中都会出现。

InitializingRTnetlinksocket

对Socket的初始化,socket_init(),Netlink一种路由器管理协议(linux-2.4.22\net\core\Rtnetlink.c,Routingnetlinksocketinterface:

protocolindependentpart。

其中RT是route路由的意思。

这句输出是在create产生rtnetlink的socket套接字时的一个调试输出。

此信息,在linux启动过程中都会出现。

Startingkswapd

启动交换守护进程kswapd,进程IO操作例程kpiod。

kswapd可以配合kpiod运行。

进程有时候无事可做,当它运行时也不一定需要把其所有的代码和数据都放在内存中。

这就意味着我们可以通过把运行中程序不用的内容切换到交换分区来更好的是利用内存。

大约每隔1秒,kswapd醒来并检查内存情况。

如果在硬盘的东西要读入内存,或者内存可用空间不足,kpiod就会被调用来做移入/移出操作。

kswapd负责检查,kpiod负责移动。

JournalledBlockDevicedriverloaded

加载日志块设备驱动。

日志块设备是用来对文件系统进行日志记录的一个块设备。

日志文件系统是在传统文件系统的基础上,加入文件系统更改的日志记录。

它的设计思想是:

跟踪记录文件系统的变化,并将变化内容记录入日志。

日志文件系统在磁盘分区中保存有日志记录,写操作首先是对记录文件进行操作,若整个写操作由于某种原因(如系统掉电)而中断,系统重启时,会根据日志记录来恢复中断前的写操作。

在日志文件系统中,所有的文件系统的变化都被记录到日志,每隔一定时间,文件系统会将更新后的元数据及文件内容写入磁盘。

在对元数据做任何改变以前,文件系统驱动程序会向日志中写入一个条目,这个条目描述了它将要做些什么,然后它修改元数据。

devfs:

v1.12c(20020818)RichardGooch(rgooch@atnf.csiro.au)

devfs:

boot_options:

0x1

Devfs模块的输出信息。

设备文件系统devfs,版本1.12c

pty:

256Unix98ptysconfigured

Pty模块的输出信息,与控制台操作有关的设置。

将通过devpts文件系统使用Unix98PTYs,(Pseudo-ttys(telnetetc)device是伪ttys设备的缩写。

∙①TTY(/dev/tty)是TeleTYpe的一个老缩写,为用户输入提供不同控制台的设备驱动程序。

它的名字来源于实际挂接到UNIX系统的、被称为电传打字机(teletype)的终端。

在Linux下,这些文件提供对虚拟控制台的支持,可以通过按<Alt-F1>到<Alt-F6>键来访问这些虚拟控制台。

这些虚拟控制台提供独立的、同时进行的本地登录对话过程

∙②ttys(/dev/ttys)是计算机终端的串行接口。

/dev/ttyS0对应MS-DOS下的COM1。

使用makedev脚本MAKEDEV来建立pty文件。

这样系统内核就支持Unix98风格的pty了。

在进行Telnet登录时将要用到/dev/pty设备。

pty是伪终端设备,在远程登录等需要以终端方式进行连接,但又并非真实终端的应用程序中必须使用这种设备,如telnet或xterm等程序。

Linux2.2以后增添了UNIX98风格的Pty设备,它使用一个新的文件系统(devpts针对伪终端的文件系统)和一个克隆的设备cloningdevice来实现其功能。

linux-2.4.22\drivers\char\Pty.c,在devfs_mk_dir(NULL,"pts",NULL);时会输出上面的信息。

loop:

loaded(max8devices)

加载返还块设备

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 农林牧渔 > 林学

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1