当前位置: 首页 > news >正文

OpenHarmony(鸿蒙南向开发)——小型系统内核(LiteOS-A)【文件系统】上

往期知识点记录:

  • 鸿蒙(HarmonyOS)应用层开发(北向)知识点汇总
  • 鸿蒙(OpenHarmony)南向开发保姆级知识点汇总~
  • 子系统开发内核
  • 轻量系统内核(LiteOS-M)
  • 轻量系统内核(LiteOS-M)【中断管理】
  • 轻量系统内核(LiteOS-M)【任务管理】
  • 轻量系统内核(LiteOS-M)【内存管理】
  • 轻量系统内核(LiteOS-M)【内核通信机制】
  • 轻量系统内核(LiteOS-M)【时间管理】
  • 轻量系统内核(LiteOS-M)【扩展组件】
  • 轻量系统内核(LiteOS-M)【内存调测】
  • 轻量系统内核(LiteOS-M)【异常调测】
  • 轻量系统内核(LiteOS-M)【Trace调测】
  • 轻量系统内核(LiteOS-M)【LMS调测】
  • 轻量系统内核(LiteOS-M)【SHELL】
  • 小型系统内核(LiteOS-A)【概述】
  • 小型系统内核(LiteOS-A)【内核启动】
  • 小型系统内核(LiteOS-A)【中断及异常处理】
  • 标准系统内核(Linux)【New IP内核协议栈】
  • 标准系统内核(Linux)【内核增强特性 > 任务调度】
  • 持续更新中……

虚拟文件系统

基本概念

VFS(Virtual File System)是文件系统的虚拟层,它不是一个实际的文件系统,而是一个异构文件系统之上的软件粘合层,为用户提供统一的类Unix文件操作接口。由于不同类型的文件系统接口不统一,若系统中有多个文件系统类型,访问不同的文件系统就需要使用不同的非标准接口。而通过在系统中添加VFS层,提供统一的抽象接口,屏蔽了底层异构类型的文件系统的差异,使得访问文件系统的系统调用不用关心底层的存储介质和文件系统类型,提高开发效率。

OpenHarmony内核中,VFS框架是通过在内存中的树结构来实现的,树的每个结点都是一个Vnode结构体,父子结点的关系以PathCache结构体保存。VFS最主要的两个功能是:

  • 查找节点。

  • 统一调用(标准)。

运行机制

当前,VFS层主要通过函数指针,实现对不同文件系统类型调用不同接口实现标准接口功能;通过Vnode与PathCache机制,提升路径搜索以及文件访问的性能;通过挂载点管理进行分区管理;通过FD管理进行进程间FD隔离等。下面将对这些机制进行简要说明。

  1. 文件系统操作函数指针:VFS层通过函数指针的形式,将统一调用按照不同的文件系统类型,分发到不同文件系统中进行底层操作。各文件系统的各自实现一套Vnode操作、挂载点操作以及文件操作接口,并以函数指针结构体的形式存储于对应Vnode、挂载点、File结构体中,实现VFS层对下访问。

  2. Vnode:Vnode是具体文件或目录在VFS层的抽象封装,它屏蔽了不同文件系统的差异,实现资源的统一管理。Vnode节点主要有以下几种类型:

    • 挂载点:挂载具体文件系统,如/、/storage
    • 设备节点:/dev目录下的节点,对应于一个设备,如/dev/mmcblk0
    • 文件/目录节点:对应于具体文件系统中的文件/目录,如/bin/init

Vnode通过哈希以及LRU机制进行管理。当系统启动后,对文件或目录的访问会优先从哈希链表中查找Vnode缓存,若缓存没有命中,则并从对应文件系统中搜索目标文件或目录,创建并缓存对应的Vnode。当Vnode缓存数量达到上限时,将淘汰长时间未访问的Vnode,其中挂载点Vnode与设备节点Vnode不参与淘汰。当前系统中Vnode的规格默认为512,该规格可以通过LOSCFG_MAX_VNODE_SIZE进行配置。Vnode数量过大,会造成较大的内存占用;Vnode数量过少,则会造成搜索性能下降。下图展示了Vnode的创建流程。

图1 Vnode创建流程

  1. PathCache:PathCache是路径缓存,它通过哈希表存储,利用父节点Vnode的地址和子节点的文件名,可以从PathCache中快速查找到子节点对应的Vnode。下图展示了文件/目录的查找流程。

图2 文件查找流程

  1. PageCache:PageCache是内核中文件的缓存。当前PageCache仅支持缓存二进制文件,在初次访问文件时通过mmap映射到内存中,下次再访问时,直接从PageCache中读取,可以提升对同一个文件的读写速度。另外基于PageCache可实现以文件为基底的进程间通信。

  2. fd管理:Fd(File Descriptor)是描述一个打开的文件/目录的描述符。当前OpenHarmony内核中,fd总规格为896,分为三种类型:

    • 普通文件描述符,系统总规格为512。
    • Socket描述符,系统总规格为128。
    • 消息队列描述符,系统总规格为256。

当前OpenHarmony内核中,对不同进程中的fd进行隔离,即进程只能访问本进程的fd,所有进程的fd映射到全局fd表中进行统一分配管理。进程的文件描述符最多有256个。

  1. 挂载点管理:当前OpenHarmony内核中,对系统中所有挂载点通过链表进行统一管理。挂载点结构体中,记录了该挂载分区内的所有Vnode。当分区卸载时,会释放分区内的所有Vnode。

