MS-RTOS IO 子系统
本章将介绍 MS-RTOS IO 子系统的基础知识,文件系统、设备驱动、网络子系统开发都需要用到 IO 子系统的数据类型和接口。
IO 子系统相关数据类型
类型 | 描述 |
---|---|
ms_io_name_node_t | 命名节点类型 |
ms_io_name_node_callback_t | 命名节点遍历回调类型 |
ms_io_driver_ops_t | 设备驱动操作类型 |
ms_io_drv_type_t | 设备驱动的类型 |
ms_io_driver_t | 设备驱动类型 |
ms_io_device_t | 设备类型 |
ms_io_fs_ops_t | 文件系统操作类型 |
ms_io_fs_type_t | 文件系统的类型 |
ms_io_fs_t | 文件系统类型 |
ms_io_file_t | IO 系统打开的一个文件实例类型 |
ms_io_file_type_t | 文件实例的类型 |
ms_io_mnt_t | 挂载点类型 |
ms_io_job_t | IO 工作类型 |
ms_io_job_opt_t | IO 工作选项 |
ms_io_job_status_t | IO 工作运行状态 |
ms_io_name_node_t
命名节点类型定义如下:
typedef struct {
ms_list_head_t node; // 链表节点
const char *name; // 名字
} ms_io_name_node_t;
ms_io_name_node_callback_t
命名节点遍历回调函数类型定义如下:
typedef void (*ms_io_name_node_callback_t)(ms_io_name_node_t *nnode, ms_ptr_t arg);
ms_io_driver_ops_t
设备驱动操作类型定义如下:
typedef struct {
// 设备驱动的类型
ms_io_drv_type_t type;
// 打开设备
int (*open)(ms_ptr_t ctx, ms_io_file_t *file, int oflag, ms_mode_t mode);
// 关闭设备
int (*close)(ms_ptr_t ctx, ms_io_file_t *file);
// 读设备
ms_ssize_t (*read)(ms_ptr_t ctx, ms_io_file_t *file, ms_ptr_t buf, ms_size_t len);
// 写设备
ms_ssize_t (*write)(ms_ptr_t ctx, ms_io_file_t *file, ms_const_ptr_t buf, ms_size_t len);
// 控制设备
int (*ioctl)(ms_ptr_t ctx, ms_io_file_t *file, int cmd, ms_ptr_t arg);
// 控制文件
int (*fcntl)(ms_ptr_t ctx, ms_io_file_t *file, int cmd, int arg);
// 获得设备状态
int (*fstat)(ms_ptr_t ctx, ms_io_file_t *file, ms_stat_t *buf);
// 判断是不是一个 TTY 设备
int (*isatty)(ms_ptr_t ctx, ms_io_file_t *file);
// 同步文件系统 CACHE
int (*fsync)(ms_ptr_t ctx, ms_io_file_t *file);
// 同步文件数据 CACHE
int (*fdatasync)(ms_ptr_t ctx, ms_io_file_t *file);
// 截断文件长度
int (*ftruncate)(ms_ptr_t ctx, ms_io_file_t *file, ms_off_t len);
// 调整文件读写指针
ms_off_t (*lseek)(ms_ptr_t ctx, ms_io_file_t *file, ms_off_t offset, int whence);
// 等待文件事件
int (*poll)(ms_ptr_t ctx, ms_io_file_t *file, ms_pollfd_t *fds, ms_bool_t setup);
// 删除设备
int (*unlink)(ms_ptr_t ctx);
/*
* Block device only:
*/
// 读块
ms_ssize_t (*readblk )(ms_ptr_t ctx, ms_io_file_t *file,
ms_size_t blk_no, ms_size_t blk_cnt, ms_ptr_t buf);
// 写块
ms_ssize_t (*writeblk)(ms_ptr_t ctx, ms_io_file_t *file,
ms_size_t blk_no, ms_size_t blk_cnt, ms_const_ptr_t buf);
/*
* NAND Flash device only:
*/
// 读 chunk
int (*readchunk )(ms_ptr_t ctx, ms_io_file_t *file,
ms_size_t chunk_no, ms_ptr_t data, ms_size_t data_len,
ms_ptr_t oob, ms_size_t oob_len, ms_uint8_t *ecc_result);
// 写 chunk
int (*writechunk)(ms_ptr_t ctx, ms_io_file_t *file,
ms_size_t chunk_no, ms_const_ptr_t data, ms_size_t data_len,
ms_const_ptr_t oob, ms_size_t oob_len);
* Power management
*/
#if MS_CFG_KERN_PM_EN > 0
// 挂起设备
ms_err_t (*suspend)(ms_ptr_t ctx, ms_pm_sleep_mode_t sleep_mode);
// 恢复设备
void (*resume)(ms_ptr_t ctx, ms_pm_sleep_mode_t sleep_mode);
// 调整工作频率
void (*adjust_freq)(ms_ptr_t ctx, ms_pm_run_mode_t run_mode);
#endif
} const ms_io_driver_ops_t;
其中 ms_io_drv_type_t
驱动类型有以下几种:
类型 | 描述 |
---|---|
MS_IO_DRV_TYPE_CHR | 字符设备驱动 |
MS_IO_DRV_TYPE_BLK | 块设备驱动 |
MS_IO_DRV_TYPE_SOCK | socket 设备驱动 |
MS_IO_DRV_TYPE_FIFO | FIFO 设备驱动 |
ms_io_driver_t
设备驱动类型定义如下:
typedef struct ms_io_driver {
ms_io_name_node_t nnode; // 名字节点
ms_io_driver_ops_t *ops; // 设备驱动操作
} ms_io_driver_t;
ms_io_device_t
设备类型定义如下:
typedef struct ms_io_device {
ms_io_name_node_t nnode; // 名字节点
#if MS_CFG_KERN_PM_EN > 0
ms_list_head_t pm_node; // 电源管理节点
#endif
ms_io_driver_t *drv; // 驱动指针
ms_ptr_t ctx; // 设备上下文
ms_atomic_t ref; // 引用计数
} ms_io_device_t;
ms_io_fs_ops_t
文件系统操作类型定义如下:
typedef struct ms_io_fs_ops {
// 文件系统的类型
ms_io_fs_type_t type;
/*
* File system interfaces
*/
// 挂载
int (*mount)(ms_io_mnt_t *mnt, ms_io_device_t *dev, const char *dev_name, ms_const_ptr_t param);
// 卸载
int (*unmount)(ms_io_mnt_t *mnt, ms_const_ptr_t param);
// 格式化
int (*mkfs)(ms_io_mnt_t *mnt, ms_const_ptr_t param);
// 创建符号链接
int (*link)(ms_io_mnt_t *mnt, const char *path1, const char *path2);
// 删除文件
int (*unlink)(ms_io_mnt_t *mnt, const char *path);
// 创建目录
int (*mkdir)(ms_io_mnt_t *mnt, const char *path, ms_mode_t mode);
// 删除目录
int (*rmdir)(ms_io_mnt_t *mnt, const char *path);
// 文件重命名、移动
int (*rename)(ms_io_mnt_t *mnt, const char *old, const char *_new);
// 同步
int (*sync)(ms_io_mnt_t *mnt);
// 截断文件长度
int (*truncate)(ms_io_mnt_t *mnt, const char *path, ms_off_t len);
// 获得文件状态
int (*stat)(ms_io_mnt_t *mnt, const char *path, ms_stat_t *buf);
// 获得文件状态
int (*lstat)(ms_io_mnt_t *mnt, const char *path, ms_stat_t *buf);
// 获得文件系统状态
int (*statvfs)(ms_io_mnt_t *mnt, ms_statvfs_t *buf);
/*
* File interfaces
*/
// 打开文件
int (*open)(ms_io_mnt_t *mnt, ms_io_file_t *file, const char *path, int oflag, ms_mode_t mode);
// 关闭文件
int (*close)(ms_io_mnt_t *mnt, ms_io_file_t *file);
// 读文件
ms_ssize_t (*read)(ms_io_mnt_t *mnt, ms_io_file_t *file, ms_ptr_t buf, ms_size_t len);
// 写文件
ms_ssize_t (*write)(ms_io_mnt_t *mnt, ms_io_file_t *file, ms_const_ptr_t buf, ms_size_t len);
// IO 控制
int (*ioctl)(ms_io_mnt_t *mnt, ms_io_file_t *file, int cmd, ms_ptr_t arg);
// 控制文件
int (*fcntl)(ms_io_mnt_t *mnt, ms_io_file_t *file, int cmd, int arg);
// 获得文件状态
int (*fstat)(ms_io_mnt_t *mnt, ms_io_file_t *file, ms_stat_t *buf);
// 判断是不是一个 TTY 设备
int (*isatty)(ms_io_mnt_t *mnt, ms_io_file_t *file);
// 同步文件系统缓冲
int (*fsync)(ms_io_mnt_t *mnt, ms_io_file_t *file);
// 同步文件系统数据缓冲
int (*fdatasync)(ms_io_mnt_t *mnt, ms_io_file_t *file);
// 截断文件长度
int (*ftruncate)(ms_io_mnt_t *mnt, ms_io_file_t *file, ms_off_t len);
// 调整文件读写指针
ms_off_t (*lseek)(ms_io_mnt_t *mnt, ms_io_file_t *file, ms_off_t offset, int whence);
// 等待文件事件
int (*poll)(ms_io_mnt_t *mnt, ms_io_file_t *file, ms_pollfd_t *fds, ms_bool_t setup);
/*
* Directory interfaces
*/
// 打开目录
int (*opendir)(ms_io_mnt_t *mnt, ms_io_file_t *file, const char *path);
// 读目录项
int (*readdir_r)(ms_io_mnt_t *mnt, ms_io_file_t *file, ms_dirent_t *entry, ms_dirent_t **result);
// 重置目录流读指针
int (*rewinddir)(ms_io_mnt_t *mnt, ms_io_file_t *file);
// 调整目录流读指针
int (*seekdir)(ms_io_mnt_t *mnt, ms_io_file_t *file, long loc);
// 获得目录流读指针
long (*telldir)(ms_io_mnt_t *mnt, ms_io_file_t *file);
// 关闭目录
int (*closedir)(ms_io_mnt_t *mnt, ms_io_file_t *file);
} const ms_io_fs_ops_t;
其中 ms_io_fs_type_t
文件系统类型有以下几种:
类型 | 描述 |
---|---|
MS_IO_FS_TYPE_ROOTFS | 根文件系统 |
MS_IO_FS_TYPE_DEVFS | 设备文件系统 |
MS_IO_FS_TYPE_DISKFS | 磁盘文件系统 |
ms_io_fs_t
文件系统类型定义如下:
typedef struct ms_io_fs {
ms_io_name_node_t nnode; // 命名节点
ms_io_fs_ops_t *ops; // 文件系统操作
} ms_io_fs_t;
ms_io_mnt_t
挂载点类型定义如下:
typedef struct ms_io_mnt {
ms_io_name_node_t nnode; // 命名节点
ms_io_fs_t *fs; // 文件系统指针
ms_ptr_t ctx; // 挂载点上下文
ms_io_device_t *dev; // 块设备指针
ms_uint32_t ref; // 引用计数
ms_bool_t umount_req; // 是否有卸载请求
ms_const_ptr_t umount_param; // 文件系统 `unmount` 参数
ms_callback_t on_unmount; // 卸载时回调函数
ms_ptr_t on_unmount_arg; // 卸载时回调函数参数
} ms_io_mnt_t;
ms_io_file_t
ms_io_file_t
为 IO 系统打开的一个文件实例类型:
typedef struct ms_io_file {
ms_list_head_t node; // 命名节点
ms_io_mnt_t *mnt; // 挂载点指针
ms_ptr_t ctx; // 上下文
union {
ms_bool_t bool_info;
ms_uint8_t uint8_info;
ms_uint16_t uint16_info;
ms_uint32_t uint32_info;
ms_addr_t addr_info;
ms_ptr_t ptr_info;
ms_atomic_t atomic_info;
} u; // 用于记录不同的类型的信息
int flags; // 标志
ms_uint32_t ref; // 引用计数
ms_io_file_type_t type; // 类型
ms_bool_t close_req; // 是否有关闭请求
} ms_io_file_t;
其中 ms_io_file_type_t
文件实例类型有以下几种:
类型 | 描述 |
---|---|
MS_IO_FILE_TYPE_FREE | 空闲 |
MS_IO_FILE_TYPE_FILE | 普通文件 |
MS_IO_FILE_TYPE_SOCK | socket |
MS_IO_FILE_TYPE_FIFO | fifo |
MS_IO_FILE_TYPE_DIR | 目录 |
ms_io_job_t
ms_io_job_t
为 IO 工作类型:
typedef struct ms_io_job {
ms_list_head_t node;
const char *name;
ms_callback_t callback;
ms_ptr_t arg;
ms_tick_t remain;
ms_tick_t period;
ms_io_job_opt_t opt;
ms_io_job_status_t status;
ms_bool_t valid;
} ms_io_job_t;
其中 ms_io_job_opt_t
IO 工作选项类型有以下几种:
类型 | 描述 |
---|---|
MS_IO_JOB_OPT_ONE_SHOT | 单次工作 |
MS_IO_JOB_OPT_PERIODIC | 周期性工作 |
其中 ms_io_job_status_t
IO 工作状态类型有以下几种:
类型 | 描述 |
---|---|
MS_IO_JOB_STATUS_UNUSED | 未使用的 |
MS_IO_JOB_STATUS_STOP | 停止 |
MS_IO_JOB_STATUS_RUNNING | 正在运行 |
IO 子系统相关宏
定义 | 说明 |
---|---|
MS_IO_NAME_BUF_SIZE | 名字缓冲区大小 |
MS_IO_PATH_BUF_SIZE | 路径缓冲区大小 |
MS_IO_PATH_BUF_ALLOC(pathbuf) | 路径缓冲区分配 |
MS_IO_PATH_BUF_FREE(pathbuf) | 路径缓冲区释放 |
MS_IO_PATH_IS_ROOT(path) | 判断路径是不是根目录 |
MS_IO_DEF_POLLFD_SLOT_SIZE | 默认的 poll fd slot 大小 |
MS_IO_LOCK() | IO 子系统上锁 |
MS_IO_UNLOCK() | IO 子系统解锁 |
_MS_IO(x, y) | 普通 ioctl 命令 |
_MS_IOR(x, y, t) | 读数据的 ioctl 命令 |
_MS_IOW(x, y, t) | 写数据的 ioctl 命令 |
_MS_IORW(x, y, t) | 读写数据的 ioctl 命令 |
驱动程序的头文件可以使用类似如下的宏定义来定义设备支持的 ioctl 命令:
#define MS_UART_CMD_SET_PARAM _MS_IOW('u', 'a', ms_uart_param_t)
#define MS_UART_CMD_GET_PARAM _MS_IOR('u', 'a', ms_uart_param_t)
#define MS_UART_CMD_SET_R_TIMEOUT _MS_IOW('u', 't', ms_uint32_t)
#define MS_UART_CMD_GET_R_TIMEOUT _MS_IOR('u', 't', ms_uint32_t)
#define MS_UART_CMD_FLUSH_RX _MS_IO('u', 'f')
#define MS_UART_CMD_DRAIN_TX _MS_IO('u', 'd')
IO 子系统相关函数
命名节点相关函数:
// 注册命名节点到链表
ms_err_t ms_io_name_node_register(ms_list_head_t *list, ms_io_name_node_t *nnode);
// 卸载命名节点
ms_err_t ms_io_name_node_unregister(ms_list_head_t *list, ms_io_name_node_t *nnode);
// 获得第 n 个命名节点
ms_io_name_node_t *ms_io_name_node_get_by_index(ms_list_head_t *list, ms_uint32_t index);
// 检查指定名字的命名节点
ms_io_name_node_t *ms_io_name_node_find(ms_list_head_t *list, const char *name);
// 遍历命名节点
ms_err_t ms_io_name_node_traverse(ms_list_head_t *list, ms_io_name_node_callback_t callback, ms_ptr_t arg);
设备相关函数:
// 注册设备
ms_err_t ms_io_device_register(ms_io_device_t *dev, const char *dev_path, const char *drv_name, ms_ptr_t ctx);
// 卸载设备
ms_err_t ms_io_device_unregister(ms_io_device_t *dev);
// 文件转设备指针
#define MS_IO_FILE_TO_DEV(file) ((ms_io_device_t *)((file)->ctx))
// 通过文件获得设备引用计数指针
#define MS_IO_DEV_REF(file) (&(MS_IO_FILE_TO_DEV(file)->ref))
驱动相关函数:
// 注册驱动
ms_err_t ms_io_driver_register(ms_io_driver_t *drv);
文件系统相关函数:
// 注册文件系统
ms_err_t ms_io_fs_register(ms_io_fs_t *fs);
// 加入挂载点路径
const char *ms_io_path_add_mnt(const char *path);
// 文件模式转文件类型
ms_uint8_t ms_io_mode_to_type(ms_mode_t mode);
poll 相关函数:
// 设置 poll
int ms_io_poll_setup(ms_pollfd_t *fds, ms_nfds_t nfds, ms_handle_t semcid);
// 拆除 poll
int ms_io_poll_teardown(ms_pollfd_t *fds, ms_nfds_t nfds, int *count);
// poll 通知 helper
int ms_io_poll_notify_helper(ms_pollfd_t **slots, ms_nfds_t nslot, ms_pollevent_t event);
// poll helper
int ms_io_poll_helper(ms_pollfd_t *fds, ms_pollfd_t **slots, ms_nfds_t nslot, ms_bool_t setup, ms_ptr_t ctx,
ms_io_poll_func_t readable_check, ms_io_poll_func_t writable_check, ms_io_poll_func_t except_check);
IO 工作相关函数:
IO 工作一般用于检查 SD 是否插拨、网线是否插拨、传感器数据采集等,这些类型的工作可能并不需要很强的实时性,以亚秒级或秒级周期性工作,所有 IO 工作都工作在一个 IO 工作线程,所以 IO 工作处理完后应该退出以让其它的 IO 工作能按时运行。
// 初始化 IO 工作
ms_err_t ms_io_job_init(ms_io_job_t *iojob, const char *name, ms_callback_t callback, ms_ptr_t arg);
// 启动 IO 工作
ms_err_t ms_io_job_start(ms_io_job_t *iojob, ms_tick_t delay, ms_tick_t period, ms_io_job_opt_t opt);
// 停止 IO 工作
ms_err_t ms_io_job_stop(ms_io_job_t *iojob);