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

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。

int mount(const char *source, const char *target,const char *filesystemtype, unsigned long mountflags,const void *data)
{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。

int umount(const char *target)
{return LOS_FsUmount(target);
}int umount2(const char *target, int flag)
{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路径指定的文件。

int open(const char *path, int oflag, ...)
{va_list vaList;va_start(vaList, oflag);int ret;ret = LOS_Open(path, oflag, vaList);va_end(vaList);return ret;
}int close(int fd)
{return LOS_Close(fd);
}int unlink(const char *path)
{return LOS_Unlink(path);
}

1.4 函数read和write

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

ssize_t read(int fd, void *buf, size_t nbyte)
{return LOS_Read(fd, buf, nbyte);
}ssize_t write(int fd, const void *buf, size_t nbyte)
{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字节处。

函数执行成功时,返回值为从文件开头的偏移字节数值。

off_t lseek(int fd, off_t offset, int whence)
{return LOS_Lseek(fd, offset, whence);
}}

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中。

int fstat(int fd, struct stat *buf)
{return LOS_Fstat(fd, buf);
}int stat(const char *path, struct stat *buf)
{return LOS_Stat(path, buf);
}
int statfs(const char *path, struct statfs *buf)
{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用于删除一个目录,只有空目录才会被删除。

int mkdir(const char *path, mode_t mode)
{return LOS_Mkdir(path, mode);
}DIR *opendir(const char *dirName)
{return LOS_Opendir(dirName);
}struct dirent *readdir(DIR *dir)
{return LOS_Readdir(dir);
}int closedir(DIR *dir)
{return LOS_Closedir(dir);
}int rmdir(const char *path)
{return LOS_Unlink(path);
}

1.8 函数fsync

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

int fsync(int fd)
{return LOS_Fsync(fd);
}

1.9 函数rename

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

int rename(const char *oldName, const char *newName)
{return LOS_Rename(oldName, newName);
}

1.10 函数ftruncate

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

int ftruncate(int fd, off_t length)
{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可以以指定的内存对齐大小来申请内存。

void free(void *ptr)
{if (ptr == NULL) {return;}LOS_MemFree(OS_SYS_MEM_ADDR, ptr);
}void *malloc(size_t size)
{if (size == 0) {return NULL;}return LOS_MemAlloc(OS_SYS_MEM_ADDR, size);
}
void *memalign(size_t boundary, size_t size)
{if (size == 0) {return NULL;}return LOS_MemAllocAlign(OS_SYS_MEM_ADDR, size, boundary);
}

1.2 函数malloc、free和memalign

函数calloc在内存的动态存储区中分配nitems个长度为size的连续空间,函数返回一个指向分配起始地址的指针;如果分配不成功,返回NULL。
函数zalloc和malloc的区别是,申请成功后,对申请的内存区域置0。函数realloc用于重新申请一块内存区域。

void *calloc(size_t nitems, size_t size)
{size_t real_size;void *ptr = NULL;if (nitems == 0 || size == 0) {return NULL;}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);}return ptr;
}
void *zalloc(size_t size)
{void *ptr = NULL;if (size == 0) {return NULL;}ptr = LOS_MemAlloc(OS_SYS_MEM_ADDR, size);if (ptr != NULL) {(void)memset_s(ptr, size, 0, size);}return ptr;
}void *realloc(void *ptr, size_t size)
{if (ptr == NULL) {return malloc(size);}if (size == 0) {free(ptr);return NULL;}return LOS_MemRealloc(OS_SYS_MEM_ADDR, ptr, size);
}

小结

本文学习了LiteOS-M内核Musl LibC的实现,特别是文件系统和内存分配释放部分。时间仓促和能力关系,如有失误,欢迎指正。

如果大家想更加深入的学习 OpenHarmony 开发的内容,不妨可以参考以下相关学习文档进行学习,助你快速提升自己:

OpenHarmony 开发环境搭建:https://qr18.cn/CgxrRy

《OpenHarmony源码解析》:https://qr18.cn/CgxrRy

  • 搭建开发环境
  • Windows 开发环境的搭建
  • Ubuntu 开发环境搭建
  • Linux 与 Windows 之间的文件共享
  • ……

系统架构分析:https://qr18.cn/CgxrRy

  • 构建子系统
  • 启动流程
  • 子系统
  • 分布式任务调度子系统
  • 分布式通信子系统
  • 驱动子系统
  • ……

OpenHarmony 设备开发学习手册:https://qr18.cn/CgxrRy

在这里插入图片描述

OpenHarmony面试题(内含参考答案):https://qr18.cn/CgxrRy

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/851374.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于小波样条框架的一维时间序列信号降噪方法(MATLAB R2018A)

1952年,DUFFIN在研究非调和Fourier级数时引入了Hilbert空间中框架的概念,然而并没有引起很大的反响。1986年,DAUBECHIES研究发现利用框架可以将L2(R)中的函数展开成类似标准正交基的级数,并且用框架研究函数时所需的条件要比用标准…

多态的应用——数组多态

介绍 ai查询 在Java中,动态数组通常通过ArrayList类来实现,它是Java集合框架(Java Collections Framework)的一部分。ArrayList是一个可调整大小的数组实现,提供了比标准数组更多的灵活性和功能。 以下是使用ArrayLis…

基于51单片机的MQ-2烟雾报警设计

随着现代家庭用火、用电量的增加,家庭烟雾发生的频率越来越高。烟雾报警器也随之被广泛应用于各种场合。本课题所研究的无线多功能烟雾报警器采用STC89C51为核心控制器,利用气体传感器MQ-2、ADC0832模数转换器、DS18B20温度传感器等实现基本功能。通过这些传感器和芯片,当环…

前端技术回顾系列 08|TS 泛型基础

在微信中阅读,关注公众号:CodeFit。 创作不易,如果你觉得这篇文章对你有帮助,请不要忘了 点赞、分享 和 关注 我的公众号:CodeFit,为我的持续创作提供一些动力。 上篇内容回顾:枚举(Enums) 在上篇文章中,我们详细回顾了 TypeScript 中的 枚举(Enums)。 枚举 是一…

设置路径别名

一、描述 如果想要给路径设置为别名,就是常见的有些项目前面的引入文件通过开头的,也就是替换了一些固定的文件路径,怎么配置。 二、配置 import { defineConfig } from vite import react from vitejs/plugin-react import path from path…

ElementUi el-tree动态加载节点数据 load方法触发机制

需求背景:需要根据点击后获取的数据动态渲染一个 el-tree,同时渲染出来的 el-tree,需要点击节点时才能获取该节点的层数的获取,如图所示,我需要点击“组”节点才能渲染“设备列表”树,同时“设备列表”树的…

war后门文件部署 什么是war后门文件 为什么要部署???看见war后门文件部署你知道????

在漏洞复现的时候做了一道war后门文件部署的,然后我们就要去了解什么是war包,然后这个漏洞实现要有什么情况??为什么要进行部署?? war包在哪些地方可以实现??? war是一种…

优设AI导航

1、优设AI导航 优设AI导航

数据结构与算法题目集(中文)6-2顺序表操作集

题目地址 https://pintia.cn/problem-sets/15/exam/problems/type/6?problemSetProblemId725&page0 注意审题,返回false的时候不要返回ERROR,否则答案错误,机器规则是死的。 位置一般指数组下标,位序一般指数组下标1。但是思…

[FreeRTOS 基础知识] 任务调度 与 链表

文章目录 任务并行的概念RTOS如何实现多任务调度? 任务并行的概念 在生活中,经常出现一心多用的情况。比如你需要一边吃饭一边手机回复信息,这里面就存在两个任务:任务一、吃饭。任务二、手机回复信息。 假如你无法一心多用&…

前端技术入门指南

引言 在数字化时代,前端开发成为了连接用户与数字世界的重要桥梁。无论你是对编程充满好奇的新手,还是想要拓展自己技能领域的在职人员,前端开发都是一个值得学习和探索的领域。本文将带你走进前端技术的世界,为你提供一个入门指…

【Modelground】个人AI产品MVP迭代平台(5)——神投手(实时投篮检测游戏)

文章目录 介绍篮框识别进球算法离屏渲染总结 介绍 神投手是我开发的一款移动端web实时投篮检测游戏。其解决的痛点是:专为投篮训练而生的,有手机就能玩的投篮计数游戏。我本人是一个篮球爱好者,特点就是投篮准,虽然投篮挺靠天赋&…

DevExpress WPF中文教程:Grid - 如何向项目添加GridControl并绑定到数据

DevExpress WPF拥有120个控件和库,将帮助您交付满足甚至超出企业需求的高性能业务应用程序。通过DevExpress WPF能创建有着强大互动功能的XAML基础应用程序,这些应用程序专注于当代客户的需求和构建未来新一代支持触摸的解决方案。 无论是Office办公软件…

第十二届蓝桥杯单片机国赛练习代码

文章目录 前言一、问题重述二、主函数总结 前言 第十五蓝桥杯国赛落幕已有十天,是时候总结一下,这个专栏也将结束。虽然并没有取得预期的结果,但故事结尾并不总是美满的。下面是赛前练习的第十二届国赛的代码。 一、问题重述 二、主函数 完整…

大数据快速使用Kerberos认证集群

一、创建安全集群并登录其Manager 创建安全集群,开启“Kerberos认证“参数开关,并配置“密码“、“确认密码“参数。该密码用于登录Manager,请妥善保管。 登录MRS管理控制台页面。 单击“集群列表“,在“现有集群“列表&#xf…

虚拟机调用摄像头设备一直 select timeout问题的解决

在VMware里面调用v4l2-ctl捕获图像,或者opencv的VideoCapture(0)捕获图像,或者直接调用v4l2的函数,在streamon后,调用select读取数据,均会一直提示select timeout的问题,大概率是由于USB版本的兼容性造成的…

fs.1.10 ON rockylinux8 docker镜像制作

概述 freeswitch是一款简单好用的VOIP开源软交换平台。 rockylinux docker上编译安装fs1.10版本的流程记录。 环境 docker engine:Version 24.0.6 rockylinux docker:8 freeswitch:v1.10.7 手动模式 rockylinux准备 docker hub拉取r…

AI智能体做高考志愿填报分析

关注公众号,赠送AI/Python/Linux资料,对AI智能体有兴趣的朋友也可以添加一起交流 高考正在进行时,学生焦虑考试,家长们焦虑的则是高考志愿怎么填。毕竟一个好的学校,好的专业是进入社会的第一个敲门砖 你看张雪峰老师…

2024.6.10学习记录

1、代码随想录二刷 2、项目难点 review 3、计组复习

RabbitMQ-工作模式(Topics模式RPC模式Publisher Confirms模式)

文章目录 Topics模式topic代码示例 RPC模式客户端界面回调队列关联ID总结RPC代码示例 Publisher Confirms模式概述在通道上启用发布者确认单独发布消息批量发布消息异步处理发布者确认总结总体代码示例 更多相关内容可查看 Topics模式 在Topics中,发送的消息不能具…