开发指导

接口说明

当前文件系统支持的接口如下表所示,表格中的“×”代表对应文件系统不支持该接口。

表1 文件操作

接口名称功能FATJFFS2NFSTMPFSPROCFS
open打开文件
read/pread/readv/preadv读取文件
write/pwrite/writev/pwritev写入文件
lseek设置文件偏移×
close关闭文件
unlink删除文件×
fstat查询文件信息
fallocate预分配大小××××
truncate文件截断××
link创建硬链接××××
symlink创建软链接×××
readlink读取软链接×××
dup复制文件句柄
fsync文件内容刷入设备××××
ioctl设备控制××××
fcntl文件控制操作
mkdir创建目录×
opendir打开目录
readdir读取目录
closedir关闭目录
telldir获取目录偏移
seekdir设置目录偏移
rewinddir重置目录偏移×
scandir读取目录数据
rmdir删除目录×
chdir切换当前路径
getcwd获取当前路径
realpath相对/绝对路径转换
rename文件/目录重命名×
chmod修改文件/目录属性×××
chown修改文件/目录所有者×××
stat/lstat查询文件/目录信息
access查询文件/目录访问权限
mount挂载分区
umount卸载分区×
statfs查询挂载分区信息
format格式化分区××××
sync分区内容刷入设备××××

表2 目录操作

接口名称功能FATJFFS2NFSTMPFSPROCFS
mkdir创建目录×
opendir打开目录
readdir读取目录
closedir关闭目录
telldir获取目录偏移
seekdir设置目录偏移
rewinddir重置目录偏移×
scandir读取目录数据
rmdir删除目录×
chdir切换当前路径
getcwd获取当前路径
realpath相对/绝对路径转换
rename文件/目录重命名×
chmod修改文件/目录属性×××
chown修改文件/目录所有者×××
stat/lstat查询文件/目录信息
access查询文件/目录访问权限
mount挂载分区
umount卸载分区×
statfs查询挂载分区信息
format格式化分区××××
sync分区内容刷入设备××××

表3 分区操作

接口名称功能FATJFFS2NFSTMPFSPROCFS
mount挂载分区
umount卸载分区×
statfs查询挂载分区信息
format格式化分区××××
sync分区内容刷入设备××××

开发流程

文件系统的主要开发流程包括挂载/卸载分区,以及系列目录/文件操作。

编程实例

代码实现如下:

#include <stdio.h>
#include <string.h>
#include "sys/stat.h"
#include "fcntl.h"
#include "unistd.h"#define LOS_OK 0
#define LOS_NOK -1int main(void)
{int ret;int fd = -1;ssize_t len;off_t off;char mntName[20] = "/storage";char devName[20] = "/dev/mmcblk0p0";char dirName[20] = "/storage/test";char fileName[20] = "/storage/test/file.txt";char writeBuf[20] = "Hello OpenHarmony!";char readBuf[20] = {0};/* 创建目录“/storage” */ret = mkdir(mntName, 0777);if (ret != LOS_OK) {printf("mkdir failed.\n");return LOS_NOK;}/* 挂载设备“/dev/mmcblk0p0”到“/storage” */ret = mount(devName, mntName, "vfat", 0, 0);if (ret != LOS_OK) {printf("mount failed.\n");return LOS_NOK;}/* 创建目录“/storage/test” */ret = mkdir(dirName, 0777);if (ret != LOS_OK) {printf("mkdir failed.\n");return LOS_NOK;}/* 创建可读写文件“/storage/test/file.txt” */fd = open(fileName, O_RDWR | O_CREAT, 0777);if (fd < 0) {printf("open file failed.\n");return LOS_NOK;}/* 将writeBuf中的内容写入文件 */len = write(fd, writeBuf, strlen(writeBuf));if (len != strlen(writeBuf)) {printf("write file failed.\n");return LOS_NOK;}/* 将文件内容刷入存储设备中 */ret = fsync(fd);if (ret != LOS_OK) {printf("fsync failed.\n");return LOS_NOK;}/* 将读写指针偏移至文件头 */off = lseek(fd, 0, SEEK_SET);if (off != 0) {printf("lseek failed.\n");return LOS_NOK;}/* 将文件内容读出至readBuf中,读取长度为readBuf大小 */len = read(fd, readBuf, sizeof(readBuf));if (len != strlen(readBuf)) {printf("read file failed.\n");return LOS_NOK;}printf("%s\n", readBuf);/* 关闭文件 */ret = close(fd);if (ret != LOS_OK) {printf("close failed.\n");return LOS_NOK;}/* 删除文件“/storage/test/file.txt” */ret = unlink(fileName);if (ret != LOS_OK) {printf("unlink failed.\n");return LOS_NOK;}/* 删除目录“/storage/test” */ret = rmdir(dirName);if (ret != LOS_OK) {printf("rmdir failed.\n");return LOS_NOK;}/* 卸载分区“/storage” */ret = umount(mntName);if (ret != LOS_OK) {printf("umount failed.\n");return LOS_NOK;}/* 删除目录“/storage” */ret = rmdir(mntName);if (ret != LOS_OK) {printf("rmdir failed.\n");return LOS_NOK;}return LOS_OK;
}

