来自:liluvu > 馆藏分类
配色: 字号:
Embedded Linux Primer
2013-04-23 | 阅:  转:  |  分享 
  
Chapter2.YourFirstEmbeddedExperience



NORflash:

Itcanbedirectlyaccessedbythemicroprocessor,andcodecanevenbeexecuteddirectlyoutofNORFlash(though,forperformancereasons,thisisrarelydone,andthenonlyonsystemsinwhichresourcesareextremelyscarce).



Nandflash:

Itismoresuitableforbulkstorageinfilesystemformatthanrawbinaryexecutablecodeanddatastorage.NANDFlashdevicesimproveuponsomeofthelimitationsoftraditional(NOR)Flashbyofferingsmallerblocksizes,resultinginfasterandmoreefficientwritesandgenerallymoreefficientuseoftheFlasharray.



Flash的使用:



内存空间:

如果有硬件MMU,则使用虚拟内存空间。







Chapter5.KernelInitialization



Bootloader:

Aabootloadercontainslogicforloadingandpassingcontroltoanotherprogram,usuallyanoperatingsystemsuchasLinux。

上电后bootloader首先获得控制,对硬件作低级初始化后,控制转到linux内核。它是loader的第一阶段,控制target上电并不依赖于linux的内核。



内核构成过程图:



注意的是:在得到piggy.gz后,有个piggy.s的汇编文件,它的内容包含了对piggy.gz的引用,进行汇编后成piggy.o。



bootstraploader:

认为是loader的第二阶段,连接board-levelbootloader和linux内核,提供合适的上下文保证内核运行以及必要步骤来解压和重新定位内核镜像。bootstraploader会初始化处理器和请求内存区域,解压二进制内核镜像,并装载到系统内存合适的地方。



Boot的流程图:





内核命令行的处理:main.c中的startup代码处理内核命令行,由于不可能知道命令行参数的目标函数是什么,也不知道会由哪个内核模块来使用这个参数。所以处理时需要某种技巧,将命令行参数相关的内核模块的目标函数通过链接脚本文件放到object文件的elf节中,并在相应的内核模块中利用技巧性的宏定义来正确处理命令行参数。

类似的,在初始化时只用到一次的初始化函数和数据被放到object文件的elf节中,用后内核再释放他们占用的内存。



Chapter6.SystemInitialization



GLIBC(libc-2.3.2.so):

包含了标准c库函数,如printf()



Linuxdynamicloader(ld-2.3.2.so):

负责装载二进制可执行文件到内存中,并处理应用程序引用共享库函数的动态链接。



内核的最后启动步骤:

在内核启动的最后阶段,执行main.c的代码尾部内容是



run_init_process("/sbin/init");

run_init_process("/etc/init");

run_init_process("/bin/init");

run_init_process("/bin/sh");

panic("Noinitfound.Trypassinginit=optiontokernel.");

会执行到根文件系统中的init程序,如果四个中没有一个执行成功,内核则panic,所以mount上的根文件系统中一定要有其中的一个。



lddprog:

命令ldd查看应用程序依赖的库。



init:

init启动后,读取系统配置文件/etc/inittab,其中包含运行级别的设定(0代表halt,6代表reboot),一般运行级别是2,可以用runlevel命令来查询。还包含启动时要执行的服务脚本。



initrd:

是一种小的自包含的根文件系统,在完成启动前装载特定设备驱动如ext3,之后就可以mount真正的ext3的根文件系统。

Bootloader在装载kernel到内存后再装载initrd到可用的内存中,并负责传递initrd镜像的装载地址给kernel。

在内核的命令行参数可以指定initrd的大小和地址。



U-bootbootloader:

1.tftpboot0x10000000kernel-uImage

2.tftpboot0x10800000initrd-uboot

3.bootm0x100000000x10800000

从tftp服务器下载内核和initrdimage,放到内存中,然后从内存启动bootm。内核启动后,mountintird作为根文件系统,寻找其中的特殊文件linuxrc(当作脚本文件执行其中的命令,其中包含了mount真正文件系统所需要的命令)执行,启动系统设计者指定的initrd行为。执行完后,内核再umountinitrd,继续处理系统启动的最后阶段。内核命令行参数root=/dev/ram0被指定后,将不执行linuxrc了,并且不加载其他的根文件系统,只把initrd作为根文件系统。



