鸿蒙轻内核 M 核源码分析:LibC 实现之 Musl LibC
摘要:本文学习了 LiteOS-M 内核 Musl LibC 的实现,特别是文件系统和内存分配释放部分。
本文分享自华为云社区《鸿蒙轻内核M核源码分析系列十九 Musl LibC》,作者:zhushy。
LiteOS-M 内核 LibC 实现有 2 种,可以根据需求进行二选一,分别是 musl libC 和 newlibc。本文先学习下 Musl LibC 的实现代码。文中所涉及的源码,均可以在开源站点https://gitee.com/openharmony/kernel_liteos_m 获取。LiteOS-M 内核提供了和内核相关的文件系统、内存申请释放接口,其他接口可以直接使用 Musl 提供的。我们分别来看下内核提供的接口部分。
1、Musl LibC 文件系统
在使用 Musl LibC 并且使能支持 POSIX FS API 时,可以使用文件 kal\libc\musl\fs.c 中定义的文件系统操作接口。这些是标准的 POSIX 接口,如果想了解其用法,可以参考 Section 2: system calls。可以在网页上搜索,也可以直接把上述网址和函数名称进行拼接,如对于 mount()函数,可以直接访问https://linux.die.net/man/2/mount。opendir 等部分函数需要在 Section 3: library functions 网页上查看。下文快速记录下各个函数的使用方法。
1.1 函数 mount
函数 mount 会挂载 source 参数(通常是设备名称,也可以是目录)指定的文件系统到 target 参数指定的目录。文件系统类型 LiteOS-M 内核支持"fat"和"littlefs"两种类型。"littlefs"文件系统不需要挂载选项参数 mountflags。对于 fat 文件类型,挂载选项参数定义在文件 third_party\musl\porting\liteos_m\kernel\include\sys\mount.h 中,如 MS_RDONLY、MS_NOSUID、MS_REMOUNT 等等。参数 data 由文件系统进行解析,fat 文件类型不需要该参数;"littlefs"文件系统需要传入的 data 参数应该为 (struct lfs_config*)指针类型。
该函数会调用 components\fs\vfs\los_fs.c 中的函数 LOS_FsMount,后文会专门讲解 FS VFS。
1.2 函数 umount 和 umount2
函数 umount, umount2 用于 unmount 卸载文件系统。参数 target 指定要卸载的文件系统。函数 umount2 除了卸载,还可以指定 flag 参数来控制卸载行为。支持的参数定义在 third_party\musl\porting\liteos_m\kernel\include\sys\mount.h,如 MNT_FORCE、MNT_DETACH、MNT_EXPIRE 和 UMOUNT_NOFOLLOW。
1.3 函数 open、close 和 unlink
函数 open 用于打开一个文件或设备,可能会先创建文件或设备。参数 path 指定文件或设备的路径,参数 oflag 需要使用下面的访问模式 O_RDONLY, O_WRONLY, O_RDWR 中的一个,这几个定义在文件 third_party\musl\porting\liteos_m\kernel\include\fcntl.h。third_party\musl\porting\liteos_m\kernel\include\bits\fcntl.h。另外,还有些其他文件创建标签或文件状态标签可以通过逻辑与进行指定。文件创建标签有 O_CLOEXEC, O_CREAT, O_DIRECTORY, O_EXCL, O_NOCTTY, O_NOFOLLOW, O_TRUNC 和 O_TTY_INIT。其余的为文件状态标签,这些标签定义文件中 third_party\musl\porting\liteos_m\kernel\include\bits\fcntl.h 中。可以访问https://linux.die.net/man/2/open了解这些标签的详细用法。
函数 open 返回值为文件描述符 file descriptor,会被其他函数如 read, write, lseek, fcntl 等使用。函数 close 用于关闭一个文件描述符,使 fd 不再引用任何文件,可被再次重用。函数 unlink 用于删除 path 路径指定的文件。
1.4 函数 read 和 write
函数 read 尝试从 fd 中读取 nbyte 字节的数据到 buf 开始的缓存里,读取成功时返回读取的字节数目。函数 write 把 buf 处开始的 nbyte 字节数据写入 fd 引用的文件里,写入成功时返回实际写入的字节数目。
1.5 函数 lseek
函数 lseek 用于重新定位文件读写的偏移位置。参数 whence 取值为 SEEK_SET、SEEK_CUR 或 SEEK_END,定义在文件 third_party\musl\porting\liteos_m\kernel\include\fcntl.h。
SEEK_SET
偏移设置在 offset 字节处。
SEEK_CUR
偏移设置在当前位置加上 offset 字节处。
SEEK_END
偏移设置在文件大小加上 offset 字节处。
函数执行成功时,返回值为从文件开头的偏移字节数值。
1.6 函数 fstat、stat 和 statfs
函数 fstat 和 stat 用于获取文件的状态 state,参数参数分别是文件描述符和文件路径。参数中的 struct stat 结构体定义在文件 third_party\musl\porting\liteos_m\kernel\include\bits\stat.h 中。
函数 statfs 返回文件系统统计 statistics 数据,结构体 struct statfs 定义在文件 third_party\musl\porting\liteos_m\kernel\include\bits\statfs.h 中。
1.7 函数 mkdir、opendir、readir、closedir 和 rmdrir
函数 mkdir 用于创建一个目录,目录名称由参数 path 指定。参数 mode 指定目录权限。创建成功返回 0,否则返回-1。
函数 opendir 用于打开一个目录流 a directory stream,目录名称由参数 dirName 指定,返回一个执行目录刘的指针。发生错误时,返回 NULL,并设置 errno。返回值类型 DIR 是 struct __dirstream 的别名,定义在文件中 third_party\musl\porting\liteos_m\kernel\include\dirent.h。可以访问https://linux.die.net/man/3/opendir了解更多关于该函数的信息。
函数 readdir 用于读取一个目录,返回一个 struct dirent 结构体指针,代表目录流 DIR *dir 中的下一个目录条目 directory entry。到达目录流尾部或错误时,返回 NULL。结构体定义在文件 third_party\musl\porting\liteos_m\kernel\include\bits\dirent.h 中。 可以访问https://linux.die.net/man/3/readdir了解更多关于该函数的信息。
函数 closedir 用于关闭一个目录。函数 rmdir 用于删除一个目录,只有空目录才会被删除。
1.8 函数 fsync
函数 mkdir 用于同步内存中所有已修改的文件数据到储存设备。可以访问https://linux.die.net/man/3/fsync了解更多关于该函数的信息。
1.9 函数 rename
函数 rename 用于重命名一个文件。可以访问https://linux.die.net/man/3/rename了解更多关于该函数的信息。
1.10 函数 ftruncate
函数 ftruncate 用于截断一个文件到指定的长度。可以访问https://linux.die.net/man/3/ftruncate了解更多关于该函数的信息。
2、Musl LibC 内存分配释放
LiteOS-M 内核提供了内存分配释放函数。这些是标准的 POSIX 接口,如果想了解其用法,可以参考 Section 3: library functions。可以在网页上搜索,也可以直接把上述网址和函数名称进行拼接,如对于 malloc()函数,可以直接访问https://linux.die.net/man/3/malloc。opendir 等部分函数需要在网页上查看。下文快速记录下各个函数的使用方法。
2.1 函数 malloc、free 和 memalign
函数 malloc 和 free 分别调用内核内存模块的接口来实现内存申请和释放。函数 memalign 可以以指定的内存对齐大小来申请内存。
2.2 函数 malloc、free 和 memalign
函数 calloc 在内存的动态存储区中分配 nitems 个长度为 size 的连续空间,函数返回一个指向分配起始地址的指针;如果分配不成功,返回 NULL。
函数 zalloc 和 malloc 的区别是,申请成功后,对申请的内存区域置 0。函数 realloc 用于重新申请一块内存区域。
小结
本文学习了 LiteOS-M 内核 Musl LibC 的实现,特别是文件系统和内存分配释放部分。时间仓促和能力关系,如有失误,欢迎指正。感谢阅读,如有任何问题、建议,都可以博客下留言给我,谢谢。
参考资料
library functions - Linux man pages
system calls - Linux man pages
版权声明: 本文为 InfoQ 作者【华为云开发者社区】的原创文章。
原文链接:【http://xie.infoq.cn/article/bda0466958181aa549bb9957e】。文章转载请联系作者。
评论