结果验证

编译运行得到的结果为:

Hello OpenHarmony!

支持的文件系统

FAT

基本概念

FAT文件系统是File Allocation Table(文件配置表)的简称,主要包括DBR区、FAT区、DATA区三个区域。其中,FAT区各个表项记录存储设备中对应簇的信息,包括簇是否被使用、文件下一个簇的编号、是否文件结尾等。FAT文件系统有FAT12、FAT16、FAT32等多种格式,其中,12、16、32表示对应格式中FAT表项的比特数,它们同时也限制了文件系统中的最大文件大小。FAT文件系统支持多种介质,特别在可移动存储介质(U盘、SD卡、移动硬盘等)上广泛使用,使嵌入式设备和Windows、Linux等桌面系统保持很好的兼容性,方便用户管理操作文件。

OpenHarmony内核支持FAT12、FAT16与FAT32三种格式的FAT文件系统,具有代码量小、资源占用小、可裁切、支持多种物理介质等特性,并且与Windows、Linux等系统保持兼容,支持多设备、多分区识别等功能。OpenHarmony内核支持硬盘多分区,可以在主分区以及逻辑分区上创建FAT文件系统。

运行机制

FAT文件系统设计与物理布局的相关文档在互联网上非常丰富,请开发者自行搜索查看。

OpenHarmony LiteOS-A内核通过Bcache提升FAT文件系统性能,Bcache是block cache的简称。当发生读写时,Bcache会缓存读写扇区附近的扇区,以减少I/O次数,提高性能。Bcache的基本缓存单位为block,每个block大小一致(默认有28个block,每个block缓存64个扇区的数据)。当Bcache脏块率(脏扇区数/总扇区数)达到阈值时,会触发写回;如果脏块率未达到阈值,则不会将缓存数据写回磁盘。如果需要保证数据写回,开发者应当调用sync和fsync触发写回。FAT文件系统的部分接口也会触发写回操作(如close、umount等),但开发者不应当基于这些接口触发写回。

开发指导

开发流程

基本使用流程为挂载→操作→卸载。

SD卡或MMC的设备名为mmcblk[x]p[y],文件系统类型为“vfat”。

示例:

mount("/dev/mmcblk0p0", "/mnt", "vfat", 0, NULL);

说明:

  • FAT文件系统中,单个文件不能大于4 GiB。

  • 当有两个SD卡插槽时,卡0和卡1不固定,先插上的为卡0,后插上的为卡1。

  • 当多分区功能打开,存在多分区的情况下,卡0注册的设备节点/dev/mmcblk0(主设备)和/dev/mmcblk0p0(次设备)是同一个设备,禁止对主设备进行操作。

  • 为避免SD卡使用异常或内存泄漏,SD卡使用过程中拔卡,用户必须先关闭正处于打开状态的文件和目录,并且卸载挂载节点。

  • 在format操作之前,需要首先umount挂载点。

  • 当Bcache功能生效时,需要注意:

    • 当mount函数的入参为MS_NOSYNC时,FAT不会主动将cache的内容写回存储器件。FAT的如下接口(open、close、 unlink、rename、mkdir、rmdir、truncate)不会自动进行sync操作,速度可以提升,但是需要上层主动调用sync来进行数据同步,否则可能会数据丢失。

    • Bcache有定时写回功能。在menuconfig中开启LOSCFG_FS_FAT_CACHE_SYNC_THREAD选项,打开后系统会创建一个任务定时写回Bcache中的数据,默认每隔5秒检查Bcache中脏数据块比例,超过80%时进行sync操作,将Bcache中的脏数据全部写回磁盘。任务优先级、刷新时间间隔以及脏数据块比例的阈值可分别通过接口LOS_SetSyncThreadPrio、 LOS_SetSyncThreadInterval和LOS_SetDirtyRatioThreshold设置。

    • 当前cache的默认大小为28个块,每个块64个扇区。

JFFS2

基本概念

JFFS2是Journalling Flash File System Version 2(日志文件系统)的缩写,是针对MTD设备的日志型文件系统。

OpenHarmony内核的JFFS2主要应用于NOR FLASH闪存,其特点是:可读写、支持数据压缩、提供了崩溃/掉电安全保护、提供“写平衡”支持等。闪存与磁盘介质有许多差异,直接将磁盘文件系统运行在闪存设备上,会导致性能和安全问题。为解决这一问题,需要实现一个特别针对闪存的文件系统,JFFS2就是这样一种文件系统。

运行机制

关于JFFS2文件系统的在存储设备上的实际物理布局,及文件系统本身的规格说明,请参考JFFS2的 官方规格说明文档。