Initramfs:

Itsimplifiestheinitialramdiskmechanism,whileprovidingsimilarearlystartupfacilities.Itiseasiertouse,doesnotrequireloadingaseparateimage,andisbuiltautomaticallyduringeachkernelbuild.



Chapter7.Bootloaders



Bootloader:

包含初始化硬件的代码,一般是由cpu的native汇编语言写成。由cpu在预先设定的地址读取执行。之后,启动os。



DRAM控制器:

由于DRAM芯片不像处理器总线那样能直接读或写,所以需要特殊的硬件控制器来启动读或写的周期。嵌入式系统中,bootloader最先要做的工作就是系统初始化,特别是内存系统的初始化,之后再copy自己到DRAM中,可以更快的执行。



Bootloader执行环境:

当bootloader获得控制后,由于没有初始化的DRAM等上下文执行环境,没有像c语言执行时可用的stack。在bootloader中使用linkerdescriptionfile(构建二进制可执行程序的布局),可以把代码设置在处理器hardcoded的地址处执行。



U-Bootimage的格式:

Bootloader初始化processor、board后,就可以装载和运行程序了,当装载操作系统如linux时,U-boot需要清楚kernelimage的格式才能执行它,因此,U-boot提供了工具mkimage创建一个能识别image属性的小头文件加在image内核文件开始处。



Chapter8.DeviceDriverBasics



设备驱动:

一般分为两类,字符驱动和块驱动。添加新的驱动要做的工作,2.6版需要内核树:

在内核目录树建立对应的目录,如../drivers/char/example

修改内核配置文件,添加新的驱动内容

修改Makefile,如../drivers/char/Makefile

编写驱动程序代码,除init和exit之后,根据需要添加如open、read、write、ioctl等接口,并初始化file_operations,再在init中利用register_chrdev注册到系统中



驱动的使用:

创建设备节点mknod/dev/hello1c2340,其中234是启动程序代码中指定此设备的主设备号。

用户程序中使用open打开/dev/hello1即可调用驱动程序中的编写的open。



Chapter9Filesystems



嵌入式系统一般要配置文件系统,不同的文件系统对它的性能、大小以及设备断电后的数据恢复的优化方面不同。



分区:

对存储设备进行分区,每个分区可以使用各种不同的文件系统,文件系统主要包括:FilesystemMetadata和FileSystemData.



Ext2:

格式化为ext2文件系统分区的命令:mke2fs/dev/sdb1–LMyself-setting-label-name

创建ext2文件系统后再mount/dev/sdb1/mnt/flash上。利用命令e2fsck/dev/sdb1检查文件系统的完整性当电源未预料到的断电以及打开的文件未关闭和umount文件系统时就关闭电源。而e2fsck应该只能使用在没有mount的文件系统上作检查。



Ext3:

在未预料的断电后,ext3的文件系统在启动时不需要作完整性的检查。这是通过日志来实现的,原理是:当文件系统中的文件有改变时,这个改变首先写到日志中;文件系统的驱动保证在对日志写之后,实际的改变才被提交到存储设备。在这些改变被记录到日志中后,驱动才会提交对实际文件和metadata写到存储设备上的改变。当在设备写时或重启时发生意外断电,只要replay日志中的改变就能恢复文件系统的一致性。

Ext3能够前向和后向兼容ext2,即能互相转换。通过命令tune2fs–j/deb/sdb1来实现。会产生.journal的隐藏文件。此外,还可以将日志文件创建在不同的设备上。如利用tune2fs-Jdevice=/dev/sda1-j/dev/sdb1创建/dev/sdb1为ext3文件系统,而将日志放在/dev/sda1中,但它必须是ext3的文件系统。



ReiserFS:

同ext3是日志文件系统,除此之后,它还保证了文件系统的操作要么全部完成要么什么都不做。为系统编程提供了API保证文件系统事务的原子性。对数据库程序的操作保证其数据操作的原子性。



