/**
* @brief File system operations table.
*/
struct _rtems_filesystem_operations_table {
rtems_filesystem_evalpath_t evalpath_h;
rtems_filesystem_evalmake_t evalformake_h;
rtems_filesystem_link_t link_h;
rtems_filesystem_unlink_t unlink_h;
rtems_filesystem_node_type_t node_type_h;
rtems_filesystem_mknod_t mknod_h;
rtems_filesystem_chown_t chown_h;
rtems_filesystem_freenode_t freenod_h;
rtems_filesystem_mount_t mount_h;
rtems_filesystem_fsmount_me_t fsmount_me_h;
rtems_filesystem_unmount_t unmount_h;
rtems_filesystem_fsunmount_me_t fsunmount_me_h;
rtems_filesystem_utime_t utime_h;
rtems_filesystem_evaluate_link_t eval_link_h;
rtems_filesystem_symlink_t symlink_h;
rtems_filesystem_readlink_t readlink_h;
rtems_filesystem_rename_t rename_h;
rtems_filesystem_statvfs_t statvfs_h;
};
/**
* @brief File system node operations table.
*/
struct _rtems_filesystem_file_handlers_r {
rtems_filesystem_open_t open_h;
rtems_filesystem_close_t close_h;
rtems_filesystem_read_t read_h;
rtems_filesystem_write_t write_h;
rtems_filesystem_ioctl_t ioctl_h;
rtems_filesystem_lseek_t lseek_h;
rtems_filesystem_fstat_t fstat_h;
rtems_filesystem_fchmod_t fchmod_h;
rtems_filesystem_ftruncate_t ftruncate_h;
rtems_filesystem_fpathconf_t fpathconf_h;
rtems_filesystem_fsync_t fsync_h;
rtems_filesystem_fdatasync_t fdatasync_h;
rtems_filesystem_fcntl_t fcntl_h;
rtems_filesystem_rmnod_t rmnod_h;
};
/*
* Structure used to determine a location/filesystem in the tree.
*/
struct rtems_filesystem_location_info_tt
{
void *node_access;
void *node_access_2;
const rtems_filesystem_file_handlers_r *handlers;
const rtems_filesystem_operations_table *ops;
rtems_filesystem_mount_table_entry_t *mt_entry;
};
rtems_filesystem_operations_table devFS_ops =
{
devFS_evaluate_path,
devFS_evaluate_for_make,
NULL,
NULL,
devFS_node_type,
devFS_mknod,
NULL,
NULL,
NULL,
devFS_initialize,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL
};
rtems_filesystem_file_handlers_r devFS_file_handlers =
{
devFS_open,
devFS_close,
devFS_read,
devFS_write,
devFS_ioctl,
NULL,
devFS_stat,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL
};
/**
* @brief Mount table entry.
*/
struct rtems_filesystem_mount_table_entry_tt {
rtems_chain_node Node;
rtems_filesystem_location_info_t mt_point_node;
rtems_filesystem_location_info_t mt_fs_root;
int options;
void *fs_info;
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;
};
typedef int (* rtems_filesystem_fsmount_me_t )(
rtems_filesystem_mount_table_entry_t *mt_entry, /* IN */
const void *data /* IN */
);
typedef struct
{
/** This member points to device name which is a null-terminated string */
char *device_name;
/** This member is the name length of a device */
uint32_t device_name_length;
/** major number of a device */
rtems_device_major_number major;
/** minor number of a device */
rtems_device_minor_number minor;
/** device creation mode, only device file can be created */
mode_t mode;
} rtems_device_name_t;
这是 /dev 目录下有多少个设备,每个设备的名字,major,minor和模式全部被记录下来了。
int devFS_initialize(
rtems_filesystem_mount_table_entry_t *temp_mt_entry,
const void *data
)
{
根据有多少个设备,分配N个设备 rtems_device_name_t 结构
根据 temp_mt_entry 设定 mt_root_fs 的 operator 和 filehandler ,一个文件系统的所有操作都设定好了。
接着 root fs 的access node 设定为 device name table
在 boot_card 中会调用初始化文件系统的函数 rtems_filesystem_initialize
2个全局变量,其中第一个文件系被认为是root文件系统,默认是 IMFS
rtems_filesystem_mount_table_size
mt = &rtems_filesystem_mount_table[0];
获取句柄
mount_h = rtems_filesystem_get_mount_handler( filesystemtype );
if ( !mount_h )
rtems_set_errno_and_return_minus_one( EINVAL );
文件系统的列表中
rtems_filesystem_table[]
{ RTEMS_FILESYSTEM_TYPE_DEVFS, devFS_initialize }
执行过后, mount_h 其实是指向了 devFS_initialize , 虽然不是 rtems_filesystem_fsmount_me_t 类型
但是这两个函数的函数类型其实是一样的。
/*
* Allocate a mount table entry
*/
mt_entry = alloc_mount_table_entry(
source,
target,
filesystemtype,
&target_length
);
if ( !mt_entry )
rtems_set_errno_and_return_minus_one( ENOMEM );
分配一个 rtems_filesystem_mount_table_entry_t 结构类型,这个是会被连接到 location info 结构上面的。
分配函数是有个小技巧,分配一个 mount table entry 结构体之前,还将所有的字符添加在后面,然后用指针指向
它们,这样就不需要另外分配零散的内存来存放那些名字了。
if ( has_target )
作为根目录,这里传入的是 NULL 所以条件不成立
/*
* Do we already have a base file system ?
*/
if ( !rtems_chain_is_empty( &mount_chain ) ) {
errno = EINVAL;
goto cleanup_and_bail;
}
接着判断链是否为空,因为传入的是NULL 参数,所以必须是根目录,链为空,否则错误
if ( (*mount_h)( mt_entry, data ) ) {
/*
* Try to undo the mount operation
*/
if ( loc.ops->unmount_h ) {
loc.ops->unmount_h( mt_entry );
}
goto cleanup_and_bail;
}
前面的分析知道,mount_h 实际上是指 devFS_initialize(或者各个fs提供的初始化函数)
于是,真正的文件系统初始化被调用了。
devFS_initialize--》
/* set file handlers */
temp_mt_entry->mt_fs_root.handlers = &devFS_file_handlers;
temp_mt_entry->mt_fs_root.ops = &devFS_ops;
/* Set the node_access to device name table */
temp_mt_entry->mt_fs_root.node_access = (void *)device_name_table;
于是 文件系统自己的 operator, file handler 就被连接起来了。
/*
* Add the mount table entry to the mount table chain
*/
rtems_libio_lock();
rtems_chain_append( &mount_chain, &mt_entry->Node );
rtems_libio_unlock();
if ( !has_target )
rtems_filesystem_root = mt_entry->mt_fs_root;
回到 rtems_filesystem_initialize
/* Clone the root pathloc */
rtems_filesystem_evaluate_path("/", 1, 0, &loc, 0);
rtems_filesystem_root = loc;
/* One more clone for the current node */
rtems_filesystem_evaluate_path("/", 1, 0, &loc, 0);
rtems_filesystem_current = loc;
将这2个全局变量分别指向 根节点
接着就是生成
status = mkdir( "/dev", 0777);
实际是调用 mknod,首先指向跟还是当前节点
rtems_filesystem_get_start_loc( pathname, &i, &temp_loc );
result = (*temp_loc.ops->evalformake_h)(
&pathname[i],
&temp_loc,
&name_start
);
接着调用文件系统提供的 evalformake函数 devFS_evaluate_for_make
但 devfs并没有做什么,单纯将 name_start 指向了 pathname
接着调用fs自己提供的 mknod 函数 devFS_mknod
result = (*temp_loc.ops->mknod_h)( name_start, mode, dev, &temp_loc );
先确认只支持 dev 目录,/已经被前面去掉了。然后取出之前注册的 device_name_table
判断,因为这里是目录,所以其实并没有做操作,当前只支持 char 和block设备的建立。
device_name_table = (rtems_device_name_t *)pathloc->node_access;
这里就是支持多少个设备的原理了,因为需要在这里添加
找到的话,就占个坑。
这样,例如console,从文件节点中 /dev/console 就可以找到 major 和minor,知道这些,就可以从
Device_drivers 的设备列表找找到相对应的设备驱动,就可以执行了。
* @brief File system operations table.
*/
struct _rtems_filesystem_operations_table {
rtems_filesystem_evalpath_t evalpath_h;
rtems_filesystem_evalmake_t evalformake_h;
rtems_filesystem_link_t link_h;
rtems_filesystem_unlink_t unlink_h;
rtems_filesystem_node_type_t node_type_h;
rtems_filesystem_mknod_t mknod_h;
rtems_filesystem_chown_t chown_h;
rtems_filesystem_freenode_t freenod_h;
rtems_filesystem_mount_t mount_h;
rtems_filesystem_fsmount_me_t fsmount_me_h;
rtems_filesystem_unmount_t unmount_h;
rtems_filesystem_fsunmount_me_t fsunmount_me_h;
rtems_filesystem_utime_t utime_h;
rtems_filesystem_evaluate_link_t eval_link_h;
rtems_filesystem_symlink_t symlink_h;
rtems_filesystem_readlink_t readlink_h;
rtems_filesystem_rename_t rename_h;
rtems_filesystem_statvfs_t statvfs_h;
};
/**
* @brief File system node operations table.
*/
struct _rtems_filesystem_file_handlers_r {
rtems_filesystem_open_t open_h;
rtems_filesystem_close_t close_h;
rtems_filesystem_read_t read_h;
rtems_filesystem_write_t write_h;
rtems_filesystem_ioctl_t ioctl_h;
rtems_filesystem_lseek_t lseek_h;
rtems_filesystem_fstat_t fstat_h;
rtems_filesystem_fchmod_t fchmod_h;
rtems_filesystem_ftruncate_t ftruncate_h;
rtems_filesystem_fpathconf_t fpathconf_h;
rtems_filesystem_fsync_t fsync_h;
rtems_filesystem_fdatasync_t fdatasync_h;
rtems_filesystem_fcntl_t fcntl_h;
rtems_filesystem_rmnod_t rmnod_h;
};
/*
* Structure used to determine a location/filesystem in the tree.
*/
struct rtems_filesystem_location_info_tt
{
void *node_access;
void *node_access_2;
const rtems_filesystem_file_handlers_r *handlers;
const rtems_filesystem_operations_table *ops;
rtems_filesystem_mount_table_entry_t *mt_entry;
};
rtems_filesystem_operations_table devFS_ops =
{
devFS_evaluate_path,
devFS_evaluate_for_make,
NULL,
NULL,
devFS_node_type,
devFS_mknod,
NULL,
NULL,
NULL,
devFS_initialize,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL
};
rtems_filesystem_file_handlers_r devFS_file_handlers =
{
devFS_open,
devFS_close,
devFS_read,
devFS_write,
devFS_ioctl,
NULL,
devFS_stat,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL
};
/**
* @brief Mount table entry.
*/
struct rtems_filesystem_mount_table_entry_tt {
rtems_chain_node Node;
rtems_filesystem_location_info_t mt_point_node;
rtems_filesystem_location_info_t mt_fs_root;
int options;
void *fs_info;
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;
};
typedef int (* rtems_filesystem_fsmount_me_t )(
rtems_filesystem_mount_table_entry_t *mt_entry, /* IN */
const void *data /* IN */
);
typedef struct
{
/** This member points to device name which is a null-terminated string */
char *device_name;
/** This member is the name length of a device */
uint32_t device_name_length;
/** major number of a device */
rtems_device_major_number major;
/** minor number of a device */
rtems_device_minor_number minor;
/** device creation mode, only device file can be created */
mode_t mode;
} rtems_device_name_t;
这是 /dev 目录下有多少个设备,每个设备的名字,major,minor和模式全部被记录下来了。
int devFS_initialize(
rtems_filesystem_mount_table_entry_t *temp_mt_entry,
const void *data
)
{
根据有多少个设备,分配N个设备 rtems_device_name_t 结构
根据 temp_mt_entry 设定 mt_root_fs 的 operator 和 filehandler ,一个文件系统的所有操作都设定好了。
接着 root fs 的access node 设定为 device name table
在 boot_card 中会调用初始化文件系统的函数 rtems_filesystem_initialize
2个全局变量,其中第一个文件系被认为是root文件系统,默认是 IMFS
rtems_filesystem_mount_table_size
mt = &rtems_filesystem_mount_table[0];
获取句柄
mount_h = rtems_filesystem_get_mount_handler( filesystemtype );
if ( !mount_h )
rtems_set_errno_and_return_minus_one( EINVAL );
文件系统的列表中
rtems_filesystem_table[]
{ RTEMS_FILESYSTEM_TYPE_DEVFS, devFS_initialize }
执行过后, mount_h 其实是指向了 devFS_initialize , 虽然不是 rtems_filesystem_fsmount_me_t 类型
但是这两个函数的函数类型其实是一样的。
/*
* Allocate a mount table entry
*/
mt_entry = alloc_mount_table_entry(
source,
target,
filesystemtype,
&target_length
);
if ( !mt_entry )
rtems_set_errno_and_return_minus_one( ENOMEM );
分配一个 rtems_filesystem_mount_table_entry_t 结构类型,这个是会被连接到 location info 结构上面的。
分配函数是有个小技巧,分配一个 mount table entry 结构体之前,还将所有的字符添加在后面,然后用指针指向
它们,这样就不需要另外分配零散的内存来存放那些名字了。
if ( has_target )
作为根目录,这里传入的是 NULL 所以条件不成立
/*
* Do we already have a base file system ?
*/
if ( !rtems_chain_is_empty( &mount_chain ) ) {
errno = EINVAL;
goto cleanup_and_bail;
}
接着判断链是否为空,因为传入的是NULL 参数,所以必须是根目录,链为空,否则错误
if ( (*mount_h)( mt_entry, data ) ) {
/*
* Try to undo the mount operation
*/
if ( loc.ops->unmount_h ) {
loc.ops->unmount_h( mt_entry );
}
goto cleanup_and_bail;
}
前面的分析知道,mount_h 实际上是指 devFS_initialize(或者各个fs提供的初始化函数)
于是,真正的文件系统初始化被调用了。
devFS_initialize--》
/* set file handlers */
temp_mt_entry->mt_fs_root.handlers = &devFS_file_handlers;
temp_mt_entry->mt_fs_root.ops = &devFS_ops;
/* Set the node_access to device name table */
temp_mt_entry->mt_fs_root.node_access = (void *)device_name_table;
于是 文件系统自己的 operator, file handler 就被连接起来了。
/*
* Add the mount table entry to the mount table chain
*/
rtems_libio_lock();
rtems_chain_append( &mount_chain, &mt_entry->Node );
rtems_libio_unlock();
if ( !has_target )
rtems_filesystem_root = mt_entry->mt_fs_root;
回到 rtems_filesystem_initialize
/* Clone the root pathloc */
rtems_filesystem_evaluate_path("/", 1, 0, &loc, 0);
rtems_filesystem_root = loc;
/* One more clone for the current node */
rtems_filesystem_evaluate_path("/", 1, 0, &loc, 0);
rtems_filesystem_current = loc;
将这2个全局变量分别指向 根节点
接着就是生成
status = mkdir( "/dev", 0777);
实际是调用 mknod,首先指向跟还是当前节点
rtems_filesystem_get_start_loc( pathname, &i, &temp_loc );
result = (*temp_loc.ops->evalformake_h)(
&pathname[i],
&temp_loc,
&name_start
);
接着调用文件系统提供的 evalformake函数 devFS_evaluate_for_make
但 devfs并没有做什么,单纯将 name_start 指向了 pathname
接着调用fs自己提供的 mknod 函数 devFS_mknod
result = (*temp_loc.ops->mknod_h)( name_start, mode, dev, &temp_loc );
先确认只支持 dev 目录,/已经被前面去掉了。然后取出之前注册的 device_name_table
判断,因为这里是目录,所以其实并没有做操作,当前只支持 char 和block设备的建立。
device_name_table = (rtems_device_name_t *)pathloc->node_access;
这里就是支持多少个设备的原理了,因为需要在这里添加
找到的话,就占个坑。
这样,例如console,从文件节点中 /dev/console 就可以找到 major 和minor,知道这些,就可以从
Device_drivers 的设备列表找找到相对应的设备驱动,就可以执行了。