之前讲到 rtems_filesystem_initialize 函数中调用了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中定义。是一个函数指针的类型
如下定义:它有两个参数
typedef int (*rtems_filesystem_fsmount_me_t)(
rtems_filesystem_mount_table_entry_t *mt_entry,
const void *data);
第二点:rtems_filesystem_get_mount_handler( filesystemtype );
这个函数在cpukit/libcsupport/src/mount-mgr.c中定义,这个文件是manage mount table的
这个函数会迭代查找rtems_filesystem_table_t结构体类型的rtems_filesystem_table,后面详细说明
在这个函数内部使用了一个结构体
typedef struct {
const char *type;
rtems_filesystem_fsmount_me_t mount_h;
} find_arg;
该函数最终为了找到对应type 的 mount_h函数。注意返回值类型就是我们想要的rtems_filesystem_fsmount_me_t类型
rtems_filesystem_fsmount_me_t
rtems_filesystem_get_mount_handler(
const char *type
)
{
find_arg fa = {
.type = type,
.mount_h = NULL
};
if ( type != NULL ) {
rtems_filesystem_iterate( find_handler, &fa );
}
return fa.mount_h;
}
第三点 rtems_filesystem_iterate 这个迭代函数,这个函数设计成有点类似c++模板,输入的routine类型为
rtems_per_filesystem_routine,本身就是一种操作函数,在这里作用是比较type的操作。
bool rtems_filesystem_iterate(
rtems_per_filesystem_routine routine,
void *routine_arg
)
{
rtems_chain_control *chain = &filesystem_chain;
const rtems_filesystem_table_t *table_entry = &rtems_filesystem_table [0];
rtems_chain_node *node = NULL;
bool stop = false;
while ( table_entry->type && !stop ) {
stop = (*routine)( table_entry, routine_arg ); //这里进行比较type
++table_entry;
}
if ( !stop ) {
rtems_libio_lock();
for (
node = rtems_chain_first( chain );
!rtems_chain_is_tail( chain, node ) && !stop;
node = rtems_chain_next( node )
) {
const filesystem_node *fsn = (filesystem_node *) node;
stop = (*routine)( &fsn->entry, routine_arg );
}
rtems_libio_unlock();
}
return stop;
}
1)filesystem_chain代表文件系统的一个链表,链表后面单独学习研究。链表输入rtems内核的东西
2)rtems_filesystem_table是文件系统的一个表,这个表的元素类型如下,可见通过查找type,就可以找到对应的文件系统的处理函数mount_h
typedef struct rtems_filesystem_table_t {
const char *type;
rtems_filesystem_fsmount_me_t mount_h;
} rtems_filesystem_table_t;
其中的比较type的函数如下所示
static bool find_handler(const rtems_filesystem_table_t *entry, void *arg)
{
find_arg *fa = arg;
if ( strcmp( entry->type, fa->type ) != 0 ) {
return false;
} else {
fa->mount_h = entry->mount_h;
return true;
}
}
rtems_filesystem_table是一个默认的文件系统表,它在cpukit/sapi/include/confdefs.h 中有定义,如下
/**
* The default file system table. Must be terminated with the NULL entry if
* you provide your own.
*/
#if !defined(CONFIGURE_HAS_OWN_FILESYSTEM_TABLE) && \
!defined(CONFIGURE_APPLICATION_DISABLE_FILESYSTEM)
const rtems_filesystem_table_t rtems_filesystem_table[] = {
#if !defined(CONFIGURE_USE_DEVFS_AS_BASE_FILESYSTEM)
{ "/", IMFS_initialize_support }, //如果没定义为dev的文件系统,那么就有这个
#endif
#if defined(CONFIGURE_FILESYSTEM_IMFS) && \
defined(CONFIGURE_FILESYSTEM_ENTRY_IMFS)
CONFIGURE_FILESYSTEM_ENTRY_IMFS, /这个在其它地方也有定义,一般都会定义CONFIGURE_FILESYSTEM_IMFS,如下面
#endif
#if defined(CONFIGURE_FILESYSTEM_DEVFS) && \
defined(CONFIGURE_FILESYSTEM_ENTRY_DEVFS)
CONFIGURE_FILESYSTEM_ENTRY_DEVFS,
#endif
#if defined(CONFIGURE_FILESYSTEM_TFTPFS) && \
defined(CONFIGURE_FILESYSTEM_ENTRY_TFTPFS)
CONFIGURE_FILESYSTEM_ENTRY_TFTPFS,
#endif
#if defined(CONFIGURE_FILESYSTEM_FTPFS) && \
defined(CONFIGURE_FILESYSTEM_ENTRY_FTPFS)
CONFIGURE_FILESYSTEM_ENTRY_FTPFS,
#endif
#if defined(CONFIGURE_FILESYSTEM_NFS) && \
defined(CONFIGURE_FILESYSTEM_ENTRY_NFS)
CONFIGURE_FILESYSTEM_ENTRY_NFS,
#endif
#if defined(CONFIGURE_FILESYSTEM_DOSFS) && \
defined(CONFIGURE_FILESYSTEM_ENTRY_DOSFS)
CONFIGURE_FILESYSTEM_ENTRY_DOSFS,
#endif
#if defined(CONFIGURE_FILESYSTEM_RFS) && \
defined(CONFIGURE_FILESYSTEM_ENTRY_RFS)
CONFIGURE_FILESYSTEM_ENTRY_RFS,
#endif
#if defined(CONFIGURE_FILESYSTEM_JFFS2) && \
defined(CONFIGURE_FILESYSTEM_ENTRY_JFFS2)
CONFIGURE_FILESYSTEM_ENTRY_JFFS2,
#endif
CONFIGURE_FILESYSTEM_NULL
};
#endif
上面一些宏定义,我没有标注的,比如 CONFIGURE_FILESYSTEM_ENTRY_JFFS2 都在cpukit/sapi/include/confdefs.h 中有定义
这里不关注其它类型的文件系统,先关注IMFS
/**
* This defines the IMFS file system table entry.
*/
#if !defined(CONFIGURE_FILESYSTEM_ENTRY_IMFS) && \
defined(CONFIGURE_FILESYSTEM_IMFS)
#define CONFIGURE_FILESYSTEM_ENTRY_IMFS \
{ RTEMS_FILESYSTEM_TYPE_IMFS, IMFS_initialize }
#endif
这部分也是上面rtems_filesystem_table的一部分
/**
* Table termination record.
*/
#define CONFIGURE_FILESYSTEM_NULL { NULL, NULL }
默认情况下,如果只有定义了IMFS,那么rtems_filesystem_table有三个值(包括上面的NULL值)第四点:如果没有在rtems_filesystem_table中找到,那么需要在chain中找,暂时理解为如果默认的rtems_filesystem_table中没有定义,那么后面挂载的文件系统会放到chain中。所以要到chain中继续查找。chain中通过rtems_filesystem_register和rtems_filesystem_unregister 增加或者删除,这两个函数也在cpukit/libcsupport/src/mount-mgr.c中定义。暂时不考虑