RTEMS 的文件系统初始化等的一点分析笔记

来源:互联网 发布:c语言分割字符串函数 编辑:程序博客网 时间:2024/05/23 01:20
/**
 * @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 的设备列表找找到相对应的设备驱动,就可以执行了。
0 0
原创粉丝点击