JFFS2:

Flash存储设备的特点:由于技术的原因,它的写效率低,主要根源是block的大小,而block大小一般为成十或成百KB,它的才除只能一次一block,虽然写通常能一次执行一个字节或一个字,但是更新单个文件就必须将整个block都要擦除然后重写。因此要避免持续过多的写操作,如启动系统的log。

创建jffs2文件系统:mkfs.jffs2-d./jffs2-image-dir-ojffs2.bin,其中jffs2-image-dir中是要创建jffs2文件系统的目录结构。

ItcontainsFlash-friendlyfeaturessuchaswearleveling(损耗均衡技术)forlongerFlashmemorylifetime.(wearlevelingFLASH闪存内的每一个区域的一种软件技术。使用该技术的好处在于:可以让FLASH闪存芯片的寿命更长,出错率更低。)



Cramfs:

MeanscramafilesystemintoasmallROM.Cramfs是只读的。适用于bootROMS.创建方法:mkcramfs.../cramfs.image,挂载mount-oloopcramfs.image/mnt/flash



NFS:

在/etc/exports中列出了作为NFS要export的文件目录。有两种用途:其一是将host上的文件目录mount到target上:mount-tnfshostip-address:/home/chris/workspace/workspace.另外是将host上的目录作为target上的root文件系统,做法是配置target的内核以支持rootfilesystemonNFS,在bootloader中设置target内核的命令行如下:

console=ttyS0,115200\

ip=192.168.1.139:192.168.1.1:192.168.1.1:255.255.255.0:coyote1:eth0:off\

nfsroot=192.168.1.1:/home/chris/sandbox/coyote-target\

root=/dev/nfs

其中ip表示为ip=::::::其中意思是:client-ipisthetarget''sIPaddress;server-ipistheaddressoftheNFSserver;gw-ipisthegateway(router),incasetheserver-ipisonadifferentsubnet;andnetmaskdefinestheclassofIPaddressing.hostnameisastringthatispassedasthetargethostname;deviceistheLinuxdevicename,suchaseth0;andPROTOdefinestheprotocolusedtoobtaininitialIPparameters.



伪文件系统:

/proc,是通过mount-tproc/proc/proc命令执行的。/proc文件系统中以系统运行的进程pid号建立目录保存进程运行的状态。

/sysfs中是系统设备的信息,根据这些信息可以决定系统设备的特性以及指定系统策略如电源管理和热插拔的能力。



Ramfs,tmpfs:

RAM-based文件系统,两种虚拟文件系统,内容存在内核的虚拟内存中,在掉电或重启后内容丢失。mount-ttmpfs/tmpfs/tmp实现文件系统的挂载。Ramfs和在内核启动时使用的ramdisk的不同是ramfs可以按需缩减和扩展,而ramdisk则不可以。



构建文件系统:

Lookbackdevice是一种将常规文件用作块设备的设备。构建ext2文件系统的步骤:

ddif=/dev/zeroof=./my-new-fs-imagebs=1kcount=512

/sbin/mke2fs./my-new-fs-image

mount-oloop./my-new-fs-image/mnt/flash



Chapter10.MTDSubsystem



TheMTDlayerarchitectureenablestheseparationofthelow-leveldevicecomplexitiesfromthehigher-layerdataorganizationandstorageformatsthatusememorydevices.



Theaimofthesystemistomakeitsimpletoprovideadriverfornewhardware,byprovidingagenericinterfacebetweenthehardwaredriversandtheupperlayersofthesystem.



Hardwaredriversneedtoknownothingaboutthestorageformatsused,suchasFTL,FFS2,etc.,butwillonlyneedtoprovidesimpleroutinesforread,writeanderase.Presentationofthedevice''scontentstotheuserinanappropriateformwillbehandledbytheupperlayersofthesystem.



MTDLinuxhomepagewww.linux-mtd.infradead.org/



MTDRAM:

一种特殊的测试驱动,即使没有像Flashmemory的MTD设备,也可用它来测试MTD子系统,使用系统内存作为块设备来模拟MTD块设备。jffs2文件系统不能像ext2那样作为loopback设备直接挂载,但可以通过MTDRAM的方法使用它:

