鸿蒙轻内核M核源码分析系列之Musl LibC

开发 前端
LiteOS-M内核LibC实现有2种,可以根据需求进行二选一,分别是musl libC和newlibc。本文先学习下Musl LibC的实现代码。文中所涉及的源码,均可以在开源站点。

想了解更多内容,请访问:

51CTO和华为官方合作共建的鸿蒙技术社区

https://harmonyos.51cto.com

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. int mount(const char *source, const char *target, 
  2.               const char *filesystemtype, unsigned long mountflags, 
  3.               const void *data) 
  4.     return LOS_FsMount(source, target, filesystemtype, mountflags, data); 

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. int umount(const char *target) 
  2.     return LOS_FsUmount(target); 
  3.  
  4. int umount2(const char *target, int flag) 
  5.     return LOS_FsUmount2(target, flag); 

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. int open(const char *path, int oflag, ...) 
  2.     va_list vaList; 
  3.     va_start(vaList, oflag); 
  4.     int ret; 
  5.     ret = LOS_Open(path, oflag, vaList); 
  6.     va_end(vaList); 
  7.     return ret; 
  8.  
  9. int close(int fd) 
  10.     return LOS_Close(fd); 
  11.  
  12. int unlink(const char *path) 
  13.     return LOS_Unlink(path); 

1.4 函数read和write

函数read尝试从fd中读取nbyte字节的数据到buf开始的缓存里,读取成功时返回读取的字节数目。函数write把buf处开始的nbyte字节数据写入fd引用的文件里,写入成功时返回实际写入的字节数目。

  1. ssize_t read(int fd, void *buf, size_t nbyte) 
  2.     return LOS_Read(fd, buf, nbyte); 
  3.  
  4. ssize_t write(int fd, const void *buf, size_t nbyte) 
  5.     return LOS_Write(fd, buf, nbyte); 

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. off_t lseek(int fd, off_t offset, int whence) 
  2.     return LOS_Lseek(fd, offset, whence); 
  3. }} 

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. int fstat(int fd, struct stat *buf) 
  2.     return LOS_Fstat(fd, buf); 
  3.  
  4. int stat(const char *path, struct stat *buf) 
  5.     return LOS_Stat(path, buf); 
  6. int statfs(const char *path, struct statfs *buf) 
  7.     return LOS_Statfs(path, buf); 

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. int mkdir(const char *path, mode_t mode) 
  2.     return LOS_Mkdir(path, mode); 
  3.  
  4. DIR *opendir(const char *dirName) 
  5.     return LOS_Opendir(dirName); 
  6.  
  7. struct dirent *readdir(DIR *dir) 
  8.     return LOS_Readdir(dir); 
  9.  
  10. int closedir(DIR *dir) 
  11.     return LOS_Closedir(dir); 
  12.  
  13. int rmdir(const char *path) 
  14.     return LOS_Unlink(path); 

1.8 函数fsync

函数mkdir用于同步内存中所有已修改的文件数据到储存设备。可以访问https://linux.die.net/man/3/fsync了解更多关于该函数的信息。

  1. int fsync(int fd) 
  2.     return LOS_Fsync(fd); 

1.9 函数rename

函数rename用于重命名一个文件。可以访问https://linux.die.net/man/3/rename了解更多关于该函数的信息。

  1. int rename(const char *oldName, const char *newName) 
  2.     return LOS_Rename(oldName, newName); 
  3.  

1.10 函数ftruncate

函数ftruncate用于截断一个文件到指定的长度。可以访问https://linux.die.net/man/3/ftruncate了解更多关于该函数的信息。

  1. int ftruncate(int fd, off_t length) 
  2.     return LOS_Ftruncate(fd, length); 

2、Musl LibC内存分配释放

LiteOS-M内核提供了内存分配释放函数。这些是标准的POSIX接口,如果想了解其用法,可以参考Section 3: library functions。可以在网页上搜索,也可以直接把上述网址和函数名称进行拼接,如对于malloc()函数,可以直接访问https://linux.die.net/man/3/malloc。opendir等部分函数需要在网页上查看。下文快速记录下各个函数的使用方法。

1.1 函数malloc、free和memalign

