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

移植案例及原理——Utils子系统文件操作

时间:2023-03-20 13:57:04 科技观察

更多内容请访问:与华为官方共建的鸿蒙技术社区https://harmonyos.51cto.comUtils子系统为公众号基地OpenHarmony的库,存放OpenHarmony常用的基础组件。这些基础组件可供OpenHarmony的各种业务子系统和上层应用使用。不同平台公共基础库提供的能力:LiteOS-M内核:KV(键值)存储、文件操作、定时器、Dump系统属性。LiteOS-A内核:KV(键值)存储、定时器、JSAPI(设备查询、数据存储)、Dump系统属性。本文介绍了开发板移植时如何适配utils子系统的文件文件操作组件,并介绍了相关的运行机制原理。系统属性部分syspara_lite包含系统参数属性syspara_lite和token。文件操作组件在utils\native\lite\中定义。源码目录如下:utils/native/lite/#通用基础库根目录├──file#文件接口实现├──hals#HAL目录│└──file#文件操作硬件抽象层头文件├───include#公共基础库外部接口文件├──js#JSAPI目录│└──builtin│├──common│├──deviceinfokit#设备信息包│├──filekit#文件包│└──kvstorekit#KV存储Kit├──kal#KAL目录│└──timer#KAL实现Timer├──kv_store#KV存储实现│├──innerkits#KV存储内部接口│└──src#KV存储源文件├───memory│└──include#内存池管理接口├──os_dump#转储系统属性└──timer_task#定时器实现1.文件文件操作组件适配示例1.1配置产品方案config.jsonutils子系统文件文件操作组件适配For配置示例请参考vendor\ohemu\qemu_csky_mini_system_demo\config.json,代码片段如下。⑴用于配置子系统的文件组件。(2)在开发板目录下指定适配目录,需要在该适配目录下创建目录device\qemu\SmartL_E802\adapter\hals\utils\file\。为什么要配置这个目录,后面会分析。{"subsystem":"utils","components":[⑴{"component":"file","features":[]},{"component":"kv_store","features":[]}]}],⑵"vendor_adapter_dir":"//device/qemu/SmartL_E802/adapter",1.2适配的hal_file.h文件中的接口定义在文件utils\native\lite\hals\file\hal_file.h头文件中操作接口,适配开发板时,如果需要使用utils子系统的文件操作组件,必须适配这些接口。需要适配的接口如下。HalFileOpen()函数的返回值是文件描述符fd,可以被其他带intfd参数的函数使用。intHalFileOpen(constchar*path,intoflag,intmode);intHalFileClose(intfd);intHalFileRead(intfd,char*buf,unsignedintlen);intHalFileWrite(intfd,constchar*buf,unsignedintlen);intHalFileDelete(constchar*path);intHalFileStat(constchar*path,unsignedint*fileSize);intHalFileSeek(intfd,intoffset,unsignedintwhence);filedevice\qemu\SmartL_E802\adapter\hals\utils\file\src\hal_file.c可以作为参考例子演示如何适配上述接口。⑴处的HalFileOpen()函数中,首先组装文件路径,“/littlefs”为SmartL_E802开发板设置的LFS文件默认挂载点。LFS的适配请参考device\qemu\SmartL_E802\liteos_m\board\fs\fs_init.c。HalFileXXX函数调用的open、close、read、write、unlink、stat、lseek函数定义在kernel\liteos_m\kal\libc\musl\fs.c或kernel\liteos_m\kal\libc\newlib\porting\src\fs.c,这个要看使用的是muslC库还是newlibC库。文件系统接口调用链如下:UtilsFileXXX(utils\native\lite\file\src\file_impl_hal\file.c)->HalFileXXXX(device\qemu\SmartL_E802\adapter\hals\utils\file\src\hal_file.c)->打开/读/写/…(kernel\liteos_m\kal\libc\musl\fs.c或kernel\liteos_m\kal\libc\newlib\porting\src\fs.c)->LOS_XXXX(kernel\liteos_m\components\fs\vfs\los_fs.c)->Lfs_XXXX(kernel\liteos_m\components\fs\littlefs\lfs_api.c)->lfs_file_XXX(third_party\littlefs\lfs.c)->Littlefs*(device\qemu\SmartL_E802\liteos_m\board\fs\littlefs_hal.c)。intHalFileOpen(constchar*path,intoflag,intmode){chartmpPath[LITTLEFS_MAX_LFN_LEN]={0};⑴(void)snprintf_s(tmpPath,LITTLEFS_MAX_LFN_LEN,LITTLEFS_MAX_LFN_LEN,"/littlefs/%s",path);返回打开(tmpPath,oflag,模式);}intHalFileClose(intfd){返回关闭(fd);}intHalFileRead(intfd,char*buf,unsignedintlen){returnread(fd,buf,len);}intHalFileWrite(intfd,constchar*buf,unsignedintlen){returnwrite(fd,buf,len);}intHalFileDelete(constchar*path){chartmpPath[LITTLEFS_MAX_LFN_LEN]={0};(void)snprintf_s(tmpPath,LITTLEFS_MAX_LFN_LEN,LITTLEFS_MAX_LFN_LEN,"/littlefs/%s",路径);返回取消链接(路径);}intHalFileStat(constchar*path,unsignedint*fileSize){chartmpPath[LITTLEFS_MAX_LFN_LEN]={0};结构统计halStat;intret=0;(void)snprintf_s(tmpPath,LITTLEFS_MAX_LFN_LEN,LITTLEFS_MAX_LFN_LEN,"/littlefs/%s",路径);ret=stat(tmpPath,&halStat);*fileSize=halStat.st_size;返还;}intHalFileSeek(intfd,intoffset,unsignedintwhence){returnlseek(fd,(off_t)offset,whence);}2、文件文件操作组件代码分析2.1组件头文件上面我们已经看到,文件文件操作组件代码的头文件为utils\native\lite\include\utils_file.h,用户程序可以使用接口int这个头文件中定义的UtilsFileOpen(constchar*path,intoflag,intmode);intUtilsFileClose(intfd);intUtilsFileRead(intfd,char*buf,unsignedintlen);intUtilsFileWrite(intfd,constchar*buf,unsignedintlen);intUtilsFileDelete(constchar*path);intUtilsFileStat(constchar*path,unsignedint*fileSize);intUtilsFileSeek(intfd,intoffset,unsignedintwhence);intUtilsFileCopy(constchar*src,constchar*dest);intUtilsFileMove(constchar*src,constchar*dest);复制头文件utils\native\lite\hals\file\hal_file.h中定义的接口,需要移植适配时提供实现,具体接口见上。2.2组件源代码文件UtilsFileXXX接口在文件utils\native\lite\file\src\file_impl_hal\file.c中实现,代码比较简单,需要移植适配的HalFileXXX接口调用开发板。intUtilsFileOpen(constchar*path,intoflag,intmode){returnHalFileOpen(path,oflag,mode);}intUtilsFileClose(intfd){returnHalFileClose(fd);}intUtilsFileRead(intfd,char*buf,unsignedintlen){returnHalFileRead(fd,buf,len);}intUtilsFileWrite(intfd,constchar*buf,unsignedintlen){returnHalFileWrite(fd,buf,len);}intUtilsFileDelete(constchar*path){returnHalFileDelete(path);}intUtilsFileStat(constchar*path,unsignedint*fileSize){returnHalFileStat(path,fileSize);}intUtilsFileSeek(intfd,intoffset,unsignedintwhence){returnHalFileSeek(fd,offset,whence);}intUtilsFileCopy(constchar*src,constchar*dest){if((src==NULL)||(dest==NULL)){returnEC_FAILURE;}intfpSrc=UtilsFileOpen(src,O_RDONLY_FS,0);如果(fpSrc<0){返回fpSrc;}intfpDest=UtilsFileOpen(dest,O_RDWR_FS|O_CREAT_FS|O_TRUNC_FS,0);如果(fpDest<0){UtilsFileClose(fpSrc);返回fpDest;}boolcopyFailed=true;char*dataBuf=(char*)malloc(BUFFER_SIZE);如果(dataBuf==NULL){转到MALLOC_ERROR;}intnLen=UtilsFileRead(fpSrc,dataBuf,BUFFER_SIZE);while(nLen>0){if(UtilsFileWrite(fpDest,dataBuf,nLen)!=nLen){转到退出;}nLen=UtilsFileRead(fpSrc,dataBuf,BUFFER_SIZE);}copyFailed=(nLen<0);EXIT:free(dataBuf);MALLOC_ERROR:UtilsFileClose(fpSrc);UtilsFileClose(fpDest);如果(复制失败){UtilsFileDelete(目标);返回EC_FAILURE;}returnEC_SUCCESS;}intUtilsFileMove(constchar*src,constchar*dest){intret=UtilsFileCopy(src,dest);如果(ret==EC_SUCCESS){ret=UtilsFileDelete(src);}returnret;}2.3编译构建组件编译构建配置文件utils\native\lite\file\BUILD.gn代码如下,(1)处的配置项ohos_board_adapter_dir为产品中定义的开发板适配目录解决方案配置文件config.json可见,开发板适配目录必须包含与目录hals/utils/file同级的BUILD.gn文件,buildtarget必须为hal_file_static。不能随便取名。import("//build/lite/config/component/lite_component.gni")static_library("native_file"){sources=["src/file_impl_hal/file.c"]include_dirs=["//utils/native/lite/include","//utils/native/lite/hals/file",]⑴deps=["$ohos_board_adapter_dir/hals/utils/file:hal_file_static"]}lite_component("file"){features=[":native_file"]}小结本文介绍了utils子系统文件操作组件的移植和适配案例,并对组件的源码进行了分析。更多信息请访问:与华为官方共建的鸿蒙技术社区https://harmonyos.51cto.com