这里仅列举几个对开发者和使用者会有一定影响的JFFS2的重要机制/特征:

  1. Mount机制及速度问题:按照JFFS2的设计,所有的文件会按照一定的规则,切分成大小不等的节点,依次存储到flash设备上。在mount流程中,需要获取到所有的这些节点信息并缓存到内存里。因此,mount速度和flash设备的大小和文件数量的多少成线性比例关系。这是JFFS2的原生设计问题,对于mount速度非常介意的用户,可以在内核编译时开启“Enable JFFS2 SUMMARY”选项,可以极大提升mount的速度。这个选项的原理是将mount需要的信息提前存储到flash上,在mount时读取并解析这块内容,使得mount的速度变得相对恒定。这个实际是空间换时间的做法,会消耗8%左右的额外空间。

  2. 写平衡的支持:由于flash设备的物理属性,读写都只能基于某个特定大小的“块”进行,为了防止某些特定的块磨损过于严重,在JFFS2中需要对写入的块进行“平衡”的管理,保证所有的块的写入次数都是相对平均的,进而保证flash设备的整体寿命。

  3. GC(garbage collection)机制:在JFFS2里发生删除动作,实际的物理空间并不会立即释放,而是由独立的GC线程来做空间整理和搬移等GC动作,和所有的GC机制一样,在JFFS2里的GC会对瞬时的读写性能有一定影响。另外,为了有空间能被用来做空间整理,JFFS2会对每个分区预留3块左右的空间,这个空间是用户不可见的。

  4. 压缩机制:当前使用的JFFS2,底层会自动的在每次读/写时进行解压/压缩动作,实际IO的大小和用户请求读写的大小并不会一样。特别在写入时,不能通过写入大小来和flash剩余空间的大小来预估写入一定会成功或者失败。

  5. 硬链接机制:JFFS2支持硬链接,底层实际占用的物理空间是一份,对于同一个文件的多个硬连接,并不会增加空间的占用;反之,只有当删除了所有的硬链接时,实际物理空间才会被释放。

开发指导

对于基于JFFS2和nor flash的开发,总体而言,与其他文件系统非常相似,因为都有VFS层来屏蔽了具体文件系统的差异,对外接口体现也都是标准的POSIX接口。

对于整个裸nor flash设备而言,没有集中的地方来管理和记录分区的信息。因此,需要通过其他的配置方式来传递这部分信息(当前使用的方式是在烧写镜像的时候,使用bootargs参数配置的),然后在代码中调用相应的接口来添加分区,再进行挂载动作。

制作JFFS2文件系统镜像

使用mkfs.jffs2工具,制作镜像默认命令如下。页大小默认为4KiB,eraseblock大小默认64KiB。若实际参数与下面不同时,修改相应参数。

./mkfs.jffs2 -d rootfs/ -o rootfs.jffs2

表1 指令含义表(更详细的介绍可以通过mkfs.jffs2 --help来查看)

指令含义
-s页大小,不指定默认为4KiB
-eeraseblock大小,不指定默认为64KiB
-p镜像大小。在镜像文件后面,用0xFF填充至指定大小,不指定则用0xFF填充至eraseblock对齐。
-d要制作成文件系统镜像的源目录
-o要制成的镜像名称

挂载JFFS2分区

调用int mount(const char *source, const char *target, const char *filesystemtype, unsigned long mountflags, const void *data)函数实现设备节点和挂载点的挂载。

该函数有五个参数,第一个参数const char *source,表示设备节点,第二个参数const char *target表示挂载点。第三个参数 const char *filesystemtype,表示文件系统类型。

最后两个参数unsigned long mountflags和const void *data表示挂载标志和数据,默认为0和NULL;这一操作也可以在Shell中使用mount命令实现,最后两个参数不需要用户给出。

运行命令:

OHOS # mount /dev/spinorblk1 /jffs1 jffs2

将从串口得到如下回应信息,表明挂载成功。

OHOS # mount /dev/spinorblk1 /jffs1 jffs2
mount OK

挂载成功后,用户就能对norflash进行读写操作。

卸载JFFS2分区

调用int umount(const char *target)函数卸载分区,只需要正确给出挂载点即可。

运行命令:

OHOS # umount /jffs1

将从串口得到如下回应信息,表明卸载成功。

OHOS # umount /jffs1
umount ok

NFS

基本概念

NFS是Network File System(网络文件系统)的缩写。它最大的功能是可以通过网络,让不同的机器、不同的操作系统彼此分享其他用户的文件。因此,用户可以简单地将它看做是一个文件系统服务,在一定程度上相当于Windows环境下的共享文件夹。

运行机制

OpenHarmony LiteOS-A内核的NFS文件系统指的是NFS的客户端,NFS客户端能够将远程的NFS服务端分享的目录挂载到本地的机器中,运行程序和共享文件,但不占用当前系统的存储空间,在本地端的机器看起来,远程服务端的目录就好像是自己的一个磁盘一样。

开发指导

  1. 搭建NFS服务器

这里以Ubuntu操作系统为例,说明服务器端设置步骤。

*   安装NFS服务器软件。

设置好Ubuntu系统的下载源,保证网络连接好的情况下执行:

        sudo apt-get install nfs-kernel-server
*   创建用于挂载的目录并设置完全权限
        mkdir -p /home/sqbin/nfssudo chmod 777 /home/sqbin/nfs
  • 设置和启动NFS server。

修改NFS配置文件/etc/exports,添加如下一行:

        /home/sqbin/nfs *(rw,no_root_squash,async)

其中/home/sqbin/nfs是NFS共享的根目录。

执行以下命令启动NFS server:

        sudo /etc/init.d/nfs-kernel-server start

执行以下命令重启NFS server:

        sudo /etc/init.d/nfs-kernel-server restart
  1. 设置单板为NFS客户端