函数malloc和free分别调用内核内存模块的接口来实现内存申请和释放。函数memalign可以以指定的内存对齐大小来申请内存。

  1. void free(void *ptr) 
  2.     if (ptr == NULL) { 
  3.         return
  4.     } 
  5.  
  6.     LOS_MemFree(OS_SYS_MEM_ADDR, ptr); 
  7.  
  8. void *malloc(size_t size
  9.     if (size == 0) { 
  10.         return NULL
  11.     } 
  12.  
  13.     return LOS_MemAlloc(OS_SYS_MEM_ADDR, size); 
  14. void *memalign(size_t boundary, size_t size
  15.     if (size == 0) { 
  16.         return NULL
  17.     } 
  18.  
  19.     return LOS_MemAllocAlign(OS_SYS_MEM_ADDR, size, boundary); 

1.2 函数malloc、free和memalign

函数calloc在内存的动态存储区中分配nitems个长度为size的连续空间,函数返回一个指向分配起始地址的指针;如果分配不成功,返回NULL。

函数zalloc和malloc的区别是,申请成功后,对申请的内存区域置0。函数realloc用于重新申请一块内存区域。

  1. void *calloc(size_t nitems, size_t size
  2.     size_t real_size; 
  3.     void *ptr = NULL
  4.  
  5.     if (nitems == 0 || size == 0) { 
  6.         return NULL
  7.     } 
  8.  
  9.     real_size = (size_t)(nitems * size); 
  10.     ptr = LOS_MemAlloc(OS_SYS_MEM_ADDR, real_size); 
  11.     if (ptr != NULL) { 
  12.         (void)memset_s(ptr, real_size, 0, real_size); 
  13.     } 
  14.     return ptr; 
  15. void *zalloc(size_t size
  16.     void *ptr = NULL
  17.  
  18.     if (size == 0) { 
  19.         return NULL
  20.     } 
  21.  
  22.     ptr = LOS_MemAlloc(OS_SYS_MEM_ADDR, size); 
  23.     if (ptr != NULL) { 
  24.         (void)memset_s(ptr, size, 0, size); 
  25.     } 
  26.     return ptr; 
  27.  
  28. void *realloc(void *ptr, size_t size
  29.     if (ptr == NULL) { 
  30.         return malloc(size); 
  31.     } 
  32.  
  33.     if (size == 0) { 
  34.         free(ptr); 
  35.         return NULL
  36.     } 
  37.  
  38.     return LOS_MemRealloc(OS_SYS_MEM_ADDR, ptr, size); 

小结

本文学习了LiteOS-M内核Musl LibC的实现,特别是文件系统和内存分配释放部分。

想了解更多内容,请访问:

51CTO和华为官方合作共建的鸿蒙技术社区

https://harmonyos.51cto.com

 

责任编辑:jianghua 来源: 鸿蒙社区
相关推荐

2022-01-12 10:50:23

鸿蒙HarmonyOS应用

2021-06-04 09:57:49

鸿蒙HarmonyOS应用

2022-03-11 20:23:14

鸿蒙源码分析进程管理

2021-05-17 09:28:59

鸿蒙HarmonyOS应用

2021-05-08 15:14:50

鸿蒙HarmonyOS应用

2021-06-04 14:15:10

鸿蒙HarmonyOS应用

2021-05-25 09:28:34

鸿蒙HarmonyOS应用

2021-10-20 16:08:57

鸿蒙HarmonyOS应用

2022-01-14 08:39:47

鸿蒙HarmonyOS应用

2021-05-31 20:30:55

鸿蒙HarmonyOS应用

2021-09-22 14:36:32

鸿蒙HarmonyOS应用

2021-07-06 09:45:03

鸿蒙HarmonyOS应用

2022-04-13 11:02:12

鸿蒙事件模块事件Event

2022-03-03 18:28:28

Harmony进程任务管理模块

2021-05-27 09:43:56

鸿蒙HarmonyOS应用

2021-05-11 09:54:55

鸿蒙HarmonyOS应用

2021-06-09 09:48:01

鸿蒙HarmonyOS应用

2021-05-21 09:25:11

鸿蒙HarmonyOS应用

2021-12-01 15:59:22

鸿蒙HarmonyOS应用

2021-05-10 15:05:56

鸿蒙HarmonyOS应用
点赞
收藏

51CTO技术栈公众号