(简单做个笔记)
VFS和ramfs
LiteOS提供了VFS和各类文件系统
(摘自百度百科)VFS(virtual File System)的作用就是采用标准的Unix系统调用读写位于不同物理介质上的不同文件系统,即为各类文件系统提供了一个统一的操作界面和应用编程接口。
ramfs是建立在内存中的一个非常简单的文件系统,通过它可以了解LiteOS的文件系统机制
ramfs_init
使用文件系统前,通过ramfs_init()注册ramfs
los_vfs_init初始化VFS,作用是注册一个文件系统的互斥量
los_fs_register(&ramfs_fs)注册ramfs
ramfs_fs是一个file_system结构体变量,file_system定义如下
struct file_system
{
const char fs_name [LOS_FS_MAX_NAME_LEN];
struct file_ops * fs_fops;
struct file_system * fs_next;
volatile uint32_t fs_refs;
};
这是一个链表
file_ops结构体的部分定义如下
struct file_ops
{
int (*open) (struct file *, const char *, int);
int (*close) (struct file *);
...
...
};
定义了各个系统调用的函数指针
ramfs初始化ramfs_fs如下
static struct file_system ramfs_fs =
{
"ramfs",
&ramfs_ops,
NULL,
0
};
其中ramfs_ops中的各个函数指针指向以ramfs开头的每个具体实现函数
在los_fs_register中,首先进行一些常规的检查,然后将ramfs_fs挂在链表file_systems里面
接下来在ramfs_init()中调用了ramfs_mount("/ramfs/", 16 * 1024)
挂载文件系统,后一个参数的意思是在内存分配16KB作为“硬盘”
ramfs_mount
在这个函数中,首先初始化一个挂载点结构体ramfs_mount_point的变量,ramfs_mount_point定义如下
struct ramfs_mount_point
{
struct ramfs_element root;
void *memory;
};
root是文件树树根,memory是分配的16KB在内存中的具体位置,其中ramfs_element的定义如下
struct ramfs_element
{
char name [LOS_MAX_FILE_NAME_LEN];
uint32_t type;
struct ramfs_element *sabling;
struct ramfs_element *parent;
volatile uint32_t refs;
union
{
struct
{
size_t size;
char *content;
} f;
struct
{
struct ramfs_element *child;
} d;
};
};
用于记录每个文件的信息
回到ramfs_mount,初始化时赋值root的文件名为“/ramfs/”,memory分配16KB
调用LOS_MemInit初始化分配的内存为动态内存池,便于管理
最后调用los_fs_mount (const char *fsname, const char *path, void *data)
将ramfs挂载到mount_point结构体链表mount_points中,mount_point结构体定义如下
struct mount_point
{
struct file_system * m_fs;
struct mount_point * m_next;
const char * m_path;
volatile uint32_t m_refs;
UINT32 m_mutex;
void * m_data; /* used by fs private data for this mount point (like /sdb1, /sdb2), */
};
los_fs_mount返回,los_ramfs_init结束,此时可以通过目录"/ramfs/"访问ramfs中的文件
系统调用的执行过程
以下面的代码为例
VOID ramfs_demo(VOID){
//首先挂载ramfs到"/ramfs/"
if(ramfs_init() == LOS_NOK){
trace_printf("ramfs_init error!\n");
return ;
}
//下面使用正常的uinx风格文件系统调用即可
int fd;
if((fd = open("/ramfs/newfile", O_WRONLY | O_CREAT)) == -1){
trace_printf("can't open new file!\n");
return ;
}
//写入字符串
const char *str_write = "Hello, LiteOS!";
write(fd, str_write, strlen(str_write));
close(fd);
if((fd = open("/ramfs/newfile", O_RDONLY)) == -1){
trace_printf("can't open file!\n");
return ;
}
char str_read[20] = {0};
//读入字符串
read(fd, str_read, 20);
trace_printf("read string from file: %s\n",str_read);
close(fd);
}
数据结构
los_vfs.c初始化了四个重要的变量
struct file files [LOS_MAX_FILES];
UINT32 fs_mutex = LOS_ERRNO_MUX_PTR_NULL;
struct mount_point *mount_points = NULL;
struct file_system *file_systems = NULL;
后面两个分别是挂载点和文件系统的链表,上面已经说过,fs_mutex是互斥信号量,files是一个打开文件表,记录当前打开的文件信息,file的结构体定义如下
struct file
{
struct file_ops * f_fops;
UINT32 f_flags;
UINT32 f_status;
off_t f_offset;
struct mount_point * f_mp; /* can get private mount data here */
UINT32 f_owner; /* the task that openned this file */
void * f_data;
};
open()调用
LiteOS对系统调用做了UNIX风格的封装,open()调用的代码如下
int open (const char *path, int flags,...)
{
int ret = los_open (path, flags);
return MAP_TO_POSIX_RET(ret);
}
在los_open中,211行首先在files数组中获得一个空表项,219行找到文件所在的文件系统挂载点,243行通过file_ops结构体中的函数指针调用真正的文件系统的open调用,也就是los_ramfs.c中的ramfs_open()
ramfs_open()根据传入的flags执行相应动作,这里是创建一个新文件,所以在文件树中找不到文件,所以238行开始创建一个新节点,并将file变量中的指针指向文件地址(这里是内存地址),回到los_open(),将files数组中表项的下标作为描述符fd返回
其他的调用
类似open(),都是封装了los_xxx()函数,然后通过file_ops结构体中的函数指针调用相应的文件系统的底层调用,不再赘述
来源:CSDN
作者:-MachInST-
链接:https://blog.csdn.net/weixin_43184560/article/details/104200994