是否要使用qemu?,开发环境是什么?
arch linux是否可用,网上ubuntu的相关资料比较多、
rtems-rfs-file-system.h,这个文件里面看到了group,inode,block,好像没找到vfs类似的jie’gou
rtems目录结构下有很多fs相关的,imfs.h也在里面
rfs具体好像就是一个文件系统的基础结构,具体目录如下:
https://docs.rtems.org/releases/rtems-docs-4.11.2/,各种RTEMS手册
最完整的rtems fs手册:
https://docs.rtems.org/releases/rtems-docs-4.11.2/filesystem/index.html
下面这个是手册的双语版在线:
http://www.doc88.com/p-0827413821379.html
是否主要读mount这部分的内容??
定义在rtems configuration中的设备都被注册为可挂载文件系统中的文件,访问设备驱动和设备可以通过传统的文件操作方式 ,除了IO manager中接口外,还有open(), read(), write(), lseek(), fstat() and ioctl() functions
路径评估:
rtems手册上的路径评估过程:
暂时理解为实现文件系统时需要考虑的功能—路径检查的功能
在 RTEMS 文件系统结构下的路径检查处理包括三部分:
1)路径检查handler函数
2)跨越挂载点的路径检查
3)系统节点信息表数据结构
1、路径检查函数包括 patheval()和 evalformake()两个
路径检查对文件系统来说是特定的。每个文件系统需要提供上述两个routine。路径检查功能对于文件系统十分重要 ,通过它们来获取开始检查的节点位置和待检查的路径名。
3、文件系统存放信息结构体(rtems_filesystem_location_info_t) 包含了识别该node的全部信息RTEMS通用文件系统代码定义了两个全局的rtems_filesystem_location_info_t结构,包括 rtems_filesystem_root和rtems_filesystem_current 结构。在初始化时,这两个结构都被定义为基本文件系统的根节点 ,当执行了 chdir 命令以后,rtems_filesystem_current 结构就被定位到命令所指向的位置 。
下面结构体在cpukit/include/rtems/fs.h中定义:
typedef struct rtems_filesystem_location_info_tt {
rtems_chain_node mt_entry_node;
void* node_access;
void* node_access_2;
const rtems_filesystem_file_handlers_r *handlers;
rtems_filesystem_mount_table_entry_t *mt_entry;
} rtems_filesystem_location_info_t;
上面代码解释:
node_access: 文件系统具体的,一个文件系统可以在这个位置定义和存储任何可以识别该节点的必要信息,一般用于存放文件系统的检查routine。对于文件系统的root node,文件系统的初始化routine应该放在这里,应该一直保持有效,直到文件系统实例被unmounted。
handlers:定义了routine的集合,在一个文件系统中根据节点类型,这些routines可以被改变。通过mount table作为初始值,可以被检查routine改为期望的状态。
mt_entry:文件系统实例在mount table的入口
整个文件系统的初始化:
libio这个函数特别多,可能和系统初始化关系很大
调用rtems_filesystem_initialize()函数将会挂载‘In Memory File System’作为 the base filesystem
初始化过程在 cpukit/sapi/include/confdefs.h 中有定义:
#ifdef CONFIGURE_INIT //一般都会定义这个宏。
const rtems_libio_helper rtems_libio_init_helper =
#ifdef CONFIGURE_APPLICATION_DISABLE_FILESYSTEM
rtems_libio_helper_null;
#else
rtems_libio_init;
#endif
const rtems_libio_helper rtems_libio_post_driver_helper =
#ifdef CONFIGURE_APPLICATION_DISABLE_FILESYSTEM
rtems_libio_helper_null;
#else
rtems_libio_post_driver;
#endif
const rtems_libio_helper rtems_libio_exit_helper =
#ifdef CONFIGURE_APPLICATION_DISABLE_FILESYSTEM
rtems_libio_helper_null;
#else
rtems_libio_exit;
#endif
const rtems_libio_helper rtems_fs_init_helper =
#ifdef CONFIGURE_APPLICATION_DISABLE_FILESYSTEM
rtems_libio_helper_null;
#else
rtems_filesystem_initialize; //这个地方是入口
#endif
#endif
rtems_filesystem_initialize()这个函数定义是在cpukit/libcsupport/include/rtems/libio_.h中声明的,
定义在cpukit/libcsupport/src/base_fs.c
void rtems_filesystem_initialize( void )
{
int rv = 0;
const rtems_filesystem_mount_configuration *root_config =
&rtems_filesystem_root_configuration; 这个配置变量是 cpukit/sapi/include/confdefs.h 中定义的。默认就是IMFS文件系统。
//安装文件系统。mount函数在cpukit/libcsupport/src/mount.c中,这些函数暂时不仔细研究
rv = mount(
root_config->source,
root_config->target,
root_config->filesystemtype,
root_config->options,
root_config->data
);
if ( rv != 0 )
rtems_fatal_error_occurred( 0xABCD0002 );
/*
* Traditionally RTEMS devices are under "/dev" so install this directory.
*
* If the mkdir() fails, we can't print anything so just fatal error.
*/
rv = mkdir( "/dev", S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH );
if ( rv != 0 )
rtems_fatal_error_occurred( 0xABCD0003 );
/*
* You can't mount another filesystem properly until the mount point
* it will be mounted onto is created. Moreover, if it is going to
* use a device, then it is REALLY unfair to attempt this
* before device drivers are initialized. So we return via a base
* filesystem image and nothing auto-mounted at this point.
*/
}
上面代码中直接使用了mkdir()函数
filesystemtype好像比较重要
**
mount的实现:
int mount(
const char *source,
const char *target,
const char *filesystemtype,
rtems_filesystem_options_t options,
const void *data
)
{
int rv = 0;
if (
options == RTEMS_FILESYSTEM_READ_ONLY|| options == RTEMS_FILESYSTEM_READ_WRITE)
{
rtems_filesystem_fsmount_me_t fsmount_me_h =
rtems_filesystem_get_mount_handler( filesystemtype );
if ( fsmount_me_h != NULL ) {
size_t target_length = 0;
rtems_filesystem_mount_table_entry_t *mt_entry = alloc_mount_table_entry(
source,
target,
filesystemtype,
&target_length
);
if ( mt_entry != NULL ) {
mt_entry->writeable = options == RTEMS_FILESYSTEM_READ_WRITE;
rv = (*fsmount_me_h)( mt_entry, data );
if ( rv == 0 ) {
if ( target != NULL ) {
rv = register_subordinate_file_system( mt_entry, target );
} else {
rv = register_root_file_system( mt_entry );
}
if ( rv != 0 ) {
(*mt_entry->ops->fsunmount_me_h)( mt_entry );
}
}
if ( rv != 0 ) {
free( mt_entry );
}
} else {
errno = ENOMEM;
rv = -1;
}
} else {
errno = EINVAL;
rv = -1;
}
} else {
errno = EINVAL;
rv = -1;
}
return rv;
}
rtems_filesystem_fsmount_me_t 这个在cpukit/libcsupport/include/rtems/libio.h中定义。是一个函数指针的类型
rtems_filesystem_get_mount_handler( filesystemtype );
这个函数在cpukit/libcsupport/src/mount-mgr.c中定义,这个文件是manage mount table的
这个函数会迭代查找rtems_filesystem_table_t结构体类型的rtems_filesystem_table
rtems_filesystem_table是一个默认的文件系统表,它在cpukit/sapi/include/confdefs.h 中有定义
如果没有在rtems_filesystem_table中找到,那么需要在chain中找,暂时理解为如果默认的rtems_filesystem_table中没有定义,那么后面挂载的文件系统会放到chain中。所以要到chain中继续查找。chain中通过rtems_filesystem_register和rtems_filesystem_unregister 增加或者删除,这两个函数也在cpukit/libcsupport/src/mount-mgr.c中定义
base file system:
• 建立一个链表的mount table chain结构
• Allocation of ajnode structure that will server as the root node of the ‘In Memory Filesystem’ 在IMFS_initialize_support中定义了该结构
• Initialization of the allocated jnodewith the appropriate OPS, directory handlers and pathconf limits and options. 通过confdefs中定义的ops去初始化这个jnode中的ops
• Allocation of a memory region for filesystem specific global management variables 在 register_root_file_system后半部分
• Creation of first mount table entry for the base filesystem
• Initialization of the first mount table chain entry to indicate that the mount point is NULL and the mounted filesystem is the base file system
rtems初始化时安装了ram based 的文件系统作为base file system。文件系统树的根目录被认为是目录结构的逻辑根。 /dev作为I/O设备目录被创建。
基于ram的文件系统,文件和目录节点都是简单的分配内存块。数据也被存储在内存块中。当系统关闭或者重启,文件都会丢失。
base file system作为安装文件系统的开始点。比如non- volatile memory, flash memory and IDE hard disk drives。
其他类型的文件系统将在挂载到base file system的挂载点上或者挂载到附属于base file system的其他系统上。
base file system被安装为IMFS,使用标准的mount函数。mount point是null。标志着操作系统下注册的第一个文件系统,并进行该文件系统的一些初始化。假如需要不同的文件系统作为base file system。那么需要修改base_fs.c
一旦base file system的root建立起来。它就记录为base file system的挂载点。device被集成到base file system。对于每个配置到系统的设备,都有一个设备注册过程。设备注册产生一个唯一的dev_t handle,有major和minor device number。除此之外,每个设备的配置信息包含一个text string代表设备在file system中的路径。一个文件系统的node被创建,这个node关联具体的设备注册路径。其他的文件系统可以被安装,但是安装在base file system的点上(directory mount points)
如何挂载一个文件系统:
直接阅读手册里面的mount和unmount部分
挂载点的概念
1:挂载点必须是一个目录。可以有文件和其他目录在它下面
2:任务比如有read/write/execute的权限,否则挂载尝试将被拒绝
3:只有一个文件系统可以挂载到一个单独的挂载点。
4:挂载完成后,挂载点名字可以作为挂载文件系统的root的引用。
mount table chain 是一个动态list结构,描述了mounted filesystem在文件系统层级结构中的具体位置。在base file system初始化的时候这个链表初始化为空。mount操作将add entry到mount table chain中。反之,unmount移除 entry
struct rtems_filesystem_mount_table_entry_tt {
rtems_chain_node mt_node;
void *fs_info;
const rtems_filesystem_operations_table *ops;
const void *immutable_fs_info;
rtems_chain_control location_chain;
rtems_filesystem_global_location_t *mt_point_node;
rtems_filesystem_global_location_t *mt_fs_root;
bool mounted;
bool writeable;
const rtems_filesystem_limits_and_options_t *pathconf_limits_and_options;
/*
* The target or mount point of the file system.
*/
const char *target;
/*
* The type of filesystem or the name of the filesystem.
*/
const char *type;
/*
* When someone adds a mounted filesystem on a real device,
* this will need to be used.
*
* The lower layers can manage how this is managed. Leave as a
* string.
*/
char *dev;
/**
* The task that initiated the unmount process. After unmount process
* completion this task will be notified via the transient event.
*
* @see ClassicEventTransient.
*/
rtems_id unmount_task;
};
mt_node:链表的节点。
mt_point_node : 包含了所有必要的信息来获取文件系统安装的目录。这个元素包含内存,该内存在path evaluation
文件系统是分配,包含了挂载点的目录。当文件系统被mt_fs_root识别为未被挂载的,可以允许这部分内存通过unmount收回
mt_fs_root包含所有必要的信息来识别安装文件系统的root。用户不允许通过一般代码获取这个node,但是它被用于识别挂载的文件系统,这是开始evaluation of pathname的地方。
fs_info:可被挂载的文件系统获取,用来识别应用于文件系统实例的唯一的thing,它是一个location。例如IMFS就用这个空间来提供node的识别(对于文件系统的每个实例都是唯一的)
dev:文件系统所在的device
功能转化层(类似VFS)重点(手册第六章):
rtems的文件系统框架是兼容posix files 和 directories接口标准的。
以下的文件系统特性产生了一个功能转换层。
1:应用程序提供了一套标准的POSIX标准功能集,这些功能允许它们和文件,设备,目录进行接口。对这些函数来说接口不会影响下级文件系统的实现 2:框架允许在base filesystem下面挂载不同类型的文件系统。3: 定位文件信息的机制在不同的文件系统类型下是不同的。4:> 文件系统和不同文件系统访问信息所需的处理之间的转换,在POSIX函数调用的级别上是不可见的。5:POSIX接口标准提供文件访问的方式,在一些函数中通过字符路径名访问,在其他函数中用过整数文件描述符访问6:整数文件描述符的性质及其相关的处理是操作系统和文件系统特定的。7:目录和设备信息必须被以相同的应用于文件的函数处理。8:目录和设备信息的形式和内容和一个常规文件完全不同。9:文件、目录和设备表示树的元素(节点) 层次结构。10:文件系统中处理每个节点类型的规则是特定于某种节点的,但仍然没有反映在POSIX接口函数中。
文件和目录删除约束
所有的文件系统都必须兑现以下~POSIX~的约束。
1、如果一个节点是一个带有孩子的目录,它不能被删除;
2、任何文件系统的根结点,无论是基础文件系统或挂载文件系统的,都不能被删除;
3、 一个节点作为文件系统挂载点的目录是不能被删除的;
4、 支持硬链接的文件系统,需要维护连结数。在移动节点之前,节点接数要减一。链接数必须小于一以允许节点的删除。
对于应用程序,这些函数允许在任何安装的文件系统中访问信息,而不需要对文件系统类型或文件系统装载配置有明确的了解。比如open(), read(), write(), close(),ext4已经支持?那么首先主要的工作就是挂载的实现?
API:
POSIX Application Programs Interface~的文件和目录一节列出了一系列函数及其用于获取访问文件系统信息的调用参数。对于应用程序,这些函数允许访问任何已挂载文件系统的信息,不需要相关文件系统类型的显性知识或文件系统的挂载配置。
以下是向应用程序提供的函数:
- access() chdir() chmod() chown()
- close() closedir()
- fchmod() fcntl() fdatasync() fpathconf() fstat() fsync() ftruncate()
- link() lseek()
- mkdir() mknod()
- mount() unmount()
- open() opendir()
- pathconf()
- read() readdir() rewinddir()
- rmdir() rmnod()
- scandir() seekdir() telldir()
- stat()
- umask() unlink()
- utime()
- write()
文件系统的类型以及文件系统中的节点类型决定了上面的每个函数执行处理的特性。RTEMS文件系统提供了一个框架,允许在不更改基本框架的情况下开发和集成新的文件系统。
为了提供所需的功能切换,每个POSIX文件和目录函数都被实现为一个shell函数。shell函数符合POSIX标准接口标准。在这个函数的shell中,文件系统和节点类型信息被访问,然后使用它来调用适当的文件系统和节点类型的特定函数来处理相应的POSIX函数调用。(访问文件系统和节点类型信息是通过调用合适的文件系统和节点类型中特殊的处理函数处理~POSIX~函数调用。)
rtems_libio_t函数:
File/Device/Directory function access via file control block rtems_libio_t structure
文件/设备/目录功能访问通过文件控制块-rtems_libio_t结构
posix open函数返回整数的文件标识符,用于对一个具体文件的文件控制块信息的引用。文件控制块信息用于locate need,文件系统,挂载tabel,函数handler
File Descriptor Table: 这是一个rtems内部的结构,跟踪系统中所有当前定义的file descriptors。open返回的是这个表中的index,这个index指示的table slot中存放的是这个文件file descriptor tabl entry的指针。rtems_libio_t代表文件控制块
Allocation of entry in the File Descriptor Table:获取file descriptor table entry通过rtems_libio_allocate(),该函数中使用了一个semaphore。(Access to the file descriptor table is controlled through a semaphore that is implemented using the rtems_libio_allocate() function. This routine will grab a semaphore and then scan the file control blocks to determine which slot is free for use. The first free slot is marked as used and the index to this slot is returned as the file descriptor for the open() request. After the alterations have been made to the file control block table, the semaphore is released to allow further operations on the table.)
最大的file descriptor table通过cpukit/sapi/include/confdefs.h 中定义
struct rtems_libio_tt {
rtems_driver_name_t *driver;
off_t size;//如果是文件,代表文件字节数,如果是目录则该项为空
off_t offset;//不管是目录还是文件,都代表byte偏移量
unsigned32 flags;
rtems_filesystem_location_info_t pathinfo;//文件/目录的访问指针
Objects_Id sem;
unsigned32 data0;
void data1;
void file_info;//A pointer to node information that is used by Handler functions
rtems_filesystem_file_handlers_r handlers;//A pointer to a table of handler functions that operate on a file, device or directory through a file descriptor index
};
rtems_filesystem_location_info_t structure(File/Directory function access)
这个结构必须在mounted条件下才可以使用
struct rtems_filesystem_location_info_tt {
void *node_access;
rtems_filesystem_file_handlers_r *handlers;
rtems_filesystem_operations_table *ops;
rtems_filesystem_mount_table_entry_t *mt_entry;
};
OPS表函数(rtems_filesystem_operation_table):
在rtems_filesystem_operation_table中定义,每个特定的文件系统中定义了一个
typedef struct {
rtems_filesystem_evalpath_t evalpath;
rtems_filesystem_evalmake_t evalformake;
rtems_filesystem_link_t link;
rtems_filesystem_unlink_t unlink;
rtems_filesystem_node_type_t node_type;
rtems_filesystem_mknod_t mknod;
rtems_filesystem_rmnod_t rmnod;
rtems_filesystem_chown_t chown;
rtems_filesystem_freenode_t freenod;
rtems_filesystem_mount_t mount;
rtems_filesystem_fsmount_me_t fsmount_me;
rtems_filesystem_unmount_t unmount;
rtems_filesystem_fsunmount_me_t fsunmount_me;
rtems_filesystem_utime_t utime;
rtems_filesystem_evaluate_link_t eval_link;
rtems_filesystem_symlink_t symlink;
} rtems_filesystem_operations_table;
IMFS文件系统:
IMFS(In-Memory FileSystem)是一个全功能的POSIX文件系统,在memory中保存所有的信息。
每一个文件,设备,hard link 目录都被表示为一种数据结构,叫做jnode。该类型在cpukit/libfs/src/imfs/imfs.h中定义
struct IMFS_jnode_tt {
rtems_chain_node Node; /* for chaining them together */
IMFS_jnode_t *Parent; /* Parent node */
const char *name; /* "basename" (not \0 terminated) */
uint16_t namelen; /* Length of "basename" */
uint16_t flags; /* Node flags */
mode_t st_mode; /* File mode */
unsigned short reference_count;
nlink_t st_nlink; /* Link count */
uid_t st_uid; /* User ID of owner */
gid_t st_gid; /* Group ID of owner */
time_t stat_atime; /* Time of last access */
time_t stat_mtime; /* Time of last modification */
time_t stat_ctime; /* Time of last status change */
const IMFS_node_control *control;
};