本指导中的NFS客户端指运行OpenHarmony内核的设备。

*   硬件连接设置。

OpenHarmony内核设备连接到NFS服务器的网络。设置两者IP,使其处于同一网段。比如,设置NFS服务器的IP为10.67.212.178/24,设置OpenHarmony内核设备IP为 10.67.212.3/24,注意:此IP为内网私有IP地址,用户使用时有差异,以用户实际IP为准。

OpenHarmony内核设备上的IP信息可通过ifconfig命令查看。

*   启动网络,确保单板到NFS服务器之间的网络通畅。

启动以太网或者其他类型网络,使用ping命令检查到服务器的网络是否通畅。

        OHOS # ping 10.67.212.178[0]Reply from 10.67.212.178: time=1ms TTL=63[1]Reply from 10.67.212.178: time=0ms TTL=63[2]Reply from 10.67.212.178: time=1ms TTL=63[3]Reply from 10.67.212.178: time=1ms TTL=63--- 10.67.212.178 ping statistics ---packets transmitted, 4 received, 0 loss

客户端NFS初始化,运行命令:

    OHOS # mkdir /nfsOHOS # mount 10.67.212.178:/home/sqbin/nfs /nfs nfs 1011 1000

将从串口得到如下回应信息,表明初始化NFS客户端成功。

    OHOS # mount 10.67.212.178:/home/sqbin/nfs /nfs nfs 1011 1000Mount nfs on 10.67.212.178:/home/sqbin/nfs, uid:1011, gid:1000Mount nfs finished.

该命令将服务器10.67.212.178上的/home/sqbin/nfs目录挂载到OpenHarmony内核设备上的/nfs上。

说明: 本例默认nfs server已经配置可用,即示例中服务器10.67.212.178上的/home/sqbin/nfs已配置可访问。

mount命令的格式为:

mount <SERVER_IP:SERVER_PATH> <CLIENT_PATH> nfs

其中“SERVER_IP”表示服务器的IP地址;“SERVER_PATH”表示服务器端NFS共享目录路径;“CLIENT_PATH”表示设备上的NFS路径,“nfs”表示客户端要挂载的路径,可以根据自己需要替换。

如果不想有NFS访问权限限制,可以在Linux命令行将NFS根目录权限设置成777:

chmod -R 777 /home/sqbin/nfs

至此,NFS客户端设置完毕。NFS文件系统已成功挂载。

  1. 利用NFS共享文件

在NFS服务器下新建目录dir,并保存。在OpenHarmony内核下运行ls命令:

    OHOS # ls /nfs

则可从串口得到如下回应:

    OHOS # ls /nfs Directory /nfs:                 drwxr-xr-x 0        u:0     g:0     dir

可见,刚刚在NFS服务器上新建的dir目录已同步到客户端(OpenHarmony内核系统)的/nfs目录,两者保持同步。

同样地,在客户端(OpenHarmony内核系统)上创建文件和目录,在NFS服务器上也可以访问,读者可自行体验。

说明: 目前,NFS客户端仅支持NFS v3部分规范要求,因此对于规范支持不全的服务器,无法完全兼容。在开发测试过程中,建议使用Linux的NFS server,其对NFS支持很完善。

Ramfs

基本概念

RAMFS是一个可动态调整大小的基于RAM的文件系统。RAMFS没有后备存储源。向RAMFS中进行的文件写操作也会分配目录项和页缓存,但是数据并不写回到任何其他存储介质上,掉电后数据丢失。

运行机制

RAMFS文件系统把所有的文件都放在 RAM 中,所以读/写操作发生在RAM中,可以用RAMFS来存储一些临时性或经常要修改的数据,例如/tmp和/var目录,这样既避免了对存储器的读写损耗,也提高了数据读写速度。

开发指导

挂载:

mount(NULL, "/dev/shm", "ramfs", 0, NULL)

创建目录:

mkdir(pathname, mode)

创建文件:

open(pathname, O_NONBLOCK | O_CREAT | O_RDWR, mode)

读取目录:

dir = opendir(pathname) 
ptr = readdir(dir)
closedir(dir)

删除文件:

unlink(pathname)

删除目录:

rmdir(pathname)

去挂载:

umount("/dev/shm")

注意:

  • RAMFS只能挂载一次,一次挂载成功后,后面不能继续挂载到其他目录。

  • RAMFS属于调测功能,默认配置为关闭,正式产品中不要使用该功能。

Procfs

基本概念

procfs是进程文件系统的简称,是一种虚拟文件系统,他用文件的形式,展示进程或其他系统信息。相比调用接口的方式获取信息,以文件操作的方式获取系统信息更为方便。

运行机制

OpenHarmony内核中,procfs在开机时会自动挂载到/proc目录下,仅支持内核模块创建文件节点来提供查询服务。

开发指导

procfs文件的创建无法使用一般的文件系统接口,需要使用ProcMkdir接口创建目录,使用CreateProcEntry接口创建文件。文件节点功能的开发就是实现read和write函数的钩子挂到CreateProcEntry创建的文件中。当用户使用读写procfs的文件时,就会调用到钩子函数来实现自定义的功能。

编程实例

下面我们以创建/proc/hello/world文件为例,实现如下功能:

