当前位置: 首页 > 科技观察

HarmonyLightKernelMCore源码分析系列之MuslLibC

时间:2023-03-15 09:15:20 科技观察

更多信息请访问:鸿蒙科技社区https://harmonyos.51cto.comLiteOS-MKernelLibC有两种实现方式,您可以任选其一根据您的需要,这两个,即musllibC和newlibc。本文首先学习MuslLibC的实现代码。本文涉及的源代码可以从开源站点https://gitee.com/openharmony/kernel_liteos_m获取。LiteOS-M内核提供了与内核相关的文件系统和内存申请释放接口,其他接口可以直接使用Musl提供的接口。下面分别看看内核提供的接口部分。1、当MuslLibC文件系统使用MuslLibC并支持POSIXFSAPI时,可以使用文件kal\libc\musl\fs.c中定义的文件系统操作接口。这些都是标准的POSIX接口,如果想了解它们的用法,可以参考第2节:系统调用。可以在网页上搜索,也可以直接拼接上面的网址和函数名。例如mount()函数,可以直接访问https://linux.die.net/man/2/mount。部分函数如opendir需要在Section3:libraryfunctions网页查看。下面快速记录一下各个功能的使用方法。1.1功能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等。参数数据由文件系统解析,fat文件类型不需要该参数;“littlefs”文件系统需要传入的数据参数应该是(structlfs_config*)指针类型。该函数会调用components\fs\vfs\los_fs.c中的函数LOS_FsMount,FSVFS后面会讲解。intmount(constchar*source,constchar*target,constchar*filesystemtype,unsignedlongmountflags,constvoid*data){returnLOS_FsMount(source,target,filesystemtype,mountflags,data);}1.2函数umount和umount2函数umount,umount2用于unmount卸载文件系统。参数目标指定要卸载的文件系统。除了卸载,函数umount2还可以指定flag参数来控制卸载行为。支持的参数在third_party\musl\porting\liteos_m\kernel\include\sys\mount.h中定义,例如MNT_FORCE、MNT_DETACH、MNT_EXPIRE和UMOUNT_NOFOLLOW。intumount(constchar*target){returnLOS_FsUmount(target);}intumount2(constchar*target,intflag){returnLOS_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。第三方\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的返回值是文件描述符filedescriptor,其他函数如read、write、lseek、fcntl等会使用该文件描述符。函数close用于关闭一个文件描述符,使fd不再引用到任何文件,可以再次重复使用。函数unlink用于删除path路径指定的文件。inopen(constchar*path,intoflag,...){va_listvaList;va_start(vaList,oflag);intret;ret=LOS_Open(path,oflag,vaList);va_end(vaList);returnret;}intclose(intfd){returnLOS_Close(fd);}intunlink(constchar*path){returnLOS_Unlink(path);}1.4函数读写函数read尝试从fd中读取nbyte数据到从buf开始的buffer中,读取成功返回读取值numberof字节。write函数将buf开始的nbyte字节数据写入fd引用的文件中,写入成功返回实际写入的字节数。ssize_tread(intfd,void*buf,size_tnbyte){returnLOS_Read(fd,buf,nbyte);}ssize_twrite(intfd,constvoid*buf,size_tnbyte){returnLOS_Write(fd,buf,nbyte);}1.5函数lseek函数lseek用于re定位读写文件的偏移位置。whence参数的值为SEEK_SET、SEEK_CUR或SEEK_END,定义在文件third_party\musl\porting\liteos_m\kernel\include\fcntl.h中。SEEK_SET偏移量设置在偏移量字节处。SEEK_CUR偏移量设置为当前位置加上偏移量字节。SEEK_END偏移量设置为文件大小加上偏移字节数。当函数执行成功时,返回值是从文件开头算起的偏移字节值。off_tlseek(intfd,off_toffset,intwhence){returnLOS_Lseek(fd,offset,whence);}}1.6函数fstat、stat和statfs函数fstat和stat用于获取文件的status状态,参数为文件描述符和文件路径分别。参数中的structstat结构定义在文件third_party\musl\porting\liteos_m\kernel\include\bits\stat.h中。函数statfs返回文件系统的统计数据。结构structstatfs在文件third_party\musl\porting\liteos_m\kernel\include\bits\statfs.h中定义。intfstat(intfd,structstat*buf){returnLOS_Fstat(fd,buf);}intstat(constchar*path,structstat*buf){returnLOS_Stat(path,buf);}intstatfs(constchar*path,structstatfs*buf){returnLOS_Statfs(path,buf);}1.7函数mkdir、opendir、readir、closedir和rmdrir函数mkdir用于创建一个目录,其名称由参数path指定。参数模式指定目录权限。创建成功返回0,否则返回-1。函数opendir用于打开一个目录流,目录名由参数dirName指定,返回一个执行该目录的指针。发生错误时,返回NULL并设置errno。返回值类型DIR是struct__dirstream的别名,定义在文件third_party\musl\porting\liteos_m\kernel\include\dirent.h中。您可以访问https://linux.die.net/man/3/opendir了解更多关于此功能的信息。函数readdir用于读取一个目录,返回一个structdirent结构体指针,代表目录流DIR*dir中的下一个目录项目录项。当到达目录流的末尾或出错时返回NULL。该结构在文件third_party\musl\porting\liteos_m\kernel\include\bits\dirent.h中定义。您可以访问https://linux.die.net/man/3/readdir以了解有关此功能的更多信息。函数closedir用于关闭一个目录。rmdir函数用于删除目录,只删除空目录。intmkdir(constchar*path,mode_tmode){returnLOS_Mkdir(path,mode);}DIR*opendir(constchar*dirName){returnLOS_Opendir(dirName);}structdirent*readdir(DIR*dir){returnLOS_Readdir(dir);}intclosedir(DIR*dir){returnLOS_Closedir(dir);}intrmdir(constchar*path){returnLOS_Unlink(path);}1.8函数fsyncmkdir函数用于将内存中所有修改过的文件数据同步到存储设备中。您可以访问https://linux.die.net/man/3/fsync以了解有关此功能的更多信息。intfsync(intfd){returnLOS_Fsync(fd);}1.9函数rename函数rename用于重命名一个文件。您可以访问https://linux.die.net/man/3/rename以了解有关此功能的更多信息。intrename(constchar*oldName,constchar*newName){returnLOS_Rename(oldName,newName);}1.10函数ftruncate函数ftruncate用于将文件截断到指定长度。您可以访问https://linux.die.net/man/3/ftruncate了解有关此功能的更多信息。intftruncate(intfd,off_tlength){returnLOS_Ftruncate(fd,length);}2.MuslLibC内存分配和释放LiteOS-M内核提供了内存分配和释放函数。这些都是标准的POSIX接口,如果想了解它们的用法,可以参考第3节:库函数。可以在网页上搜索,也可以直接将上面的网址和函数名拼接起来。例如malloc()函数,可以直接访问https://linux.die.net/man/3/malloc。有些功能比如opendir需要在网页上查看。下面快速记录一下各个功能的使用方法。1.1函数malloc、free和memalign函数malloc和free分别调用内核内存模块的接口实现内存申请和释放。函数memalign可以申请指定内存对齐大小的内存。voidfree(void*ptr){if(ptr==NULL){return;}LOS_MemFree(OS_SYS_MEM_ADDR,ptr);}void*malloc(size_tsize){if(size==0){returnNULL;}returnLOS_MemAlloc(OS_SYS_MEM_ADDR,size);}void*memalign(size_tboundary,size_tsize){if(size==0){returnNULL;}returnLOS_MemAllocAlign(OS_SYS_MEM_ADDR,size,boundary);}1.2函数malloc,free和memalign函数calloc在动态存储区分配nitem内存一块连续的空间,长度为size,函数返回一个指向分配起始地址的指针;如果分配不成功,则返回NULL。函数zalloc和malloc的区别在于申请成功后,申请的内存区域置0。函数realloc用于重新申请一块内存区域。void*calloc(size_tnitems,size_tsize){size_treal_size;void*ptr=NULL;if(nitems==0||size==0){returnNULL;}real_size=(size_t)(nitems*size);ptr=LOS_MemAlloc(OS_SYS_MEM_ADDR,real_size);if(ptr!=NULL){(void)memset_s(ptr,real_size,0,real_size);}returnptr;}void*zalloc(size_tsize){void*ptr=NULL;if(size==0){returnNULL;}ptr=LOS_MemAlloc(OS_SYS_MEM_ADDR,size);if(ptr!=NULL){(void)memset_s(ptr,size,0,size);}returnptr;}void*realloc(void*ptr,size_tsize){if(ptr==NULL){returnmalloc(size);}if(size==0){free(ptr);returnNULL;}returnLOS_MemRealloc(OS_SYS_MEM_ADDR,ptr,size);}总结这篇文章学习了LiteOS-M内核MuslLibC实现,尤其是文件系统和内存分配和释放部分。更多信息请访问:Harmonyos.51cto.com,与华为官方合作打造的鸿蒙技术社区