1.鸿蒙轻内核M核源码分析:LibC实现之Musl LibC
2.Linux/mntç®å½ä¸»è¦ç¨äºä»ä¹ï¼
3.linux启动时挂载rootfs
4.Linux内核源码解析---mount挂载原理
5.Ext4文件系统挂载默认选项
6.深入剖析Linux文件系统之文件系统挂载(一)(超详细~)
鸿蒙轻内核M核源码分析:LibC实现之Musl LibC
本文探讨了LiteOS-M内核中Musl LibC的核源实现,重点关注文件系统与内存管理功能。原理Musl LibC在内核中提供了两种LibC实现选项,核源使用者可根据需求选择musl libC或newlibc。原理本文以musl libC为例,核源深度解析其文件系统与内存分配释放机制。原理gdb调试android源码
在使用musl libC并启用POSIX FS API时,核源开发者可使用文件kal\libc\musl\fs.c中定义的原理文件系统操作接口。这些接口遵循标准的核源POSIX规范,具体用法可参阅相关文档,原理或通过网络资源查询。核源例如,原理mount()函数用于挂载文件系统,核源而umount()和umount2()用于卸载文件系统,原理后者还支持额外的核源卸载选项。open()、close()、unlink()等文件操作接口允许用户打开、关闭和删除文件,其中open()还支持多种文件创建和状态标签。read()与write()用于文件数据的读写操作,lseek()则用于文件读写位置的调整。
在内存管理方面,LiteOS-M内核提供了标准的POSIX内存分配接口,包括malloc()、free()与memalign()等。其中,malloc()和free()用于内存的php开源相册源码申请与释放,而memalign()则允许用户以指定的内存对齐大小进行内存申请。
此外,calloc()函数在分配内存时预先设置内存区域的值为零,而realloc()则用于调整已分配内存的大小。这些函数构成了内核中内存管理的核心机制,确保资源的高效利用与安全释放。
总结而言,musl libC在LiteOS-M内核中的实现,通过提供全面且高效的文件系统与内存管理功能,为开发者提供了强大的工具集,以满足不同应用场景的需求。本文虽已详述关键功能,但难免有所疏漏,欢迎读者在遇到问题或有改进建议时提出,共同推动技术进步。感谢阅读。
Linux/mntç®å½ä¸»è¦ç¨äºä»ä¹ï¼
linuxä¸mntç®å½çä½ç¨ï¼mount å¯ç´æ¥ç解为âæè½½âææ¥å 驱ãUSB设å¤çç®å½ï¼å è½½åï¼ä¼å¨mntéå¤åºç¸åºè®¾å¤çç®å½ãlinuxç³»ç»æ ¹ç®å½ä¸å个ç®å½ç¨é说æï¼1ã/ æ ¹ç®å½ --------- ææç®å½æå¨å ¶ä¸
2ã/bootã--------- åæ¾Ubuntuå æ ¸åç³»ç»å¯å¨æ件ãç³»ç»å¯å¨æ¶è¿äºæ件å è¢«è£ è½½ã
3ã/etcã--------- ç³»ç»çé ç½®æ件ç®å½ãå¯ç æ件ã设置ç½å¡ä¿¡æ¯ãç¯å¢åéç设置çé½å¨æ¤ç®å½ä¸ï¼è®¸å¤ç½ç»é ç½®æ件ä¹å¨å ¶ä¸ã
4ã/lib --------- æ ¹æ件系ç»ç®å½ä¸ç¨åºåæ ¸å¿æ¨¡åçå ±äº«åºãè¿ä¸ªç®å½éåæ¾çç³»ç»æåºæ¬çå¨æé¾æ¥å ±äº«åºï¼ç±»ä¼¼äºWindowsä¸çsystemç®å½ï¼å ä¹ææçåºç¨ç¨åºé½éè¦ç¨å°è¿äºå ±äº«åºã
5ã/media --------- 主è¦ç¨äºæè½½å¤åªä½è®¾å¤ãubuntuç³»ç»èªå¨æè½½çå 驱ãusb设å¤ï¼åæ¾ä¸´æ¶è¯»å ¥çæ件ã
6ã/proc --------- è¿ä¸ªç®å½æ¯ç³»ç»å åçæ å°ï¼æ们å¯ä»¥ç´æ¥è®¿é®è¿ä¸ªç®å½æ¥è·åç³»ç»ä¿¡æ¯ãä¹å°±æ¯è¯´ï¼è¿ä¸ªç®å½çå 容ä¸å¨ç¡¬çä¸èæ¯å¨å åéã
7ã/sbin ã --------- så°±æ¯Super Userçææï¼è¿éåæ¾çæ¯ç³»ç»ç®¡çå使ç¨çç³»ç»ç®¡çç¨åºï¼å¦ç³»ç»ç®¡çãç®å½æ¥è¯¢çå ³é®å½ä»¤æ件ã
8ã/tmp --------- è¿ä¸ªç®å½æ¯ç¨æ¥åæ¾ä¸äºä¸´æ¶æ件çï¼ææç¨æ·å¯¹æ¤ç®å½é½æ读åæéã
9ã/homeã --------- ç¨æ·ç主ç®å½ãä¸é¢æ¯èªå·±å®ä¹çç¨æ·åçæ件夹ãæ¯ä¸ªç¨æ·ç设置æ件ï¼ç¨æ·çæ¡é¢æ件夹ï¼è¿æç¨æ·çæ°æ®é½æ¾å¨è¿éã
ã/mnt ã --------- æ¤ç®å½ä¸»è¦æ¯ä½ä¸ºæè½½ç¹ä½¿ç¨ãé常å æ¬ç³»ç»å¼å¯¼å被æè½½çæ件系ç»çæè½½ç¹ãå¦æè½½Windowsä¸çæ个ååºã
linux启动时挂载rootfs
1。linux启动时,经过一系列初始化之后,需要mount 根文件系统,为最后运行init进程等做准备,mount 根文件系统有这么几种方式:
1)文件系统已经存在于硬盘(或者类似的设备)的某个分区上了,kernel根据启动的命令行参数(root=/dev/xxx),直接进行mount。 这里有一个问题,在root文件系统本身还不存在的情况下,kernel如 何根据/dev/xxx来找到对应的设备呢?注意:根文件系统和其他文件系统的mount方式是不一样的,kernel通过直接解析设备的如何看懂底层源码名称来获得设备的主、从设备号,然后就可以访问对应的设备驱动 了。所以在init/main.c中有很长一串的root_dev_names(如hda,hdab,sda,sdb,nfs,ram,mtdblock……),通过这个表就可以根据设备名称得到设备号。注意,bootloader或内核中设定的启动参数(root=/dev/xxx)只是一个代号,实际的根文件系统中不一定存在这个设备文件!
2)从软驱等比较慢的设备上装载根文件系统,如果kernel支持ramdisk,在装载root文件系统时,内核判断到需要从软盘(fdx)mount(root=/dev/fd0),就会自动把文件系统映象复制到ramdisk,一般对应设备ram0,然后在ram0上mount 根文件系统。 从源码看,如果kernel编译时没有支持ramdisk,而启动参数又是root=/dev/fd0, 系统将直接在软盘上mount,除了速度比较慢,理论上是可行的(没试过,不知道是不是这样?)
3)启动时用到initrd来mount根文件系统。注意理解ramdisk和initrd这两个概念,其实ramdisk只是在ram上实现的块设备,类似与硬盘操作,但有更快的读写速度,它可以在系统运行的任何时候使用,而不仅仅是用于启动;initrd(boot loader initialized RAM disk)可以说是启动过程中用到的一种机制,具体的易家购源码实现过程也使用ramdisk技术。就是在装载linux之前,bootloader可以把一个比较小的根文件系统的映象装载在内存的某个指定位置,姑且把这段内存称为initrd(这里是initrd所占的内存,不是ramdisk,注意区别),然后bootloader通过传递参数的方式告诉内核initrd的起始地址和大小(也可以把这些参数编译在内核中),在启动阶段就可以暂时的用initrd来mount根文件系统。initrd的最初的目的是为了把kernel的启动分成两个阶段:在kernel中保留最少最基本的启动代码,然后把对各种各样硬件设备的支持以模块的方式放在initrd中,这样就在启动过程中可以从initrd所mount的根文件系统中装载需要的模块。这样的一个好处就是在保持kernel不变的情况下,通过修改initrd中的内容就可以灵活的支持不同的硬件。在启动完成的最后阶段,根文件系统可以重新mount到其他设备上,但是也可以不再 重新mount(很多嵌入式系统就是这样)。 initrd的具体实现过程是这样的:bootloader把根文件系统映象装载到内存指定位置,把相关参数传递给内核,内核启动时把initrd中的内容复制到ramdisk中(ram0),把initrd占用的内存释放掉,在ram0上mount根文件系统。从这个过程可以看出,内核需要对同时对ramdisk和initrd的支持(这种需要都编入内核,不能作为模块)。
2。嵌入式系统根文件系统的一种实现方法:对于kernel和根文件系统都存储在flash中的系统,一般可以利用linux启动的initrd的机制。具体的android app 实例源码过程前面已经比较清楚了,还有一点就是在启动参数中传递root=/dev/ram0,这样使得用initrd进行mount的根文件系统不再切换,因为这个时候实际的设备就是ram0。还有就是initrd的起始地址参数为虚拟地址,需要和bootloader中用的物理地址对应。
Linux内核源码解析---mount挂载原理
Linux磁盘挂载命令"mount -t xxx /dev/sdb1 abc/def/"的底层实现原理非常值得深入了解。从内核初始化的vfsmount开始说起。
内核初始化过程中,主要关注"main.c"中的vfs_caches_init函数,这个方法与mount紧密相连。接着,跟进"mnt_init"和"namespace.c",关键在于最后的三个函数,它们控制了挂载过程的实现。
在"mount.c"中,sysfs_fs_type结构中包含了获取超级块的函数指针,而"init_rootfs"则注册了rootfs类型的文件系统。挂载系统调用sys_mount中的dev_name, dir_name和type参数,分别对应设备名称、挂载目录和文件系统类型。
"do_mount"方法通过path_lookup收集挂载目录信息,创建nameidata结构,然后调用do_add_mount进行实际挂载。这个过程涉及do_kern_mount和graft_tree,尽管具体实现较为复杂,但核心在于创建vfsmount并将其与namespace关联。
在"graft_tree"中的判断逻辑中,vfsmount被创建并与其父mount和挂载目录的dentry建立关系。在"attach_mnt"方法中,新vfsmount与现有结构关联,设置挂载点和父vfsmount,最终形成挂载的概念,即为设备分配vfsmount,并将其与指定目录和vfsmount结合,成为vfs系统的一部分。
Ext4文件系统挂载默认选项
在研究Ext4文件系统挂载选项时,发现官方文档与实际挂载点/proc/mounts显示的选项不完全匹配,特别是默认选项如delalloc。深入内核源码,揭示了procfs展示挂载信息的机制。通过梳理mount过程,发现/proc/mounts与/proc/fs/ext4/{ device}/options显示的选项不一致主要由nodefs参数决定,该参数影响输出的分隔符与选项的展示。
分析显示,/proc/mounts输出的默认选项与Ext4文件系统实际挂载时的行为存在差异,这主要与nodefs参数的状态有关。当nodefs为0时,输出通常更详细,但实际挂载时,部分选项并未显示,这一现象引发对默认选项设置来源的深入探讨。
通过查阅文件系统配置,发现每个文件系统都有一个super block,包含默认挂载选项字段s_default_mount_opts,这是通过tune2fs工具设置的,记录了创建或调整时指定的默认挂载选项。这些默认值包括但不限于user_xattr和acl,与/proc/mounts和/proc/fs/ext4/{ device}/options显示的选项有所差异。
在内核挂载阶段,ext4通过额外设置内存中superblock的s_def_mount_opt字段,影响了实际挂载时的默认选项。这一设置允许在磁盘上通过mkfs时预先指定选项,甚至修改默认行为,如通过设置EXT4_DEFM_NODELALLOC改变delalloc逻辑。
综上所述,Ext4文件系统的默认挂载选项来源于磁盘上的默认选项字段和挂载时的参数设置。内核处理过程中,内存中的superblock字段与磁盘上的并非简单的对应关系,ext4对内存中字段进行额外配置,影响了最终显示的默认选项。
总结,了解Ext4文件系统挂载选项的设置,需关注磁盘上的默认选项、挂载时的参数设置以及内核处理过程中的额外配置。正确查阅/proc/fs/ext4/{ device}/options能准确获取挂载时的选项信息。
深入剖析Linux文件系统之文件系统挂载(一)(超详细~)
深入剖析Linux文件系统之文件系统挂载(一)(超详细~) 我们知道,在Linux系统中,将一个块设备上的文件系统挂载到特定目录才能访问该文件系统下的文件。本文将详细阐述文件系统挂载的核心逻辑,包括Linux内核为挂载文件系统所执行的操作以及为何必须挂载才能访问文件。本文分为上下两篇,上篇着重于挂载全貌及具体文件系统挂载方法,下篇则详细介绍挂载实例与挂载点、超级块的关系。 在Linux中,虚拟文件系统层VFS通过统一所有具体文件系统的接口,屏蔽差异,向用户提供一致的访问方式。VFS作为接口层,向下连接具体的文件系统,向上提供用户进程访问文件的功能。接下来,我们探讨VFS中几个关键对象的作用。 VFS对象包括: file_system_type:描述文件系统类型,包括磁盘文件系统、内存文件系统、伪文件系统和网络文件系统。磁盘文件系统用于非易失性存储介质上的文件,如ext2、ext4、xfs等;内存文件系统在内存上存储文件;伪文件系统则是内核可见或用户可见的虚拟文件系统,如proc、sysfs等;网络文件系统允许访问远程计算机上的数据。 super_block:用于描述块设备上文件系统整体信息,如文件块大小、最大文件大小、文件系统标识等。磁盘文件系统仅有一个super_block描述整个文件系统。 mount:描述超级块与挂载点之间的联系,建立文件系统挂载的实例。磁盘文件系统可被多次挂载,每次挂载内存中创建一个mount对象。 inode:描述磁盘上文件的元数据,文件系统需要从块设备读取磁盘上的inode,创建内存中的inode对象,通常在文件首次打开时创建。 dentry:用于描述文件层次结构,构建目录树,存储目录或文件的名称和inode号,以便进程访问目录项。 file:描述进程打开的文件,创建文件对象加入进程的文件打开表,通过文件描述符进行读写操作。 挂载流程包括系统调用处理、挂载点路径查找、参数合法性检查、调用具体文件系统挂载方法、以及实例添加到全局文件系统树。挂载实例添加到全局文件系统树涉及vfs_get_tree和do_new_mount_fc函数,ext2对挂载的处理则包括初始化阶段、挂载时调用、以及通过mount_bdev执行实际挂载工作。 具体文件系统挂载方法包括: ext2对挂载的处理:启动阶段初始化,挂载时调用ext2_mount,执行mount_bdev来执行实际挂载,ext2_fill_super读取磁盘上的超级块并填充内存中的超级块。 mount_bdev源码分析:查找块设备描述符,创建或获取vfs超级块,调用具体文件系统的fill_super方法读取并填充超级块。 ext2_fill_super源码分析:读取磁盘上的超级块,填充并关联vfs超级块,读取块组描述符,读取磁盘根inode并建立根inode,创建根dentry关联到根inode。 挂载完成后,文件系统已准备好被访问,用户进程通过文件路径打开文件,但尚未关联至挂载点。为了将文件系统关联到挂载点,需要通过do_new_mount_fc将挂载实例加入全局文件系统树。下篇将详细讲解这一过程。