版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
第六章嵌入式Linux文件系统第六章嵌入式Linux文件系统(1)Linux文件系统与文件管理虚拟文件系统VFS/dentry目录项对象/inode索引节点对象(2)嵌入式文件系统嵌入式Linux文件系统概述/JFFS2嵌入式文件系统/根文件系统Linux文件管理在Linux中,有三种基本的文件类型。目录可以包含普通文件和特殊文件,目录相当于Windows和MacOS中的文件夹。目录普通文件是以字节为单位的数据流,包括文本文件、源码文件、可执行文件等。文本和二进制对Linux来说并无区别,对普通文件的解释由处理该文件的应用程序负责。普通文件Linux与外部设备(例如光驱,打印机,终端,modern等)是通过一种被称为设备文件的文件来进行通信。Linux与外部设备之间输入输出的关系和输入输出到一个文件的方式是相同的。Linux和一个外部设备通讯之前,这个设备必须首先要有一个设备文件存在。例如,每一个终端都有自己的设备文件来供Linux写数据(比如出现在终端屏幕上)和读取数据(比如用户通过键盘输入)。设备文件案例:文件的打开在这个例子中,open()系统调用用于在只写模式下打开文件testfile.txt,所有者和用户组(0644)具有读取权限。如果open()系统调用失败,程序打印错误信息并返回1。否则,程序通过write()系统调用写入字符串"Hello",然后使用close()系统调用关闭文件。文件系统是操作系统用于确认磁盘或分区上的文件的方法和数据结构。文件系统是负责存取和管理文件信息的机构,用于对数据、文件以及设备的存取控制,它提供对文件和目录的分层组织形式、数据缓冲以及对文件存取权限的控制功能。文件系统具有以下主要功能:1.对文件存储设备进行管理,分别记录空闲区和被占用区,以便于用户创建、修改以及删除文件时对空间的操作。2.对文件和目录的按名访问、分层组织功能。3.创建、删除及修改文件功能。4.数据保护功能。5.文件共享功能
Linux文件系统概述PartOne6.1
为了支持多种不同的文件系统,采用了虚拟文件系统VFS(VirtualFilesystem)技术。虚拟文件系统是对多种实际文件系统的共有功能的抽象,它屏蔽了各种不同文件系统在实现细节上的差异,为用户程序提供了统一的、抽象的、标准的接口以便对文件系统进行访问,如打开,读,写等操作。虚拟文件系统VFS确保了对所有文件的访问方式都是完全相同的。虚拟文件系统VFS虚拟文件系统VFS虚拟文件系统VFS确保了对所有文件的访问方式都是完全相同的。(1)Device
Drivers,设备驱动用于控制所有的外部设备及控制器。由于存在大量不能相互兼容的硬件设备(特别是嵌入式产品),所以也必须有众多的设备驱动与之匹配。值得注意的是,Linux内核中将近一半的源码都是设备驱动。
(2)DeviceIndependentInterface,该模块定义了描述硬件设备的统一方式(统一设备模型),所有的设备驱动都遵守这个规则,同时可以用一致的形式向上提供接口。这样做可以有效降低开发难度。(3)LogicalSystems逻辑文件系统,每一种文件系统都会对应一个逻辑文件系统,它会实现具体的文件系统逻辑。
(4)SystemIndependentInterface,该模块主要面向块设备和字符设备,负责以统一的接口表示硬件设备和逻辑文件系统,这样上层软件就不再关心具体的硬件形态了。
(5)SystemCallInterface,系统调用接口,向用户空间提供访问文件系统和硬件设备的统一的接口。
VFS是底层文件系统的主要组件(接口)。这个组件导出一组接口,然后将它们抽象到行为可能差异很大的各个文件系统。VFS具有两个针对文件系统对象的缓存:inode索引节点对象和dentry目录项对象,它们缓存最近使用过的文件系统对象。每个文件系统实现(如ext2、JFFS2等等)可以导出一组通用接口供VFS使用。缓冲区缓存会缓存文件系统和相关块设备之间的请求。dentry目录项对象dentry
结构表示一个打开的目录项,structdentry{...structdentry*d_parent;//父目录指针structqstrd_name;//目录名字
structinode*d_inode;//指向inode结构
...conststructdentry_operations*d_op;//操作方法集...};当我们打开文件
/usr/local/lib/libc.so
文件时,内核会为文件路径中的每个目录创建一个
dentry
结构。inode索引节点对象inode
结构表示一个真实的文件。structinode{...uid_ti_uid;//文件所属用户gid_ti_gid;//文件所属组...structtimespeci_atime;//最后访问时间
structtimespeci_mtime;//最后修改时间
structtimespeci_ctime;//文件创建时间...unsignedshorti_bytes;//文件大小...
conststructfile_operations*i_fop;//文件操作方法集(用于设置file结构)...};inode索引节点对象inode有两个重要的成员i_op(inode操作函数表)和i_fop(文件操作函数表)。
i_op主要负责处理与文件或目录本身相关的元数据操作和结构性操作,如:创建和创建文件、删除文件、查找文件、修改权限等。
i_fop的类型为structfile_operations结构,其定义如下:虚拟文件系统VFS综合看来,Linux虚拟文件系统采用了面向对象设计思想,文件系统中定义的VFS相当于面向对象系统中的抽象基类,从它出发可以派生出不同的子类,以支持多种具体文件系统,但从效率考虑内核纯粹使用C语言编程,故没有直接利用面向对象的语义。
Ext2文件系统格式PartTwo6.26.2.1Ext2文件系统TheSecondExtendedFileSystem(ext2)文件系统是Linux系统中的标准文件系统,主要包括普通文件、目录文件、特殊文件和符号链接文件。Ext2文件系统是通过对Minix的文件系统进行扩展而得到的,其存取文件的性能良好,可以管理特大磁盘分区,文件系统最大可达4TB。早期Linux都使用ext2文件系统。在ext2文件系统中,文件由包含有文件所有信息的节点inode进行唯一标识。Ext2文件系统采用三级间接块来存储数据块指针,并以块(默认为1KB)为单位分配空间。在ext2系统中,所有元数据结构的大小均基于“块”,而不是“扇区”。块的大小随文件系统的大小而有所不同。而一定数量的块又组成一个块组,每个块组的起始部分有多种描述该块组各种属性的元数据结构。每个块组依次包括超级块、块组描述符、块位图和节点inode位图、inode表及数据块区。1.超级块每个ext2文件系统都必须包含一个超级块,其中存储了该文件系统的大量基本信息,如块的大小、每块组中包含的块数等。同时系统会对超级块进行备份,备份被存放在块组的第一个块中。超级块的起始位置为其所在分区的第1024个字节,占用1KB的空间,主要作用:存储文件系统的全局信息和运行状态,减少磁盘I/O。提供文件系统操作方法(s_op文件系统函数表)。以s_root为根目录,建立和维护文件系统内部文件树。通过s_fs_info可以访问实际文件系统超级块。
2.块组描述符一个块组描述符用以描述一个块组的属性。块组描述符组由若干块组描述符组成,描述了文件系统中所有块组的属性,存放于超级块所在块的下一个块中。3.块位图和节点inode位图块位图和inode位图的每一位分别指出块组中对应的哪个块或inode是否被使用。:5.数据块数据块中存放文件的内容,包括目录表、扩展属性、符号链接等4.节点inode表节点inode表用于跟踪定位每个文件,包括位置、大小等,不包括文件名。一个块组只有一个节点inode表。6.2.2目录结构在ext2文件系统中,目录是作为文件存储的。根目录总是在inode表的第二项,而其子目录则在根目录文件的内容中定义。目录项在include/linux/ext2_fs.h文件中定义,其结构如下:structext2_dir_entry_2{ __le32 inode; /*Inodenumber*/ __le16 rec_len; /*Directoryentrylength*/ __u8 name_len; /*Namelength*/ __u8 file_type; char name[EXT2_NAME_LEN]; /*Filename*/};6.3.1EXT3文件系统EXT3是第三代扩展文件系统(Thirdextendedfilesystem),EXT3是在EXT2基础上增加日志形成的一个日志文件系统,常用于Linux操作系统。日志文件系统最大的特点是会将整个磁盘的写入动作完整记录在磁盘的某个区域上,以便有需要时可以回溯追踪。除开日志文件系统所具有的优点,Ext3的特点还主要有:(1)ext3文件系统在非正常关机状况下,系统无需检查文件系统,而且ext3的恢复时间也极短。(2)ext3文件系统能够极大地提高文件系统的完整性,避免了意外宕机对文件系统的破坏。(3)ext3文件系统可以不经任何更改,而直接加载成为ext2文件系统。由ext2文件系统转换成ext3文件系统也非常容易。(4)3种日志模式可选:日记、顺序、回写。可适应不同场合对日志模式的要求。(5)便于移植,无论是硬件体系或是内核修改,其移植工作均较容易。6.3.2EXT4文件系统第四代扩展文件系统EXT4(Fourthextendedfilesystem)是Linux系统下的日志文件系统,是ext3文件系统的后继版本。2008年12月25日,LinuxKernel2.6.28的正式版本发布。随着这一新内核的发布,Ext4文件系统也结束实验期,成为稳定版。Ext4文件系统的特点主要包括:1.Ext4的文件系统容量达到1EB,而文件容量则达到16TB;2.
Ext4理论上支持无限数量的子目录;3.Ext4文件系统具有64位空间记录块数量;4.Ext4在文件系统层面实现了持久预分配并提供相应的API,比应用软件自己实现更有效率;5.Ext4支持更大的i-节点和支持快速扩展属性和i-节点保留;6.Ext4给日志数据添加了校验功能,日志校验功能可以很方便地判断日志数据是否损坏;7.Ext4支持在线碎片整理,并将提供e4defrag工具进行个别文件或整个文件系统的碎片整理。嵌入式文件系统JFFS2PartFoue6.4嵌入式文件系统嵌入式文件系统是指嵌入式系统中实现文件存取、管理等功能的模块,这些模块提供一系列文件输入输出等文件管理功能,为嵌入式系统和设备提供文件系统支持。QNXVxWorksYaffs/yaffs2CramfsNFS主流的嵌入式操作系统的文件系统QNX提供多种资源管理器,包括各种文件系统和设备管理,支持多个文件系统同时运行;包括提供完全的POSIX以及UNIX语法的文件系统,支持多种闪存设备的嵌入式文件系统,支持对多种文件服务器WINDOWS、LANManager等的透明访问的SMB文件系统、FAT文件系统、CD一ROM文件系统等,并支持多种外部设备。QNXVxWorks的文件系统提供的组件一FFS“快速文件系统”非常适合于实时系统的应用。它包括几种支持使用块设备(如磁盘)的本地文件系统,这些设备都使用一个标准的接口从而使得文件系统能够被灵活的在设备驱动程序上移植。另外,也支持SCSI磁带设备的本地文件系统`。VXWORKS的I/O的体系结构甚至还支持一个单独的从系统上同时并存几个不同的文件系统,支持四种文件系统FAT、RT11FS、RAWFS、TAPES。VxWorksYaffs(YetAnotherFlashFileSystem)/yaffs2是专为嵌入式系统使用NAND型闪存而设计的日志型文件系统。速度快,挂载时间很短,对内存的占用较小。另外它还是跨平台的文件系统,除了Linux和eCos,还支持WinCE,pSOS和ThreadX等。Yaffs/yaffs2Yaffs/yaffs2自带NAND芯片的驱动,并且为嵌入式系统提供了直接访问文件系统的API,用户可以不使用Linux中的MTD与VFS,直接对文件系统操作。当然,yaffs也可与MTD驱动程序配合使用。yaffs与yaffs2的主要区别在于,前者仅支持小页(512Bytes)NAND闪存,后者则可支持大页(2KB)NAND闪存。同时,yaffs2在内存空间占用、垃圾回收速度、读/写速度等方面均有大幅提升。Yaffs/yaffs2Cramfs(CompressedROMFileSystem)是Linux的创始人LinusTorvalds参与开发的一种只读的压缩文件系统。在cramfs文件系统中,每一页(4KB)被单独压缩,可以随机页访问,其压缩比高达2:1,为嵌入式系统节省大量的Flash存储空间,使系统可通过更低容量的FLASH存储相同的文件,从而降低系统成本。Cramfs网络文件系统NFS(NetworkFileSystem)是由Sun开发并发展起来的一项在不同机器、不同操作系统之间通过网络共享文件的技术。在嵌入式Linux系统的开发调试阶段,可以利用该技术在主机上建立基于NFS的根文件系统,挂载到嵌入式设备,可以很方便地修改根文件系统的内容。NFS嵌入式Linux文件系统
扩展:ramfs文件系统ramfs是一个非常巧妙,利用VFS虚拟文件系统自身结构而形成的内存文件系统。ramfs没有自已的文件存储结构,它的文件存储于页缓存(pagecache)中,目录结构由dentry链表本身描述,文件则由虚拟文件系统VFS的inode结构本身描述。从ramfs的描述可以看出,虚拟文件系统VFS本质上可看成一种内存文件系统,它统一了文件在内核中的表示方式并对磁盘文件系统进行缓冲。ramfs文件系统ramfs是一种非常简单的文件系统,它直接利用linux内核已有的高速缓存机制,使用系统的物理内存,生成一个大小可以动态变化的的基于内存的文件系统。ramfs工作于虚拟文件系统层(VFS)层,不能被格式化。只有root用户才能进行ramfs写操作。通过查看Makefile文件可以检查ramfs依赖的模块。obj-y+=ramfs.ofile-mmu-y:=file-nommu.ofile-mmu-$(CONFIG_MMU):=file-mmu.oramfs-objs+=inode.o$(file-mmu-y)扩展:ramdisk文件系统ramdisk是一种将内存中的的一块区域作为物理磁盘进行使用的技术,也就是说,ramdisk是在内存区域中创建块设备用于存放文件系统的技术。对于用户而言,可以把ramdisk与通常的硬盘分区同等对待并使用。由于掉电后ramdisk的内容会消失,因而ramdisk不适合作为长期保存文件的介质。ramdisk文件系统为更好实现内核模块自动加载机制,基于ramdisk的initrd(BootLoaderinitializedRAMdisk)得以诞生。initrd是一个被压缩过的小型根目录,NorFlash通常容量较小,其主要特点是程序代码可以直接在Flash内运行。NorFlash具有RAM接口,易于访问,缺点是擦除电路复杂,写速度和擦除速度都比较慢,最大擦写次数约10万次,典型的块大小是128kB。NandFlash通常容量较大,具有很高的存储密度,从而降低了单位价格。NandFlash的块尺寸较小,典型大小为8kB,擦除速度快,使用寿命也更长,最大擦写次数可以达到100万次,但是其访问接口是复杂的I/O口,并且坏块和位反转现象较多,对驱动程序的要求较高。一般结论:由于NorFlash和NandFlash各具特色,因此它们的用途也各不相同,NorFlash一般用来存储体积较小的代码,而NandFlash则用来存放大体积的数据。NorFlash和NandFlash的对比JFFS2嵌入式文件系统
JFFS2文件系统层次操作实现垃圾收集平均磨损基本介绍数据压缩不足之处为了延长Flash的整体寿命需要均匀地使用各个块,这就需要磨损均衡的功能;为了提高Flash存储器的利用率,还应该有对存储空间的碎片收集功能;在嵌入式系统中,要考虑出现系统意外掉电的情况,所以文件系统还应该有掉电保护的功能,保证系统在出现意外掉电时也不会丢失数据。因此在Flash存储设备上,目前主要采用了专门针对Flash存储器的要求而设计的JFFS26.4.2JFFS2嵌入式文件系统1.JFFS2文件系统简介JFFS(JournalingFlashFileSystem)是瑞典的AxisCommunications公司专门针对嵌入式系统中的Flash存储器的特性而设计的一种日志文件系统。Redhat公司的DavidWoodhouse在JFFS的基础上进行了改进,从而发布了JFFS2(JournalingFlashFileSystemVersion2)。和JFFS相比,JFFS2支持更多节点类型,提高了磨损均衡和碎片收集的能力,增加了对硬链接的支持。JFFS2还增加了数据压缩功能,这更利于在容量较小的Flash中使用。和传统的Linux文件系统如ext2相比,JFFS2处理擦除和读写操作的效率更高,并且具有完善的掉电保护功能,使存储的数据更加安全。返回JFFS2在Flash上只存储两种类型的数据实体,分别为用于描述数据节点的jffs2_raw_inode和描述目录项jffs2_raw_dirent。
Jffs2_raw_dirent主要包括文件名、节点ino号、父节点ino号、版本号、校验码等信息,它用来形成整个文件系统的层次目录结构。
Jffs2_raw_inode主要包括文件ino号、版本号、访问权限、修改时间、本节点所包含的数据文件中的起始位置及本节点所包含的数据大小等信息,它用来管理文件的所有数据。一个目录文件由多个jffs2_raw_dirent组成。而普通文件,符号链接文件,设备文件,FIFO文件等都由一个或多个jffs2_raw_inode数据实体组成。返回返回structjffs2_inode_cache{structjffs2_scan_info*scan;
//在扫描链表的时候存放临时信息,在扫描结束以后设置成NULLstruct
jffs2_inode_cache*next;structjffs2_raw_node_ref*node;_u32ino;intnlink;};structjfffs2_raw_node_ref{
structjffs2_raw_node_ref*next_in_ino;
structjffs2_raw_node_refnext_phys;
_u32flash_offset;
_u32totlen;
};当进行写入操作时,在块还未被填满之前,仍然按顺序进行写操作,系统从free_list取得一个新块,而且从新块的开始部分不断地进行写操作,一旦free_list大小不够时,系统将会触发“碎片收集”功能回收废弃节点操作实现垃圾收集在JFFS中,文件系统与队列类似,每一个队列都存在唯一的头指针和尾指针。最先写入日志的节点作为头指针,而每次写入一个新节点时,这个节点作为日志的尾指针。每个节点存在一个与节点写入的顺序有关的version
节点,它专门用来存放节点的版本号。该节点每写入一个节点其版本号加1。节点写入总是从日志的尾部进行,而读/写点则没有任何限制。但是擦除和碎片收集操作总是在头部进行。当用户请求写操作时发现存储介质上没有足够的空余空间,也就表明空余空间已经符合“碎片收集”的启动条件。如果有垃圾空间能够被回收,碎片收集进程启动将收集垃圾空间中的垃圾块,否则,碎片收集就线程处于睡眠状态。返回平均磨损在JFFS中,碎片收集总是对文件系统队列头所指节点的块进行回收。如果该块填满了数据就将该数据后移,这样该块就成为空闲块。通过这种处理方式可以保证Flash中每块的擦除次数相同,从而提高了整个Flash芯片的使用寿命。返回数据压缩JFFS2提供了数据压缩技术,数据存入Flash之前,JFFS2会自动对其进行压缩。目前,内嵌JFFS2
的压缩算法很多,最常见的是zlib
算法,这种算法仅对ASCII
和二进制数据文件进行压缩。在嵌入式文件系统中引入数据压缩技术,使其数据能够得到最大限度的压缩,可以提高资源的利用率,有利于提高性能和节省开发成本。返回JFFS2的不足之处(1)挂载时间过长。JFFS2的挂载过程需要对闪存从头到尾的扫描,这个过程比较花费时间。
(2)磨损平衡具有较大随意性。JFFS2对磨损平衡是用概率的方法来解决的,这很难保证磨损平衡的确定性。在某些情况下,可能造成对擦写块不必要的擦写操作;在某些情况下,又会引起对磨损平衡调整的不及时。(3)扩展性很差。首先,闪存越大,闪存上节点数目越多挂载时间就越长。其次,虽然JFFS2尽可能的减少内存的占用,但实际上对内存的占用量是同i节点数和闪存上的节点数成正比的。返回根文件系统Linux根文件系统中一般有如下的几个目录:根文件系统是一种特殊的文件系统,该文件系统不仅具有普通文件系统的存储数据文件的功能,它还是内核启动时所挂载(mount)的第一个文件系统,内核代码的映像文件保存在根文件系统中,系统引导启动程序会在根文件系统挂载之后从中把一些初始化脚本和服务加载到内存中去运行。/bin目录01/sbin目录02/dev目录03/etc目录04/home目录06/lib目录05/root目录07/usr目录08/var目录09/proc目录/tmp目录/mnt目录101211根文件系统/bin目录该目录下的命令可以被root与一般账号所使用,由于这些命令在挂接其他文件系统之前就可以使用,所以/bin目录必须和根文件系统在同一个分区中。01/sbin目录该目录下存放系统命令,即只有系统管理员能够使用的命令,系统命令还可以存放在/usr/sbin,/usr/local/sbin目录下,/sbin目录中存放的是基本的系统命令,它们用于启动系统和修复系统等,/sbin目录必须和根文件系统在同一个分区中。/sbin目录下常用的命令有:shutdown、reboot、fdisk、fsck、init等,本地用户自己安装的系统命令放在/usr/local/sbin目录下。02/dev目录该目录下存放的是设备与设备接口的文件,设备文件是Linux中特有的文件类型,在Linux系统下,以文件的方式访问各种设备,即通过读/写某个设备文件操作某个具体硬件。比如通过"dev/ttySAC0"文件可以操作串口0,通过"/dev/mtdblock1"可以访问MTD设备的第2个分区。比较重要的文件有/dev/null,/dev/zero,/dev/tty,/dev/lp*等。03根文件系统/etc目录该目录下存放着系统主要的配置文件,例如人员的账号密码文件、各种服务的其实文件等。在嵌入式系统中,这些内容可以大为精减。04/lib目录该目录下存放共享库和可加载驱动程序,共享库用于启动系统。05/home目录系统默认的用户文件夹,它是可选的,对于每个普通用户,在/home目录下都有一个以用户名命名的子目录,里面存放用户相关的配置文件。06/root目录系统管理员(root)的主文件夹,即是根用户的目录,与此对应,普通用户的目录是/home下的某个子目录。07根文件系统/usr目录存放的是共享、只读的程序和数据,这表明/usr目录下的内容可以在多个主机间共享,这些主要也符合文件系统层次标准FHS标准的。/usr目录在嵌入式中可以精减。08/var目录与/usr目录相反,/var目录中存放可变的数据,比如spool目录(mail,news),log文件,临时文件。09/proc目录这是一个空目录,常作为proc文件系统的挂接点,proc文件系统是个虚拟的文件系统,它没有实际的存储设备,里面的目录,文件都是由内核临时生成的,用来表示系统的运行状态,也可以操作其中的文件控制系统。10/mnt目录用于临时挂载某个文件系统的挂接点,通常是空目录,也可以在里面创建一引起空的子目录,比如/mnt/cdram/mnt/hda1。用来临时挂载光盘、移动存储设备等。11/tmp目录用于存放临时文件,通常是空目录,一些需要生成临时文件用到的/tmp目录下,所以/tmp目录必须存在并可以访问。12真实根文件系统挂载流程(扩展:6.10版本内核)根目录小结对于嵌入式Linux系统的根文件系统来说,一般可能没有上面所列出的那么复杂,比如嵌入式系统通常都不是针对多用户的,所以/home这个目录在一般嵌入式Linux中可能就很少用到。一般说来,只有/bin,/dev,/etc,/lib,/proc,/var,/usr这些需要的,而其他都是可选的。Busybox#tar-xjvfbusybox-1.24.1.tar.bz2#cdbusybox-1.24.1#makemenuconfig#make#makeinstall本章小结文件系统是操作系统的重要组成部分,Linux采用VFS虚拟文件系统技术支持多种类型的文件系统。Linux虚拟文件系统采用了面向对象设计思想,VFS相当于面向对象系统中的抽象基类,从它出发可以派生出不同的子类,以支持多种具体文件系统。嵌入式操作系统由于自身系统的特点,对文件系统提出了不同的要求。第七章嵌入式Linux系统移植本章含有多个微课视频,涉及编译器实战,调试器实战,扩展等内容,请择机观看目录7.1BootLoader基本概念与典型结构7.2U-Boot7.3交叉开发环境的建立7.4交叉编译工具链7.5嵌入式Linux系统移植过程7.6Gdb调试器7.7远程调试7.8内核调试第七章嵌入式Linux系统移植(1)BootLoader基本概念与操作模式/常见的BootLoader/U-Boot/U-Boot针对RISC-V(扩展)/U-Boot针对设备树(扩展)(2)交叉开发环境交叉开发环境的建立/交叉编译工具链/clang与LLVM(扩展)(3)嵌入式Linux系统移植U-Boot的移植/内核配置、编译和移植(4)调试Gdb本地调试/远程调试/GDBSERVER实战案例BootLoader基本概念
一个嵌入式Linux系统通常可以分为以下几个部分:(1)引导加载程序及其环境参数。这里通常是指BootLoader以及相关环境参数。(2)Linux内核。基于特定嵌入式开发板的定制内核以及内核的相关启动参数。(3)文件系统。主要包括根文件系统和一般建立于Flash内存设备之上文件系统。(4)用户应用程序。基于用户的应用程序。有时在用户应用程序和内核层之间可能还会包括一个嵌入式图形用户界面程序(GUI)。常见的嵌入式GUI有QT和MiniGUI等。在嵌入式操作系统中,BootLoader是在操作系统内核运行之前运行的一小段程序,可以初始化硬件设备、建立内存空间映射图,从而将系统的软硬件环境带到一个适合的状态,以便为最终调用操作系统内核准备好正确的环境。在嵌入式系统中,通常并没有像通用计算机中BIOS那样的固件程序,因此整个系统的加载启动任务就完全由BootLoader来完成。BootLoader是嵌入式系统在加电后执行的第一段代码,在它完成CPU和相关硬件的初始化之后,再将操作系统映像或固化的嵌入式应用程序装载到内存中然后跳转到操作系统所在的空间,启动操作系统运行。对于嵌入式系统而言,BootLoader是基于特定硬件平台来实现的。因此,几乎不可能为所有的嵌入式系统建立一个通用的BootLoader,不同的处理器架构都有不同的BootLoader。BootLoader不仅依赖于CPU的体系结构,而且依赖于嵌入式系统板级设备的相关配置。7.1.2BootLoader的操作模式大多数BootLoader都包含两种不同的操作模式:自启动模式和交互模式。这种划分仅仅对于开发人员才有意义。(1)自启动模式自启动模式也叫启动加载模式。在这种模式下,BootLoader自动从目标机上的某个固态存储设备上将操作系统加载到RAM中运行,整个过程并没有用户的介入。这种模式是BootLoader的正常工作模式(2)交互模式交互模式也叫下载模式。在这种模式下,目标机上的BootLoader将通过串口或网络等通信手段从开发主机上下载内核映像、根文件系统到RAM中。然后再被BootLoader写到目标机上的固态存储媒质(如FLASH)中,或者直接进入系统的引导。交互模式也可以通过接口(如串口)接收用户的命令。这种模式在初次固化内核、根文件系统时或者更新内核及根文件系统时都会用到。7.1.3BootLoader的典型结构BootLoader启动大多数都分为两个阶段。第一阶段主要包含依赖于CPU的体系结构硬件初始化的代码,通常都用汇编语言来实现。这个阶段的任务有:基本的硬件设备初始化(屏蔽所有的中断、关闭处理器内部指令/数据Cache等)。为第二阶段准备RAM空间。如果是从某个固态存储媒质中,则复制BootLoader的第二阶段代码到RAM。设置堆栈。跳转到第二阶段的C程序入口点。第二阶段通常用C语言完成,以便实现更复杂的功能,也使程序有更好的可读性和可移植性。这个阶段的任务有:初始化本阶段要使用到的硬件设备。检测系统内存映射。将内核映像和根文件系统映像(如果有设备树则也需要)从Flash读到RAM。为内核设置启动参数。调用内核。Exynos4412的启动流程Exynos4412微处理器的启动过程由BL0、BL1和BL2(BL为BootLoader的简称,在本书后续章节中将有详细介绍)3部分代码实现,其中BL0在出厂时已经被固化到64KB的iROM区中。(1)执行内部只读存储器iROM中的启动代码BL0(厂家固化在里面的),这段代码主要是初始化一些系统的基本配置,对应图4-2中的标志①。该段代码主要的功能有:关看门狗时钟。初始化指令cache。初始化栈、堆。初始化块设备复制函数。初始化PLL及设置系统时钟。Exynos4412的启动流程Exynos4412微处理器的启动过程由BL0、BL1和BL2(BL为BootLoader的简称,在本书后续章节中将有详细介绍)3部分代码实现,其中BL0在出厂时已经被固化到64KB的iROM区中。(2)根据OM引脚设置,从相应启动设备复制BL1到片内256KB的SRAM中(iRAM区),并检查BL1的完整性校验信息,如果检查失败,iROM将自动偿试从其它启动设备启动,如SD/MMC等。BL1的代码量一般不大,因而一般情况下BL1负责完成的工作较少,主要是进一步完善系统时钟的初始化工作、动态内存DRAM控制器的配置、通信接口的初始化等。根据安全启动秘钥值,BL1还将对操作系统镜像进行完整性校验。该过程对应图4-2中的标志②。(3)完成内动态内存DRAM控制器的初始化后,把操作系统镜像从启动设备加载到DRAM中,该过程对应图4-2中的标志③。(4)跳转到操作系统中运行。扩展:操作系统启动之前:RISC-V引导程序扩展:OpenSBI用例OpenSBI作为固件的常见用例方法:FW_PAYLOAD:带有下一个引导阶段作为有效载荷的固件。这种类型的固件直接包含了下一引导阶段的二进制代码,即payload,通常是bootloader或操作系统内核。FW_JUMP:带有静态跳转地址到下一个引导阶段的固件。FW_DYNAMIC:具有下一启动阶段动态信息的固件。常见的BootLoader
(1)RedbootRedboot(RedHatEmbeddedDebugandBootstrap)是RedHat公司开发的一个独立运行在嵌入式系统上的BootLoader程序,是目前比较流行的一个功能、可移植性好的BootLoader。Redboot是一个采用eCos开发环境开发的应用程序,并采用了eCos的硬件抽象层作为基础,但它完全可以摆脱eCos环境运行,可以用来引导任何其他的嵌入式操作系统,如Linux、WindowsCE等。Redboot支持的处理器构架有ARM,MIPS,MN10300,PowerPC,RenesasSHx,v850,x86等,是一个完善的嵌入式系统BootLoader。(2)U-BootU-Boot(UniversalBootLoader)于2002年12月17日发布第一个版本U-Boot-0.2.0。U-Boot自发布以后已更新多次,其支持具有持续性。U-Boot是在GPL下资源代码最完整的一个通用BootLoader。(3)BlobBlob(BootLoaderObject)是由Jan-DerkBakker和ErikMouw发布的,是专门为StrongARM构架下的LART设计的BootLoader。Blob的最后版本是blob-2.0.5。Blob功能比较齐全,代码较少,比较适合做修改移植,用来引导Liunx,目前大部分S3C44B0板都用Blob修改移植后加载uClinux。(4)vivivivi是韩国mizi公司开发的BootLoader,适用于ARM9处理器,现在已经停止开发了。它是三星官方板SMDK2410采用的BootLoader。Vivi最主要的特点就是代码小巧,有利于移植新的处理器。同时vivi的软件架构和配置方法类似Linux风格,对于有过编译Linux内核经验的用户,vivi更容易上手。
U-BootPartTwo7.27.2.1U-Boot概述U-Boot,全称UniversalBootLoader,是遵循GPL条款的开放源码项目。从FADSROM、8xxROM、PPCBOOT逐步发展演化而来。其源码目录、编译形式与Linux内核很相似,事实上,不少U-Boot源码就是根据相应的Linux内核源程序进行简化而形成的,尤其是一些设备的驱动程序。
U-Boot支持多种嵌入式操作系统,主要有OpenBSD,NetBSD,FreeBSD,4.4BSD,Linux,SVR4,Esix,Solaris,Irix,SCO,Dell,NCR,VxWorks,LynxOS,pSOS,QNX,RTEMS,ARTOS,android等。同时,U-Boot除了支持PowerPC系列的处理器外,还能支持MIPS、x86、ARM、NIOS、XScale等诸多常用系列的处理器。U-Boot的主要特点有:源码开放,目前有些版本的未开源。支持多种嵌入式操作系统内核和处理器架构。可靠性和稳定性均较好。功能设置高度灵活,适合调试、产品发布等;设备驱动源码十分丰富,支持绝大多数常见硬件外设;并将对于与硬件平台相关的代码定义成宏并保留在配置文件中,开发者往往只需要修改这些宏的值就能成功使用这些硬件资源,简化了移植工作。U-Boot源码开放,目前有些版本的未开源。支持多种嵌入式操作系统内核和处理器架构。可靠性和稳定性均较好。功能设置高度灵活,适合调试、产品发布等;设备驱动源码十分丰富,支持绝大多数常见硬件外设;并将对于与硬件平台相关的代码定义成宏并保留在配置文件中,开发者往往只需要修改这些宏的值就能成功使用这些硬件资源,简化了移植工作。U-Boot的主要特点U-BOOT源码分析及编译
参考板的编译makeARCH=armCROSS_COMPILE=arm-linux-distcleanmakeARCH=armCORSS_COMPILE=arm-linux-s5pc210_universal_defconfigmakeV=1ARCH=armCROSS_COMPILE=arm-linux--j1请参考本案例微课U-Boot启动的一般流程
U-Boot启动第一阶段的主要工作U-BootSPL(
SecondaryProgramLoader,第二阶段程序加载器)对于一些SOC来说,它的内部SRAM可能会比较小,小到无法装载下一个完整的U-Boot镜像,因此就需要U-BootSPL,它主要负责初始化外部RAM和环境,并加载固件程序和真正的U-Boot镜像到RAM中执行。为了统一U-BootSPL的所有实现方式并允许简单地添加新的实现方法,U-Boot创建了通用的SPL框架。有了这个框架,几乎所有的电路板源文件都可以重复使用,不再需要代码重复或符号链接。ifeq($(CONFIG_SPL_BUILD),y)obj-y+=board_spl.oelseobj-y+=board.oendifobj-$(CONFIG_SPL_BUILD)+=foo.o#ifdefCONFIG_SPL_BUILDfoo();#endifSPL的目标文件是单独构建的,并放置在“spl”目录中。最终生成的二进制文件是u-boot-spl、u-boot-spl.bin和u-boot-spl.map。Kconfig为SPL启用了名为CONFIG_SPL_BUILD的配置选项。因此可以使用不同的设置为SPL编译源文件。可以通过Kconfig中的CONFIG_SPL选项启用SPL映像的构建。U-BootSPL(
SecondaryProgramLoader,第二阶段程序加载器)在Exynos4412芯片上电启动时首先启动iROM里面的程序,iROM里面的程序会复制BL1到iRAM里面去执行,接着BL1会继续复制BL2到iRAM中去运行。Samsung公司已经提供了BL1二进制文件,大小为8K。BL2就是引导加载程序U-boot的二进制文件,其大小被限制在了16K,但是正常编译出来的u-boot.bin已经远远大于16K了。因此,我们要使用U-boot提供的SPL(SecondaryProgramLoader)功能来解决这个问题。SPL是U-boot中独立的一个代码分支,复用了U-boot的代码,由CONFIG_SPL_BUILD配置项控制,它把U-boot的执行分为了2个阶段。SPL是U-boot第一阶段执行的代码,完成芯片级、板级的一些初始化操作,最主要的是初始化时钟和片外内存、加载U-boot第二阶段的代码并跳转到内存中去执行这部分代码。因此,在移植引导加载程序U-boot到Exynos4412目标板时,要使能U-boot的SPL功能。U-Boot启动的一般流程:第二阶段第二阶段初始化(也叫板级初始化)代码的入口就是_main函数,该函数定义在U-boot源代码u-boot/arch/arm/lib/crt0.S文件中。_main函数完成的主要工作包括:(1)设置C代码的运行环境,为接下来调用board_init_f函数做准备。设置堆栈,为执行C语言代码做好准备。如果使用了U-boot的SPL(SecondaryProgramLoader)功能(由CONFIG_SPL_BUILD宏定义),则可以由CONFIG_SPL_STACK宏定义堆栈基址;否则使用CONFIG_SYS_INIT_SP_ADDR宏定义堆栈基址。接着调用board_init_f_alloc_reserve函数,为U-boot的全局变量GD(globaldata)数据结构分配内存空间;再调用board_init_f_init_reserve函数,对全局变量GD进行初始化。U-Boot启动的一般流程:第二阶段(1)board_init_f()(2)board_init_r()U-Boot启动的一般流程:第二阶段(2)如果当前运行的是SPL模式,则进入_main函数就直接返回没有执行初始化的函数。而正常的U-boot模式会继续执行board_init_f函数,在board_init_f函数中调用initcall_run_list函数依次执行init_sequence_f函数数组里面的函数,例如U-boot驱动模型初始化、环境变量的初始化、串口的初始化、内存的初始化、U-bootrelocation操作前的环境初始化等。(3)执行U-bootrelocation操作,把内存中的u-boot进行重定位;清除BBS段。(4)调用board_init_r函数,在board_init_r函数中调用initcall_run_list函数,执行init_sequence_r函数数组里面的函数,完成后续的板级初始化操作。最后U-boot运行到了run_main_loop函数,并且在run_main_loop函数进入命令行状态,等待终端输入命令以及对命令进行处理。
7.2.3U-Boot环境变量U-Boot的环境变量是使用U-Boot的关键,它可以由用户定义并遵守约定俗成的一些用法,也有部分是U-Boot定义并不得更改。值得注意的是在未初始化的开发板中并不存在环境变量。U-Boot在缺省的情况下会存在一些基本的环境变量,当用户执行了saveenv命令之后,环境变量会第一次保存到flash中,之后用户对环境变量的修改和保存都是基于保存在flash中的环境变量的操作。环境变量名称相关描述bootdelay
执行自动启动的等候秒数baudrate
串口控制台的波特率netmask
以太网接口的掩码ethaddr
以太网卡的网卡物理地址bootfile
缺省的下载文件bootargs
传递给内核的启动参数bootcmd
自动启动时执行的命令serverip
服务器端的ip地址ipaddr
本地ip地址stdin
标准输入设备stdout
标准输出设备stderr
标准出错设备表7-3U-Boot常用环境变量U-Boot的环境变量中最重要的两个变量是:
bootcmd和bootargs。Bootcmd是自动启动时默认执行的一些命令,因此用户可以在当前环境中定义各种不同配置,不同环境的参数设置,然后通过bootcmd配置好参数。
Bootargs是环境变量中的重中之重.7.2.4
U-Boot命令U-Boot上电启动后,按任意键退出自启动状态,进入命令行状态。工作在启动加载模式时,BootLoader会自动执行bootcmd命令,比如这行代码。bootcmd=“nandread0x1000000x800000000x300000;bootm0x80000000”U-Boot首先把内核镜像拷贝到内存地址为0x80000000的位置,然后执行bootm0x80000000命令。bootm命令实际上调用的是do_bootm_linux函数。intdo_bootm_linux(intflag,intargc,char*constargv[], bootm_headers_t*images){ /*NoneedforthoseonRISC-V*/ if(flag&BOOTM_STATE_OS_BD_T||flag&BOOTM_STATE_OS_CMDLINE) return-1; if(flag&BOOTM_STATE_OS_PREP){ boot_prep_linux(images); return0; } if(flag&(BOOTM_STATE_OS_GO|BOOTM_STATE_OS_FAKE_GO)){ boot_jump_linux(images,flag); return0; } boot_prep_linux(images); boot_jump_linux(images,flag); return0;}在do_bootm_linux函数中,会定义一个函数指针Kernel,它指向内核的入口地址。在启动阶段之间,函数指针Kernel中hartid通过a0寄存器传递,设备树的起始地址通过a1寄存器传递。config_distro_bootcmd.h文件定义了bootcmd和许多辅助命令变量,这些变量自动搜索连接的磁盘以查找引导配置文件并执行它们。开发板必须提供配置<config_distro_bootcmd.h>以便它支持正确的引导设备类型集。要提供此配置,只需在包含<config_distro_bootcmd.h>之前定义宏BOOT_TARGET_DEVICES。例如:#ifndefCONFIG_SPL_BUILD#defineBOOT_TARGET_DEVICES(func)\func(MMC,mmc,1)\func(MMC,mmc,0)\func(USB,usb,0)\func(PXE,pxe,na)\func(DHCP,dhcp,na)#include<config_distro_bootcmd.h>#endif该宏中的每个条目都定义了一个单一的启动设备(例如特定的eMMC设备或SD卡)或启动设备的类型(例如USB、磁盘)
。
U-Boot对设备树的支持(扩展)在U-Boot源码的arch/<arch>/dts目录中包含一个Makefile文件,用于构建设备树blob(devicetreeblob,dtb)文件并将其嵌入到U-Boot映像中。这是一个十分有用的规则文件。如果开发者需要针对许多具有不同外设的类似开发板展开工作,开发者可以在设备树文件中描述每个板的特性,并且具有一个通用的源代码库。此功能的开启,只需要将CONFIG_OF_CONTROL添加到的开发板配置文件中。除了描述板上的硬件之外,U-Boot还使用设备树用于各种配置目的。例如,用于验证启动的公钥以特定格式嵌入到/signature节点中。实际上U-Boot使用设备树进行配置的内容众多,这包括开发板使用的设备、使用binman创建的图像格式、用于控制台的UART、用于安全启动的公钥以及许多其他内容。RISC-V架构的U-Boot引导过程(扩展)M模式U-Boot引导过程
S模式U-Boot引导过程当在M模式U-Boot中运行时,它会加载包含固件和S模式操作系统的payload镜像(例如fw_payload),在这种情况下,开发者可以使用mkimage将payload镜像打包成uImage格式,并使用bootm命令启动它。RISC-V生成启动映像可能包含用于特定平台初始化的U-BootSPL(SecondaryProgramLoader,第二阶段程序加载器,也叫辅助程序加载器)。U-BootSPL然后加载一个FIT映像(u-boot.itb),该镜像包含提供SBI的固件(例如fw_dynamic),以及在S模式下运行的常规U-Boot(或U-Boot本身).最后,加载S模式操作系统。7.3交叉开发环境的建立PartThree7.3交叉开发环境的建立主机-目标机交叉开发环境模式是由开发主机和目标机两套计算机系统内组成的。开发主机一般指通用计算机,如PC等,目标机指嵌入式开发板(系统)。通过交叉开发环境,在主机上使用开发工具(如各种SDK),针对目标机设计应用系统进行设计工作,然后下载到目标机上运行。交叉开发模式一般采用以下3个步骤:(1)在主机上编译BootLoader(引导加载程序),然后通过JTAG接口烧写到目标板。(2)在主机上编译Linux内核,然后通过BootLoader下载到目标板以启动或烧写到Flash。(3)在主机上编译各类应用程序,通过NFS运行、调试这些程序,验证无误后再将制作好的文件系统映像烧写到目标板7.3.1.主机与目标机的连接方式主机与目标机的连接方式主要有串口、以太网接口、USB接口、JTAG接口等方式连接。主机可以使用minicom、kermit或者Windows超级终端等工具,通过串口发送文件。目标机亦可以把程序运行结果通过串口返回并显示。以太网接口方式使用简单,配置灵活,支持广泛,传输速率快,缺点是网络驱动的实现比较复杂。JTAG(JointTestActionGroup,联合测试行动小组)是一种国际标准测试协议(IEEE1149.1标准),主要是用于对目标机系统中的各芯片的简单调试,和对BootLoader的下载两个功能。JTAG连接器中,其芯片内部封装了专门的测试电路TAP(TestAccessPort,测试访问口),通过专用的JTAG测试工具对内部节点进行测试。因而该方式是开发调试嵌入式系统的一种简洁高效的手段。JTAG有两种标准,14针接口和20针接口。虽然JTAG调试不占用系统资源,能够调试没有外部总线的芯片,代价也非常小,但是JTAG只能提供一种静态的调试方式,不能提供处理器实时运行时的信息。它是通过串行方式依次传递数据的,所以传送信息速度比较慢。7.3.2.主机-目标机的文件传输方式主机-目标机的文件传输方式主要有串口传输方式、网络传输方式、USB接口传输方式、JTAG接口传输方式、移动存储设备方式。串口传输协议常见的有kermit、Xmodem、Ymoderm、Zmoderm等。串口驱动程序的实现相对简单,但是速度慢,不适合较大文件的传输。USB接口方式通常将主机设为主设备端,目标机设为从设备端。与其他通信接口相比,USB接口方式速度快,配置灵活,易于使用。如果目标机上有移动存储介质如U盘等,可以制作启动盘或者复制到目标机上,从而引导启动。网络传输方式一般采用TFTP(trivialfiletransportprotocol)协议。TFTP是一个传输文件的简单协议,是TCP/IP协议族中的一个用来在客户机与服务器之间进行简单文件传输的协议,提供不复杂、开销不大的文件传输服务。端口号为69。此协议只能从文件服务器上获得或写入文件,不能列出目录,不进行认证,它传输8位数据。传输中有三种模式:netascii,这是8位的ASCII码形式;另一种是octet,这是8位源数据类型;最后一种mail已经不再支持,它将返回的数据直接返回给用户而不是保存为文件。7.3.3.文件系统的挂接-配置网络文件系统NFSNFS(NetworkFileSystem)即网络文件系统,是FreeBSD支持的文件系统中的一种,它允许网络中的计算机之间通过TCP/IP网络共享资源。在NFS的应用中,本地NFS的客户端应用可以透明地读写位于远端NFS服务器上的文件,就像访问本地文件一样。NFS的优点主要有:(1)节省本地存储空间,将常用的数据存放在一台NFS服务器上且可以通过网络访问,那么本地终端将可以减少自身存储空间的使用。(2)用户不需要在网络中的每个机器上都建有Home目录,Home目录可以放在NFS服务器上且可以在网络上被访问使用。(3)一些存储设备如软驱、CDROM和Zip等都可以在网络上被别的机器使用。这可以减少整个网络上可移动介质设备的数量。交叉编译工具链
交叉开发工具链就是为了编译、链接、处理和调试跨平台体系结构的程序代码。从工具链的组成上来说,它一般由多个程序构成,glibc、gcc、binutils和gdb四个软件提供分别对应着各个功能。常见的交叉编译例子如下:(1)在WindowsPC上,利用诸如类似ADS、RVDS等软件,使用armcc编译器,则可编译出针对ARMCPU的可执行代码。(2)在LinuxPC上,利用arm-linux-gcc编译器,可编译出针对LinuxARM平台的可执行代码。(3)在WindowsPC上,利用cygwin环境,运行arm-elf-gcc编译器,可编译出针对ARMCPU的可执行代码。7.4.2工具链的构建方法通常构建交叉工具链有如下三种方法。方法一:分步编译和安装交叉编译工具链所需要的库和源代码,最终生成交叉编译工具链。该方法相对比较困难,适合想深入学习构建交叉工具链的读者及用户。如果只是想使用交叉工具链,建议使用下列的方法二构建交叉工具链。方法二:通过Crosstool脚本工具来实现一次编译,生成交叉编译工具链,该方法相对于方法一要简单许多,并且出错的机会也非常少,建议大多数情况下使用该方法构建交叉编译工具链。方法三:直接通过网上下载已经制作好的交叉编译工具链。该方法的优点是简单可靠,缺点也比较明显,扩展性不足,对特定目标没有针对性,而且也存在许多未知错误的可能,建议读者慎用此方法。
GCC对于GUN编译器来说,GCC的编译要经历四个相互关联的步骤∶预处理(也称预编译,Preprocessing)、编译(Compilation)、汇编(Assembly)和链接(Linking)。file.cc程序源文件file.ic程序预处理后文件file.cxxc++程序源文件,也可以是file.cc/file.cpp/file.c++file.iic++程序预处理后文件file.hc/c++头文件file.s汇编程序文件file.o目标代码文件Binutils与glibcBinutilsBinutils提供了一系列用来创建、管理和维护二进制目标文件的工具程序,如汇编(as)、连接(ld)、静态库归档(ar)、反汇编(objdump)、elf结构分析工具(readelf)、无效调试信息和符号的工具(strip)等。通常binutils与gcc是紧密相集成的,没有binutils的话,gcc是不能正常工作的。
glibcGlibc是gnu发布的libc库,也即c运行库。Glibc是linux系统中最底层的应用程序开发接口,几乎其它所有的运行库都倚赖于glibc。Glibc除了封装linux操作系统所提供的系统服务外,它本身也提供了许多其它一些必要功能服务的实现,比如open,malloc,printf等等。Glibc是GNU工具链的关键组件,用于和二进制工具和编译器一起使用,为目标架构生成用户空间应用程序。ELF(可执行和可链接格式,ExecutableLinkableFormat)ELF(ExecutableLinkableFormat)是一种Unix-like系统上的二进制文件格式标准。ELF文件格式对于底层的操作系统开发非常重要,当程序需要在底层进行优化,调试,排错等操作时,ELF文件可以更好地帮助程序员完成任务。ELF标准中定义的采用ELF格式的文件分为以下4类:ELF(可执行和可链接格式,ExecutableLinkableFormat)ELF格式由几个节组成,包括头、程序头表、节头表和节本身。以下是每个节的简要概述:1.头(ELFHeader):ELF头包含文件的基本信息,包括文件类型、目标体系结构、入口点和其他元数据。2.程序头表(ProgramHeaderTable):这一节描述了程序执行时将加载到内存中的文件段。程序头表中的每个条目都描述了应该加载到内存中的文件的一个连续区域,以及有关该段的内存保护、对齐和其他属性信息。3.节头表(SectionHeaderTable):此部分包含有关文件中其他节的元数据,例如它们的大小、地址和类型。节头表中的每个条目描述文件中的一个节。4.节:可执行文件的大部分由包含程序代码、数据和其他资源的各种节组成。ELF文件中的一些常见节包括文本节(包含程序的可执行代码)、数据节(包含全局和静态数据)和符号表(将程序中使用的符号映射到它们的内存中地址)。ELF(可执行和可链接格式,ExecutableLinkableFormat)ELF文件处理的相关工具GNU为程序员提供了相关的处理工具软件,存放在Binutils工具包中。该工具包中的小程序如下:ar:归档文件,将多个文件打包成一个大文件。as:被gcc调用,输入汇编文件,输出目标文件供链接器ld连接。ld:GNU链接器。被gcc调用,它把目标文件和各种库文件结合在一起,重定位数据,并链接符号引用。objcopy:执行文件格式转换。objdump:显示ELF文件的信息。readelf:显示更多ELF格式文件的信息(包括DWARF调试信息)。
make与MakefileGNUmake是一个命令工具,是一个用来控制软件构建过程的自动化管理工具。Make工具通过称为Makefile的文件来完成并自动维护编译工作,由Richard
Stallman与Roland
McGrath设计开发。Makefile是用于自动编译和链接的,一个工程有很多文件组成,每一个文件的改变都会导致工程的重新链接,但是不是所有的文件都需要重新编译,Makefile中记录有文件的信
息,在make时会决定在链接的时候需要重新编译哪些文件。make命令格式:make[-fMakefile][option][target]#maketarget#make#makeclean(伪目标)GNUmake是一种常用的编译工具,通过它,开发人员可以很方便地管理软件编译的内容、方式和时机,从而能够把主要精力集中在代码的编写上。Gnumake的主要工作是读取一个文
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 商洛市2026届高三第四次模拟考试生物试卷含解析
- 环保小卫士:我们一起行动小学主题班会课件
- 消除安全隐患护航健康成长小学主题班会课件
- 热爱劳动勤动手从小做起树新风小学主题班会课件
- 感恩父母报恩情,小学主题班会课件
- 传承红色基因弘扬中华文化-小学主题班会课件
- 关于邀请参加年度大会的通知函(4篇)范文
- 传承中华美德塑造美好品格小学主题班会课件
- 警惕陌生人员接触远离潜在人身安全一年级主题班会课件
- 抵制交通违规筑牢安全意识小学主题班会课件
- 《宁静住宅评价标准》
- 2005-2016年考研英语(一)真题
- 一元一次方程和分式方程复习教案 人教版
- 2023-2024学年北京市海淀区高二(下)期末语文试题
- 《电力建设工程起重施工技术规范》
- TDTG5024斗式提升机机座及总体部分设计
- 一例严重多发伤大出血病例分享课件
- 中粮集团产品开发流程培训课件
- 挂靠合同:公会挂靠-(范本)
- 义务教育(数学)课程标准(2022版)(含2022年新增和修订部分)
- 青岛中瑞泰丰新材料有限公司2万吨无机环保新材料来料加工项目 环境影响报告书
评论
0/150
提交评论