1.在/proc/hello/world位置创建一个文件

2.当读文件内容时,返回"HelloWorld!"

3.当写文件内容时,打印写入的内容

#include "proc_fs.h"static int TestRead(struct SeqBuf *buf, void *arg)
{LosBufPrintf(buf, "Hello World!\n"); /* 将数据打印到buffer中,这个buffer中的数据会返回到read的结果中 */return 0;
}static int TestWrite(struct ProcFile *pf, const char *buffer, size_t buflen, loff_t *ppos)
{if ((buffer == NULL) || (buflen <= 0)) {return -EINVAL;}PRINTK("your input is: %s\n", buffer); /* 注意和上面的read接口区别,这是对write接口输入命令的反馈,这个打印只会打印到控制台 */return buflen;
}
static const struct ProcFileOperations HELLO_WORLD_OPS = {.read = TestRead,.write = TestWrite,
};void HelloWorldInit(void)
{/* 创建hello目录 */struct ProcDirEntry *dir = ProcMkdir("hello", NULL);if (dir == NULL) {PRINT_ERR("create dir failed!\n");return;}/* 创建world文件 */struct ProcDirEntry *entry = CreateProcEntry("world", 0, dir);if (entry == NULL) {PRINT_ERR("create entry failed!\n");return;}/* 将自定义的read和write钩子挂到文件中 */entry->procFileOps = &HELLO_WORLD_OPS;
}

结果验证

启动后在shell输入如下命令

OHOS # cat /proc/hello/world
OHOS # Hello World!
OHOS # echo "yo" > /proc/hello/world
OHOS # your input is: yo

经常有很多小伙伴抱怨说:不知道学习鸿蒙开发哪些技术?不知道需要重点掌握哪些鸿蒙应用开发知识点?

为了能够帮助到大家能够有规划的学习,这里特别整理了一套纯血版鸿蒙(HarmonyOS Next)全栈开发技术的学习路线,包含了鸿蒙开发必掌握的核心知识要点,内容有(ArkTS、ArkUI开发组件、Stage模型、多端部署、分布式应用开发、WebGL、元服务、OpenHarmony多媒体技术、Napi组件、OpenHarmony内核、OpenHarmony驱动开发、系统定制移植等等)鸿蒙(HarmonyOS NEXT)技术知识点。

在这里插入图片描述

《鸿蒙 (Harmony OS)开发学习手册》(共计892页):https://gitcode.com/HarmonyOS_MN/733GH/overview

如何快速入门?

1.基本概念
2.构建第一个ArkTS应用
3.……

鸿蒙开发面试真题(含参考答案):https://gitcode.com/HarmonyOS_MN/733GH/overview

在这里插入图片描述

OpenHarmony 开发环境搭建

图片

《OpenHarmony源码解析》:

  • 搭建开发环境
  • Windows 开发环境的搭建
  • Ubuntu 开发环境搭建
  • Linux 与 Windows 之间的文件共享
  • ……
  • 系统架构分析
  • 构建子系统
  • 启动流程
  • 子系统
  • 分布式任务调度子系统
  • 分布式通信子系统
  • 驱动子系统
  • ……

图片

OpenHarmony 设备开发学习手册:https://gitcode.com/HarmonyOS_MN/733GH/overview

图片
在这里插入图片描述

相关文章:

OpenHarmony(鸿蒙南向开发)——小型系统内核(LiteOS-A)【文件系统】上

往期知识点记录&#xff1a; 鸿蒙&#xff08;HarmonyOS&#xff09;应用层开发&#xff08;北向&#xff09;知识点汇总 鸿蒙&#xff08;OpenHarmony&#xff09;南向开发保姆级知识点汇总~ 子系统开发内核 轻量系统内核&#xff08;LiteOS-M&#xff09; 轻量系统内核&#…...

NISP 一级 | 8.4 《网络安全法》

关注这个证书的其他相关笔记&#xff1a;NISP 一级 —— 考证笔记合集-CSDN博客 2017 年 6 月 1 日&#xff0c;《中华人民共和国网终安全法》&#xff08;以下简称《网终安全法》&#xff09;正式实施。这是我国第一部全面规范网络空间安全管理方面问题的基础性法律&#xff0…...

实现人体模型可点击

简化需求&#xff1a;实现项目内嵌人体模型&#xff0c;实现点击不同部位弹出部位名称 一&#xff1a;优先3d&#xff0c; 方案&#xff1a;基于three.js&#xff0c;.gltf格式模型&#xff0c;vue3 缺点&#xff1a;合适且免费的3d模型找不到&#xff0c;因为项目对部位有要…...

C++ | Leetcode C++题解之第429题N叉树的层序遍历

题目&#xff1a; 题解&#xff1a; class Solution { public:vector<vector<int>> levelOrder(Node* root) {if (!root) {return {};}vector<vector<int>> ans;queue<Node*> q;q.push(root);while (!q.empty()) {int cnt q.size();vector<…...

Pandas简介

Pandas 是一个流行的开源数据分析库&#xff0c;它是基于 NumPy 构建的&#xff0c;为 Python 编程语言提供了高性能、易用的数据结构和数据分析工具。Pandas 主要用于数据清洗、数据转换、数据分析等任务&#xff0c;使得数据处理工作变得更加高效和便捷。 Pandas 的两个主要…...

