5秒启动wince

[复制链接]
3372|2
 楼主| high 发表于 2008-6-5 04:50 | 显示全部楼层 |阅读模式
理解BinFS,&nbsp;Multi-XIP,&nbsp;Multi-bin<br /><br />欢迎访问:&nbsp;www.chenyq2008.spaces.live.com<br /><br />----------------------------------<br /><br />[bin文件的格式]<br />Bin文件格式比较简单.前面7个字节是标志,&nbsp;固定的{‘B’,&nbsp;‘0’,&nbsp;‘0’,&nbsp;‘0’,&nbsp;‘F’,&nbsp;‘F’,&nbsp;‘a’}.&nbsp;接下来4个字节是Image&nbsp;Start表示image的开始地址,&nbsp;这个地址,按我想其实就是加载地址了.&nbsp;然后4个字节是Image&nbsp;Length,表示image的长度.&nbsp;下面这个结构体说明了bin文件的格式.&nbsp;<br /><br />struct&nbsp;BinFile&nbsp;{&nbsp;<br /><br />BYTE&nbsp;signature[7];&nbsp;<br /><br />DWORD&nbsp;ImageStart;&nbsp;<br /><br />DWORD&nbsp;ImageLength;&nbsp;<br /><br />Record&nbsp;ImageRecords[ImageLength];&nbsp;<br /><br />}&nbsp;<br /><br />其中Record的结构是&nbsp;<br /><br />struct&nbsp;Record{&nbsp;<br /><br />DWORD&nbsp;address;&nbsp;<br /><br />DWORD&nbsp;length;&nbsp;<br /><br />DWORD&nbsp;chksum;&nbsp;<br /><br />}&nbsp;<br /><br />[BinFS]<br />bin文件则是由romimage.exe产生的文件,包含image,是image的载体形式.&nbsp;我们的nk.bin就是由romimage产生的image文件了.&nbsp;Binfs是Binary&nbsp;Rom&nbsp;Image&nbsp;File&nbsp;System.&nbsp;是一个文件系统.&nbsp;Binfs和bin文件什么关系?&nbsp;<br /><br />下面的描述是我的猜测:&nbsp;因为binfs是基于bin的一种文件格式.(A)bin是一个简单的,线性分布的记录的集合(B).大部分的Bin,其中的record是压缩后的数据.&nbsp;所以使用binfs时候,&nbsp;驱动处理record包含一个解压过程,&nbsp;继而再呈现为磁盘文件.&nbsp;这是文件系统驱动在binfs读文件的情况,&nbsp;反过来写就十分困难.如果期望在binfs上创建或者修改,&nbsp;设想下,&nbsp;先需要把文件处理成为record,&nbsp;为了替换原来的record,&nbsp;更可怕的是,&nbsp;binfs是一个简陋之极的filesystem,&nbsp;它的所有的record是线性连续分布的,&nbsp;它甚至都不是一个链表…所以对其任意修改都是伤筋动骨的.&nbsp;因此在binfs.dll的fsd驱动里面,&nbsp;FSD_WriteFile,&nbsp;FSD_SetFileTime…这样的需要修改binfs等函数接口全部都是设置一个错误:SetLastError(&nbsp;ERROR_ACCESS_DENIED);然后返回.&nbsp;因此直接替换一个或者几个record是困难的.最好重新整体打包一个bin,&nbsp;然后替换掉binfs,&nbsp;那么另外一个问题,&nbsp;如果打包后的binfs超过原来的大小了,&nbsp;还得修改磁盘分区表……&nbsp;话说回来,&nbsp;binfs设计的目的也就是一个只读的filesystem,&nbsp;是image载体.再次体会下binfs的名称:Binary&nbsp;Rom&nbsp;Image&nbsp;File&nbsp;System.&nbsp;如果你非得打入敌人内部,&nbsp;可以仔细看看romimage的源代码,&nbsp;它提供了一些有意义的工具来帮助你,&nbsp;catbin,&nbsp;compress,&nbsp;sortbin,&nbsp;viewbin,&nbsp;cvrtbin,&nbsp;stampbin,&nbsp;checksymbols.&nbsp;<br /><br />Eboot能识别bin文件格式,在写image的时候,&nbsp;把bin文件里面image写入到flash&nbsp;加载的时候,&nbsp;把image读出到内存正确地址.&nbsp;bin也许会用到压缩image.&nbsp;eboot并没有解压image,&nbsp;只是忠实的按照地址执行拷贝过程.&nbsp;<br /><br />[Multi-XIP]&nbsp;<br />XIP&nbsp;:&nbsp;Excute-in-place.本地执行.&nbsp;意思是可以直接执行而不需要拷贝到内存执行.&nbsp;比如nor&nbsp;flash&nbsp;和&nbsp;masked&nbsp;ROM设备,&nbsp;上面的代码都可以XIP,&nbsp;而nand不行.&nbsp;Multi-XIP的意思是在把一个image分成多个XIP&nbsp;regions.&nbsp;从而可以分布在ROM的不同地址.&nbsp;<br /><br />那么Multi-XIP什么意思?&nbsp;本来image是一个连续分布的整体,需要install在一块连续的ROM&nbsp;区域或者nor区域.&nbsp;而Multi-XIP技术可以将这个整体打散成几个.&nbsp;这就是我最简单的理解了.基于Multi-XIP,&nbsp;就可以将image分散分布在各个ROM了.&nbsp;<br /><br />[Multi-bin]&nbsp;<br />在文档也会看到Multi-bin的字眼.&nbsp;那么Multi-XIP和Multi-bin什么联系和区别?下面又是我的猜测:&nbsp;<br /><br />字面上Multi-bin是很多个bin的意思了.&nbsp;Bin只是image的一种载体形式.&nbsp;对image也许会有许多格式,&nbsp;比如hex,&nbsp;nb0…所以,我想,&nbsp;Multi-bin是Multi-XIP的一种.&nbsp;<br /><br />[加快启动速度和节省ram]<br />这部分描述的特性一定强烈吸引人.&nbsp;Multi-XIP&nbsp;只是把一个image分成几个regions,&nbsp;并不会加快启动速度和节省ram.&nbsp;怎么才会呢?&nbsp;要知道一个WinCE的image里面很多的文件并不是启动时候需要加载到ram的.&nbsp;设想我们如果能够把必须的部分加载到内存,&nbsp;其余的部分仍然留在nand中,&nbsp;等到需要的时再从nand磁盘加载.&nbsp;这一方面使得加载到内存的image大幅减小,&nbsp;从而加快了从nand拷贝到ram的速度.&nbsp;另外,&nbsp;也减少了对ram的占用.&nbsp;<br /><br />所以,&nbsp;达到这个目的有2个要求,&nbsp;<br /><br />(A)&nbsp;能够把一个image打散,&nbsp;至少打成2个,一个是关键性的启动必要文件,&nbsp;另外一个是在启动后动态加载.&nbsp;这不就是Multi-XIP技术了吗?&nbsp;<br /><br />(B)&nbsp;为了能作内核启动后动态加载,&nbsp;需要把image做成文件系统.&nbsp;这不就是binfs了吗&nbsp;<br /><br />[分析]<br />在WinCE5.0&nbsp;+arm920t&nbsp;+&nbsp;64M&nbsp;SDRAM&nbsp;+&nbsp;64M&nbsp;nand的系统,&nbsp;我成功的实现了multi-xip和binfs.&nbsp;上电到桌面跳出时间缩短到5秒内.&nbsp;可用内存也大幅增加到60M多.&nbsp;<br /><br />实现这项特性的关键还是要对系统的启动非常熟悉.&nbsp;简单描述下启动过程如下:&nbsp;<br /><br />还是那张图(到之前的**可以找到),&nbsp;这次我们关注的是KernelInit部分.&nbsp;其中ProcInit()把nk.exe作为当前进程,准备好了,&nbsp;SchedInit()把nk.exe的启动函数地址设置为SystemStartupFunc,&nbsp;所以FirstSchedule()之后,&nbsp;nk.exe开始运行了,&nbsp;从SystemStartupFunc开始了&nbsp;<br /><br />SystemStartupFunc()&nbsp;<br /><br />{&nbsp;<br /><br />KernelInit2();&nbsp;<br /><br />加载coredll.dll,&nbsp;并取得几个api函数地址&nbsp;<br /><br />如果定义了START_KERNEL_MONITOR_THREAD宏,则启动线程Monitor1内核线程&nbsp;<br /><br />创建并启动PowerHandlerGuardThrd内核线程.&nbsp;<br /><br />加载shimeng.dll&nbsp;<br /><br />创建并启动CleanDirtyPagesThread内核线程.&nbsp;<br /><br />创建并启动RunApps内核线程.&nbsp;<br /><br />While(1)&nbsp;<br /><br />{&nbsp;<br /><br />无限等待hAlarmThreadWakeup.并处理.&nbsp;<br /><br />}&nbsp;<br /><br />}&nbsp;<br /><br />在KernelInit2()函数中,&nbsp;会加载kd.dll(kernel&nbsp;debug),&nbsp;hd.dll,&nbsp;osaxst0.dll,&nbsp;osaxst1.dll,&nbsp;kcover&nbsp;<br /><br />.dll,&nbsp;celog.dll.&nbsp;但这些dll包括后面的shimeng.dll都不是必须的.至少不是这个阶段必须的.&nbsp;<br /><br />关键在RunApps这个线程里面,&nbsp;它启动了filesys.exe&nbsp;<br /><br />RunApps()&nbsp;<br /><br />{&nbsp;<br /><br />CreateProcess(filesys.exe…)并等待注册表准备好事件.&nbsp;<br /><br />InitMUILanguages();&nbsp;<br /><br />}&nbsp;<br /><br />这个InitMUILanguages是多国语言的初始化.&nbsp;这里需要使用wince.nls这个文件.否则,&nbsp;在我的平台会出现3个data&nbsp;abort.导致启动失败.&nbsp;我的测试平台是英文locale.&nbsp;<br /><br />这阶段总结下,&nbsp;需要的有nk.exe(也就是kern.exe,&nbsp;kernkitl.exe,&nbsp;kernprof.exe之一),&nbsp;coredll.dll,&nbsp;wince.nls.filesys.exe.&nbsp;其他的kd.dll(kernel&nbsp;debug),&nbsp;hd.dll,&nbsp;osaxst0.dll,&nbsp;osaxst1.dll,&nbsp;kcover&nbsp;<br /><br />.dll,&nbsp;celog.dll和shimeng.dll经实践都不是必须的.&nbsp;酌情加入.&nbsp;<br /><br />[Filesys.exe的启动过程]<br />Filesys.exe被创建启动,&nbsp;先执行Init()函数,&nbsp;在Init()里面调用InitStorageManager()初始化StorageManager.&nbsp;<br /><br />InitStorageManager()&nbsp;<br /><br />{&nbsp;<br /><br />创建并注册相关api.&nbsp;<br /><br />创建消息队列&nbsp;<br /><br />创建PNPThread线程&nbsp;<br /><br />AutoLoadFileSystems()&nbsp;<br /><br />}&nbsp;<br /><br />在我们正常的逻辑里面,&nbsp;磁盘设备,&nbsp;块设备等都是需要先经由device.exe初始化后,&nbsp;然后交给filesys.exe来Mount.&nbsp;所以PNPThread会在运行期等待device.exe发出事件,获知pnp设备插入.&nbsp;但InitStorageManager()函数的最后一个函数调用提供了重要机制.&nbsp;使得启动时候也会有机会Mount磁盘.&nbsp;<br /><br />至此,&nbsp;注册表可访问了,&nbsp;磁盘也Mount上了.&nbsp;剩下的事情就是根据注册表的启动项来进行后面的事了.&nbsp;注册表的启动项在HKLMinit下面的launch,&nbsp;在这里设置后续加载device.exe,&nbsp;gwes.exe,&nbsp;explorer.exe,&nbsp;service.exe.&nbsp;<br /><br />总结这个阶段要用到的文件,&nbsp;<br /><br />filesys.exe和fsdmgr.dll:&nbsp;StorageManager的实现在fsdmgr.dll&nbsp;<br /><br />注册表boot.hv,&nbsp;nand&nbsp;flash的驱动即块驱动smflash.dll,&nbsp;分区驱动mspart.dll,&nbsp;2个fsd文件系统驱动fatfsd.dll和binfs.dll,&nbsp;还有一个disk&nbsp;cache模块&nbsp;diskcache.dll和fatutil.dll&nbsp;<br /><br />实现的具体工作还包括修改bib和reg.&nbsp;最重要的是config.bib的修改.还有storagemanager怎么使用注册表的配置,&nbsp;这些比较容易从网络搜索获得,&nbsp;先埋个坑,以后有时间在补充了.<br /><br /> 相关链接:<a href='http://chenyq2008.spaces.live.com/blog/cns!F73164AC8D0D8D50!218.entry'>http://chenyq2008.spaces.live.com/blog/cns!F73164AC8D0D8D50!218.entry</a>
hexenzhou 发表于 2008-6-5 16:19 | 显示全部楼层

强烈关注,我现在用的WinCE就是启动速度太慢了。希望楼主继续下文。
coke 发表于 2008-6-5 19:15 | 显示全部楼层

关注. 我的也是启动太慢

  
您需要登录后才可以回帖 登录 | 注册

本版积分规则

99

主题

1078

帖子

0

粉丝
快速回复 在线客服 返回列表 返回顶部