#modprobejffs2

#modprobemtdblock

#modprobemtdram

#ddif=jffs2.binof=/dev/mtdblock0

4690+1recordsin

4690+1recordsout

#mkdir/mnt/flash

#mount-tjffs2/dev/mtdblock0/mnt/flash

#ls-l/mnt/flash

与loopback设备不同的是,在jffs2文件系统中的修改如rm、cp在umount后改变都会丢失。如果想保存改变,则要执行#ddif=/dev/mtdblock0of=./your-modified-fs-image.bin



Chapter11.BusyBox



BusyBoxisasmallandefficientreplacementforalargecollectionofstandardLinuxcommandlineutilities.



基于busybox创建的root文件系统:

$tree

.

|--bin

||--busybox

||--cat->busybox

||--dmesg->busybox

||--echo->busybox

||--hostname->busybox

||--ls->busybox

||--ps->busybox

||--pwd->busybox

|''--sh->busybox

|--dev

|''--console

|--etc

''--proc

4directories,10files



Chapter12.EmbeddedDevelopmentEnvironment



交叉开发环境:

命令cpp–v可以得到交叉编译器的./configure时的配置信息,得到include的寻找目录等信息。



TFTP协议:

通过它来传送host的文件到target上,bootloader使用TFTP从host上下载kernel到target上。



DHCPorBOOTP:

theprotocolyourtargetandserverusetoaccomplishtheautomaticdetectionofnetworksettings.



Chapter13.DevelopmentTools



TracingandProfilingtools:

Strace查看app的系统调用的情况;

Ltrace查看app的库函数调用的情况;

Mtrace查看malloc,realloc的内存情况;



Binaryutilities:

Readelf,objdump,objcopy,strip,addr2line,strings,ldd,nm



Chapter14.KernelDebuggingTechniques



KGDB:

Itisaveryusefulkernel-levelgdbstubthatenablesdirectsymbolicsource-leveldebugginginsidetheLinuxkernelanddevicedrivers.Itusesthegdbremoteprotocoltocommunicatetoyourhost-basedcross-gdb.



在内核配置文件中要选定支持kgdb选项,并且在内核命令行参数中要指定gdb参数才可以对内核进行调试。也可要用来LKM的devicedriver。





JTAG:

Hardware-assisteddebuggingviaaJTAGprobeenablesdebuggingFlashorROMresidentcodewhereotherdebuggingmethodscanbecumbersomeorotherwiseimpossible.

通常所说的JTAG大致分两类,一类用于测试芯片的电气特性,检测芯片是否有问题;一类用于Debug;一般支持JTAG的CPU内都包含了这两个模块。

??????一个含有JTAGDebug接口模块的CPU,只要时钟正常,就可以通过JTAG接口访问CPU的内部寄存器和挂在CPU总线上的设备,如FLASH,RAM,SOC(比如4510B,44Box,AT91M系列)内置模块的寄存器,象UART,Timers,GPIO等等的寄存器。

Chapter15.DebuggingEmbeddedLinuxApplications



Gdbserver:

gdbserverrunsonthetargetsystemandactsasthegluebetweenthecross-gdbrunningonadevelopmenthostandtheprocessbeingdebuggedonthetarget.



GDB:

GDBcanbeusedtodebugmultipleindependentprocessesviamultipleconcurrentGDBsessions.

GDBcanbeconfiguredtofollowaforkedprocessonafork()systemcall.Itsdefaultmodeistocontinuetodebugtheparentthatis,thecalleroffork().

GDBhasfeaturestofacilitatedebuggingmultithreadedapplicationswrittentoPOSIXthreadAPIs.ThecurrentdefaultLinuxthreadlibraryistheNativePosixThreadsLibrary(NPTL).

GDBsupportsattachingtoanddetachingfromanalreadyrunningprocess.



Chapter16.PortingLinux



Chapter17.LinuxandRealTime



内核抢占:

当进程中有共享的临界区数据访问时,应该关闭内核抢占,访问处理后再开启内核抢占功能。



献花(0)
+1
(本文系liluvu首藏)