Python | Leetcode Python题解之第430题扁平化多级双向链表

题目&#xff1a; 题解&#xff1a; class Solution:def flatten(self, head: "Node") -> "Node":def dfs(node: "Node") -> "Node":cur node# 记录链表的最后一个节点last Nonewhile cur:nxt cur.next# 如果有子节点&#…...

机器人机构、制造

简单整理一下&#xff0c;在学习了一些运动学和动力学之类的东西&#xff0c;简单的整合了一些常用的机械结构和图片。 1.电机&#xff1a; 市面上的电机有&#xff1a;直流电机&#xff0c;交流电机&#xff0c;舵机&#xff0c;步进电机&#xff0c;电缸&#xff0c;无刷电…...

《拿下奇怪的前端报错》:nvm不可用报错`GLIBC_2.27‘‘GLIBCXX_3.4.20‘not Found?+ 使用docker构建多个前端项目实践

有些前端的小伙伴可能会好奇&#xff0c;nvm是什么&#xff1f;这里接简单介绍下&#xff0c;它是一个Nodejs版本管理工具。为什么需要它呢&#xff1f;当然是需要多个Nodejs版本的时候&#xff0c;那什么时候需要多个Nodejs版本&#xff1f;那肯定是在有点年头的公司了&#x…...

5.《DevOps》系列K8S部署CICD流水线之K8S通过Yaml部署GitLab

架构 服务器IP服务名称硬件配置192.168.1.100k8s-master8核、16G、120G192.168.1.101k8s-node18核、16G、120G192.168.1.102k8s-node28核、16G、120G192.168.1.103nfs2核、4G、500G操作系统:Rocky9.3 后续通过K8S部署Jenkins NFS的SC创建参考:2.《DevOps》系列K8S部署CICD流…...

[SAP ABAP] 创建数据库视图和维护视图

数据准备 学校表(ZDBT_SCH_437) 学生表(ZDBT_STU_437) 学校表(ZDBT_SCH_437)与学生表(ZDBT_STU_437)字段 学校表(ZDBT_SCH_437)与学生表(ZDBT_STU_437)行数据明细 1.创建数据库视图 使用SE11创建数据库视图 填写视图名称ZV_DATABASEV_437&#xff0c;点击创建按钮 选择数据库视…...

【最快最简单的排序 —— 桶排序算法】

最快最简单的排序 —— 桶排序算法 桶排序是一种排序算法&#xff0c;其工作原理是将数据分到有限数量的桶子里&#xff0c;然后对每个桶内的元素进行单独排序&#xff0c;最后依次把各个桶中的记录列出来。桶排序的效率取决于映射函数的选择和桶的数量。 桶排序适用于数据分…...

AI时代,服务器厂商能否打破薄利的命运?

文&#xff5c;刘俊宏 编&#xff5c;王一粟 AI大模型正在引发新一轮的“算力焦渴”。 近日&#xff0c;OpenAI刚发布的o1大模型再次刷新了大模型能力的上限。对比上一次迭代的版本&#xff0c;o1的推理能力全方位“吊打”了GPT-4o。更优秀的能力&#xff0c;来自与o1将思维…...

2024年9月python二级易错题和难题大全(附详细解析)(二)

2024年9月python二级易错题和难题大全(附详细解析)(二) 第1题第2题第3题第4题第5题第6题第7题第8题第9题第10题第11题第12题第13题第14题第15题第16题第17题第18题第19题第20题第1题 1、以下代码的输出结果是() x = 12 + 3 * ((5 * 8) - 14) // 6 print(x) A、25.0 B、6…...

4.结构型设计模式 - 第1回:引言与适配器模式 (Adapter Pattern) ——设计模式入门系列

一、引言 在现代软件开发中&#xff0c;设计模式是帮助我们解决复杂问题的工具&#xff0c;它们提供了在常见场景下重用已验证解决方案的途径。而结构型设计模式主要关注类与对象之间的组合方式&#xff0c;旨在通过增强灵活性和降低耦合度来改进代码的结构。 本次讨论的是结…...

解决mybatis plus 中 FastjsonTypeHandler无法正确反序列化List类型的问题

由于是根据自动映射类型&#xff0c;我们设置的字段类型是List 也就是反序列化的时候也只是用 FastjsonTypeHandler中的 Override protected Object parse(String json) { return JSON.parseObject(json, type); } 反序列化方法&#xff0c;这是type为List 反序列后我们并没…...

MacOS安装homebrew,jEnv,多版本JDK

1 安装homebrew homebrew官网 根据官网提示&#xff0c;运行安装命令 /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"安装后&#xff0c;bash会提示执行两条命令 (echo; echo eval "$(/opt/homebrew/b…...

【HTTP】认识 URL 和 URL encode

文章目录 认识 URLURL 基本格式**带层次的文件路径****查询字符串****片段标识符** URL encode 认识 URL 计算机中非常重要的概念&#xff0c;并不仅仅是在 HTTP 中使用。用来描述一个网络资源所处的位置&#xff0c;全称“唯一资源定位符” URI 是“唯一资源标识符“严格的说…...

【AI学习笔记】初学机器学习西瓜书概要记录(二)常用的机器学习方法篇

初学机器学习西瓜书的概要记录&#xff08;一&#xff09;机器学习基础知识篇(已完结) 初学机器学习西瓜书的概要记录&#xff08;二&#xff09;常用的机器学习方法篇(持续更新) 初学机器学习西瓜书的概要记录&#xff08;三&#xff09;进阶知识篇(待更) 文字公式撰写不易&am…...

[SDX35+WCN6856]SDX35 + WCN6856 默认增加打包wifi配置hostapd_24g.conf和hostapd_5g.conf操作方法

SDX35 SDX35介绍 SDX35设备是一种多模调制解调器芯片,支持 4G/5G sub-6 技术。它是一个4nm芯片专为实现卓越的性能和能效而设计。它包括一个 1.9 GHz Cortex-A7 应用处理器。 SDX35主要特性 ■ 3GPP Rel. 17 with 5G Reduced Capability (RedCap) support. Backward compati…...

【iOS】OC高级编程 iOS多线程与内存管理阅读笔记——自动引用计数

文章目录 什么是自动引用计数 内存管理/引用计数 概要 内存管理的思考方式 自己生成的对象&#xff0c;自己所持有 非自己生成的对象&#xff0c;自己也能持有 不再需要自己持有的对象时释放 无法释放非自己持有的对象 什么是自动引用计数 自动引用计数&#xff08;AR…...

网络安全-LD_PRELOAD,请求劫持

目录 一、环境 二、开始做题 三、总结原理 四、如何防护 一、环境 我们这里用蚁剑自带的靶场第一关来解释 docker制作一下即可 二、开始做题 首先环境内很明显给我们已经写好了webshell 同样我们也可以访问到 我们使用这个蚁剑把这个webshell连上 我们发现命令不能执行&am…...

GO入门之值传递于引用(指针、内存地址)传递扫盲

GO入门之值传递于引用&#xff08;指针、内存地址&#xff09;传递扫盲 Go 语言中&#xff0c;值传递和引用&#xff08;指针&#xff09;传递是两个关键的概念。通过案例可以很好地展示两者的区别。 值传递与引用传递的区别&#xff1a; 值传递&#xff1a;传递的是变量的副…...

【渗透测试】-vulnhub源码框架漏洞-Os-hackNos-1

vulnhub源码框架漏洞中的CVE-2018-7600-Drupal 7.57 文章目录  前言 1.靶场搭建&#xff1a; 2.信息搜集&#xff1a; 主机探测&#xff1a; 端口扫描&#xff1a; 目录扫描&#xff1a; 3.分析&#xff1a; 4.步骤&#xff1a; 1.下载CVE-2018-7600的exp 2.执行exp: 3.写入木…...

sqli-lab靶场学习(三)——Less8-10(盲注、时间盲注)

Less8 第八关依然是先看一般状态 http://localhost/sqli-labs/Less-8/?id1 然后用单引号闭合&#xff1a; http://localhost/sqli-labs/Less-8/?id1 这关的问题在于报错是不显示&#xff0c;那没办法通过上篇文章的updatexml大法处理。对于这种情况&#xff0c;需要用“盲…...

Pybullet 安装过程

Pybullet 安装过程&#xff08;windows&#xff09; 1. 安装C编译工具2. 安装Pybullet 1. 安装C编译工具 pybullet 需要C编译套件&#xff0c;直接装之前检查下&#xff0c;要不会报缺少某版本MVSC的error&#xff0c;最好的方式是直接下载visual studio&#xff0c;直接按默认…...

Error when custom data is added to Azure OpenAI Service Deployment

题意&#xff1a;在向 Azure OpenAI 服务部署添加自定义数据时出现错误。 问题背景&#xff1a; I receive the following error when adding my custom data which is a .txt file (it doesnt matter whether I add it via Azure Cognitive Search, Azure Blob Storage, or F…...

libreoffice word转pdf

一、准备一个word文件 运行&#xff1a; cd /root libreoffice --headless --convert-to pdf --outdir /root/output doc1.docx 发现中文乱码&#xff1a; 此时我们需要给linux 上添加中文字体&#xff1a; centos7 添加中文字体 再次运行正常&#xff1a; libreoffice --h…...

java -----泛型

泛型的理解和好处 泛型是在JDK5之后引入的一个新特性&#xff0c;可以在编译阶段约束操作的数据类型&#xff0c;并进行检查。 泛型的格式为 <数据类型> import java.util.ArrayList;SuppressWarnings({"all"}) public class Generic02 {public static void…...

Springboot 文件上传下载相关问题

文章目录 关于Springboot 文件上传下载问题解决方案注意事项文件上传文件下载文件删除文件在线打开在写练习的时候&#xff0c;发现了一些小小的问题&#xff0c;已经在 上述代码中体现。① 代码路径碰到中文的时候&#xff0c;会有乱码&#xff0c;需要转换&#xff08;内容中…...

【Kotlin 与 Java 互操作】Java中调用带有默认值的Kotlin函数(十四)

导读大纲 1.0.1 Java 没有默认参数值的概念1.0.2 使用 JvmOverloads 来简化调用 1.0.1 Java 没有默认参数值的概念 因此当从 Java 调用带有默认参数值的 Kotlin 函数时 1. 必须明确指定所有参数值 fun <T> joinToString(collection: Collection<T>,separator: St…...