diff --git a/kernel/common/stdlib.h b/kernel/common/stdlib.h new file mode 100644 index 00000000..68bfc045 --- /dev/null +++ b/kernel/common/stdlib.h @@ -0,0 +1,9 @@ +#pragma once + +/** + * @brief 将长整型转换为字符串 + * + * @param input 输入的数据 + * @return const char* 结果字符串 + */ +const char* ltoa(long input); \ No newline at end of file diff --git a/kernel/exception/trap.c b/kernel/exception/trap.c index 9c6e435f..ad05edde 100644 --- a/kernel/exception/trap.c +++ b/kernel/exception/trap.c @@ -160,7 +160,7 @@ void do_stack_segment_fault(struct pt_regs *regs, unsigned long error_code) { kerror("do_stack_segment_fault(12),\tError Code:%#18lx,\tRSP:%#18lx,\tRIP:%#18lx\t CPU:%d\n", error_code, regs->rsp, regs->rip, proc_current_cpu_id); - + traceback(regs); current_pcb->state = PROC_STOPPED; sched(); } diff --git a/kernel/filesystem/VFS/VFS.c b/kernel/filesystem/VFS/VFS.c index 5bc589fd..c7d2d1d5 100644 --- a/kernel/filesystem/VFS/VFS.c +++ b/kernel/filesystem/VFS/VFS.c @@ -16,6 +16,8 @@ extern struct vfs_file_operations_t ps2_keyboard_fops; static struct vfs_filesystem_type_t vfs_fs = {"filesystem", 0}; struct vfs_superblock_t *vfs_root_sb = NULL; +struct vfs_dir_entry_t *vfs_alloc_dentry(const int name_size); + /** * @brief 挂载文件系统 * @@ -166,11 +168,7 @@ struct vfs_dir_entry_t *vfs_path_walk(const char *path, uint64_t flags) // 如果没有找到dentry缓存,则申请新的dentry if (dentry == NULL) { - dentry = (struct vfs_dir_entry_t *)kzalloc(sizeof(struct vfs_dir_entry_t), 0); - // 为目录项的名称分配内存 - dentry->name = (char *)kmalloc(tmp_path_len + 1, 0); - // 貌似这里不需要memset,因为空间会被覆盖 - // memset(dentry->name, 0, tmp_path_len+1); + dentry = vfs_alloc_dentry(tmp_path_len+1); memcpy(dentry->name, (void *)tmp_path, tmp_path_len); dentry->name[tmp_path_len] = '\0'; @@ -186,9 +184,6 @@ struct vfs_dir_entry_t *vfs_path_walk(const char *path, uint64_t flags) return NULL; } // 找到子目录项 - // 初始化子目录项的entry - list_init(&dentry->child_node_list); - list_init(&dentry->subdirs_list); dentry->parent = parent; list_add(&parent->subdirs_list, &dentry->child_node_list); @@ -214,6 +209,7 @@ struct vfs_dir_entry_t *vfs_path_walk(const char *path, uint64_t flags) /** * @brief 填充dentry * + * @return dirent的总大小 */ int vfs_fill_dirent(void *buf, ino_t d_ino, char *name, int namelen, unsigned char type, off_t offset) { @@ -240,18 +236,16 @@ int vfs_fill_dirent(void *buf, ino_t d_ino, char *name, int namelen, unsigned ch /** * @brief 创建文件夹 - * - * @param path(r8) 路径 - * @param mode(r9) 模式 - * @return uint64_t + * + * @param path 文件夹路径 + * @param mode 创建模式 + * @param from_userland 该创建请求是否来自用户态 + * @return int64_t 错误码 */ -uint64_t sys_mkdir(struct pt_regs *regs) +int64_t vfs_mkdir(const char* path, mode_t mode, bool from_userland) { - const char *path = (const char *)regs->r8; - // kdebug("path = %s", path); - mode_t mode = (mode_t)regs->r9; uint32_t pathlen; - if (regs->cs & USER_CS) + if (from_userland) pathlen = strnlen_user(path, PAGE_4K_SIZE - 1); else pathlen = strnlen(path, PAGE_4K_SIZE - 1); @@ -279,7 +273,7 @@ uint64_t sys_mkdir(struct pt_regs *regs) memset(buf, 0, pathlen + 1); // 拷贝字符串(不包含要被创建的部分) - if (regs->cs & USER_CS) + if (from_userland) strncpy_from_user(buf, path, last_slash); else strncpy(buf, path, last_slash); @@ -306,7 +300,8 @@ uint64_t sys_mkdir(struct pt_regs *regs) struct vfs_dir_entry_t *subdir_dentry = (struct vfs_dir_entry_t *)kmalloc(sizeof(struct vfs_dir_entry_t), 0); memset((void *)subdir_dentry, 0, sizeof(struct vfs_dir_entry_t)); - + list_init(&subdir_dentry->subdirs_list); + list_init(&subdir_dentry->child_node_list); if (path[pathlen - 1] == '/') subdir_dentry->name_length = pathlen - last_slash - 2; else @@ -325,10 +320,29 @@ uint64_t sys_mkdir(struct pt_regs *regs) subdir_dentry->parent = parent_dir; // kdebug("to mkdir, parent name=%s", parent_dir->name); int retval = parent_dir->dir_inode->inode_ops->mkdir(parent_dir->dir_inode, subdir_dentry, 0); - list_add(&parent_dir->subdirs_list, &subdir_dentry->child_node_list); + list_append(&parent_dir->subdirs_list, &subdir_dentry->child_node_list); // kdebug("retval = %d", retval); return 0; } +/** + * @brief 创建文件夹 + * + * @param path(r8) 路径 + * @param mode(r9) 模式 + * @return uint64_t + */ +uint64_t sys_mkdir(struct pt_regs *regs) +{ + const char *path = (const char *)regs->r8; + // kdebug("path = %s", path); + mode_t mode = (mode_t)regs->r9; + + if (regs->cs & USER_CS) + return vfs_mkdir(path, mode, true); + else + return vfs_mkdir(path, mode, false); + +} /** * @brief 打开文件 @@ -502,7 +516,6 @@ uint64_t do_open(const char *filename, int flags) } // 保存文件描述符 f[fd_num] = file_ptr; - return fd_num; } diff --git a/kernel/filesystem/VFS/VFS.h b/kernel/filesystem/VFS/VFS.h index 8bb1bbaa..13419849 100644 --- a/kernel/filesystem/VFS/VFS.h +++ b/kernel/filesystem/VFS/VFS.h @@ -223,4 +223,14 @@ struct vfs_dir_entry_t *vfs_alloc_dentry(const int name_size); * @param flags 标志位 * @return uint64_t 错误码 */ -uint64_t do_open(const char *filename, int flags); \ No newline at end of file +uint64_t do_open(const char *filename, int flags); + +/** + * @brief 创建文件夹 + * + * @param path 文件夹路径 + * @param mode 创建模式 + * @param from_userland 该创建请求是否来自用户态 + * @return int64_t 错误码 + */ +int64_t vfs_mkdir(const char* path, mode_t mode, bool from_userland); \ No newline at end of file diff --git a/kernel/filesystem/VFS/mount.c b/kernel/filesystem/VFS/mount.c index 0d55b275..af67d385 100644 --- a/kernel/filesystem/VFS/mount.c +++ b/kernel/filesystem/VFS/mount.c @@ -30,7 +30,7 @@ int do_mount(struct vfs_dir_entry_t *old_dentry, struct vfs_dir_entry_t *new_den mp->dentry = old_dentry; mp->parent_dentry = old_dentry->parent; - kdebug("&new_dentry->name=%#018lx, &old_dentry->name=%#018lx", &new_dentry->name, &old_dentry->name); + // kdebug("&new_dentry->name=%#018lx, &old_dentry->name=%#018lx", &new_dentry->name, &old_dentry->name); // 拷贝名称 strncpy(new_dentry->name, old_dentry->name, old_dentry->name_length); @@ -41,7 +41,22 @@ int do_mount(struct vfs_dir_entry_t *old_dentry, struct vfs_dir_entry_t *new_den // 将新的dentry的list结点替换掉父dentry的列表中的old_dentry的list结点 list_replace(&old_dentry->child_node_list, &new_dentry->child_node_list); + + // 后挂载的dentry在链表的末尾(umount恢复的时候需要依赖这个性质) list_append(&mnt_list_head, &mp->mnt_list); + return 0; +} + +/** + * @brief 取消某个文件系统的挂载 + * + * @param dentry 对应文件系统的根dentry + * @return int 错误码 + */ +int do_umount(struct vfs_dir_entry_t* dentry) +{ + // todo: 实现umount(主要是结点的恢复问题) + return 0; } \ No newline at end of file diff --git a/kernel/filesystem/VFS/mount.h b/kernel/filesystem/VFS/mount.h index 13ec7d55..1c532023 100644 --- a/kernel/filesystem/VFS/mount.h +++ b/kernel/filesystem/VFS/mount.h @@ -26,4 +26,12 @@ int mount_init(); * @param new_dentry 待挂载的新的dentry(需使用vfs_alloc_dentry来分配) * @return int 错误码 */ -int do_mount(struct vfs_dir_entry_t *old_dentry, struct vfs_dir_entry_t *new_dentry); \ No newline at end of file +int do_mount(struct vfs_dir_entry_t *old_dentry, struct vfs_dir_entry_t *new_dentry); + +/** + * @brief 取消某个文件系统的挂载 + * + * @param dentry 对应文件系统的根dentry + * @return int 错误码 + */ +int do_umount(struct vfs_dir_entry_t* dentry); \ No newline at end of file diff --git a/kernel/filesystem/devfs/chardev.c b/kernel/filesystem/devfs/chardev.c index a1595630..5a220ca4 100644 --- a/kernel/filesystem/devfs/chardev.c +++ b/kernel/filesystem/devfs/chardev.c @@ -1,6 +1,85 @@ #include "chardev.h" +#include "internal.h" +#include +#include +#include +#include -int chardev_register() +static struct vfs_dir_entry_t *chardev_folder_dentry = NULL; +extern struct vfs_dir_entry_t *devfs_root_dentry; + +/** + * @brief 字符设备名称前缀 + * + */ +static char chardev_name_prefix[CHAR_DEV_STYPE_END + 1][32] = { + [CHAR_DEV_STYPE_START] = "", + [CHAR_DEV_STYPE_PS2_KEYBOARD] = "ps2.kb", + [CHAR_DEV_STYPE_PS2_MOUSE] = "ps2.mse", + [CHAR_DEV_STYPE_USB_MOUSE] = "usb.mse", + [CHAR_DEV_STYPE_USB_KEYBOARD] = "usb.kb", + [CHAR_DEV_STYPE_BLUETOOTH_MOUSE] = "bt.mse", + [CHAR_DEV_STYPE_BLUETOOTH_KEYBOARD] = "bt.kb", + [CHAR_DEV_STYPE_END] = "", +}; +/** + * @brief 为不同类型的字符设备分配的管理信息结构体 + * + */ +static struct chardev_manage_info_t { - + mutex_t lock; // 操作互斥锁 + int count; +} chardev_manage_info[CHAR_DEV_STYPE_END + 1]; + +/** + * @brief 在devfs中注册字符设备(该函数只应被devfs调用) + * + * @param private_info inode私有信息 + * @param target_dentry 返回的dentry的指针 + * @return int 错误码 + */ +int __devfs_chardev_register(struct devfs_private_inode_info_t *private_info, struct vfs_dir_entry_t **target_dentry) +{ + // 检测subtype是否合法 + if (private_info->sub_type <= CHAR_DEV_STYPE_START || private_info->sub_type >= CHAR_DEV_STYPE_END) + return -EINVAL; + mutex_lock(&chardev_manage_info[private_info->sub_type].lock); + + // 拷贝名称 + char devname[64] = {0}; + strcpy(devname, chardev_name_prefix[private_info->sub_type]); + char *ptr = devname + strlen(chardev_name_prefix[private_info->sub_type]); + sprintk(ptr, "%d", chardev_manage_info[private_info->sub_type].count); + int namelen = strlen(devname); + + struct vfs_dir_entry_t *dentry = vfs_alloc_dentry(namelen + 1); + __devfs_fill_dentry(dentry, devname); + __devfs_fill_inode(dentry, __devfs_alloc_inode(), VFS_ATTR_DEVICE, private_info); + + // 将dentry挂载到char文件夹下 + __devfs_dentry_bind_parent(chardev_folder_dentry, dentry); + + ++chardev_manage_info[private_info->sub_type].count; + mutex_unlock(&chardev_manage_info[private_info->sub_type].lock); + *target_dentry = dentry; + return 0; +} + +/** + * @brief 初始化chardev管理机制 + * + */ +void __devfs_chardev_init() +{ + // 初始化管理信息结构体 + for (int i = CHAR_DEV_STYPE_START + 1; i < CHAR_DEV_STYPE_END; ++i) + { + mutex_init(&chardev_manage_info[i].lock); + chardev_manage_info[i].count = 0; + } + + vfs_mkdir("/dev/char", 0, false); + // 获取char dev的dentry + chardev_folder_dentry = __devfs_find_dir(devfs_root_dentry, "char"); } \ No newline at end of file diff --git a/kernel/filesystem/devfs/chardev.h b/kernel/filesystem/devfs/chardev.h index 54dd7d38..af4a6546 100644 --- a/kernel/filesystem/devfs/chardev.h +++ b/kernel/filesystem/devfs/chardev.h @@ -1,4 +1,5 @@ #pragma once -#include +#include "devfs.h" + diff --git a/kernel/filesystem/devfs/devfs-types.h b/kernel/filesystem/devfs/devfs-types.h index 909adf0e..8efdb88c 100644 --- a/kernel/filesystem/devfs/devfs-types.h +++ b/kernel/filesystem/devfs/devfs-types.h @@ -3,23 +3,33 @@ /** * @brief devfs_private_file_info_t的type字段值 - * + * */ enum { DEV_TYPE_UNDEF = 0, DEV_TYPE_CHAR = 1, + DEV_TYPE_USB, + DEV_TYPE_BLOCK, + DEV_TYPE_NET, + DEV_TYPE_BUS, + }; /** * @brief 字符设备的sub_type字段值 - * + * */ enum { - CHAR_DEV_STYPE_PS2 = 1, - CHAR_DEV_STYPE_USB, - CHAR_DEV_STYPE_BLUETOOTH, + CHAR_DEV_STYPE_START = 0, + CHAR_DEV_STYPE_PS2_KEYBOARD = 1, + CHAR_DEV_STYPE_USB_KEYBOARD, + CHAR_DEV_STYPE_PS2_MOUSE, + CHAR_DEV_STYPE_USB_MOUSE, + CHAR_DEV_STYPE_BLUETOOTH_MOUSE, + CHAR_DEV_STYPE_BLUETOOTH_KEYBOARD, + CHAR_DEV_STYPE_END, // 结束标志 }; /** diff --git a/kernel/filesystem/devfs/devfs.c b/kernel/filesystem/devfs/devfs.c index 8e252c42..3d367a07 100644 --- a/kernel/filesystem/devfs/devfs.c +++ b/kernel/filesystem/devfs/devfs.c @@ -1,17 +1,18 @@ #include "devfs.h" +#include "internal.h" #include #include #include #include -static struct vfs_super_block_operations_t devfs_sb_ops; -static struct vfs_dir_entry_operations_t devfs_dentry_ops; -static struct vfs_file_operations_t devfs_file_ops; -static struct vfs_inode_operations_t devfs_inode_ops; - -static struct vfs_dir_entry_t *devfs_root_dentry; // 根结点的dentry -static struct vfs_superblock_t devfs_sb = {0}; +struct vfs_super_block_operations_t devfs_sb_ops; +struct vfs_dir_entry_operations_t devfs_dentry_ops; +struct vfs_file_operations_t devfs_file_ops; +struct vfs_inode_operations_t devfs_inode_ops; +struct vfs_dir_entry_t *devfs_root_dentry; // 根结点的dentry +struct vfs_superblock_t devfs_sb = {0}; +const char __devfs_mount_path[] = "/dev"; extern struct vfs_file_operations_t ps2_keyboard_fops; /** @@ -37,7 +38,7 @@ static void devfs_write_superblock(struct vfs_superblock_t *sb) {} static void devfs_put_superblock(struct vfs_superblock_t *sb) {} static void devfs_write_inode(struct vfs_index_node_t *inode) {} -static struct vfs_super_block_operations_t devfs_sb_ops = +struct vfs_super_block_operations_t devfs_sb_ops = { .write_superblock = &devfs_write_superblock, .put_superblock = &devfs_put_superblock, @@ -52,7 +53,7 @@ static long devfs_release(struct vfs_dir_entry_t *dEntry) {} static long devfs_iput(struct vfs_dir_entry_t *dEntry, struct vfs_index_node_t *inode) {} -static struct vfs_dir_entry_operations_t devfs_dentry_ops = +struct vfs_dir_entry_operations_t devfs_dentry_ops = { .compare = &devfs_compare, .hash = &devfs_hash, @@ -60,7 +61,10 @@ static struct vfs_dir_entry_operations_t devfs_dentry_ops = .iput = &devfs_iput, }; -static long devfs_open(struct vfs_index_node_t *inode, struct vfs_file_t *file_ptr) { return 0; } +static long devfs_open(struct vfs_index_node_t *inode, struct vfs_file_t *file_ptr) +{ + return 0; +} static long devfs_close(struct vfs_index_node_t *inode, struct vfs_file_t *file_ptr) {} static long devfs_read(struct vfs_file_t *file_ptr, char *buf, int64_t count, long *position) {} static long devfs_write(struct vfs_file_t *file_ptr, char *buf, int64_t count, long *position) {} @@ -85,7 +89,6 @@ static long devfs_readdir(struct vfs_file_t *file_ptr, void *dirent, vfs_filldir ++file_ptr->position; // 获取目标dentry(由于是子目录项,因此是child_node_list) struct vfs_dir_entry_t *target_dent = container_of(list, struct vfs_dir_entry_t, child_node_list); - // kdebug("target name=%s, namelen=%d", target_dent->name, target_dent->name_length); char *name = (char *)kzalloc(target_dent->name_length + 1, 0); @@ -101,7 +104,7 @@ failed:; return 0; } -static struct vfs_file_operations_t devfs_file_ops = +struct vfs_file_operations_t devfs_file_ops = { .open = &devfs_open, .close = &devfs_close, @@ -121,17 +124,43 @@ static struct vfs_file_operations_t devfs_file_ops = static long devfs_create(struct vfs_index_node_t *parent_inode, struct vfs_dir_entry_t *dest_dEntry, int mode) { } + static struct vfs_dir_entry_t *devfs_lookup(struct vfs_index_node_t *parent_inode, struct vfs_dir_entry_t *dest_dEntry) { - kdebug("devfs_lookup: %s", dest_dEntry->name); + /* + 由于devfs是伪文件系统,其所有的搜索都依赖于dentry缓存。 + 因此,不需要根据inode来搜索目标目录项。除非目录项不存在,否则不会调用这个函数。 + 当本函数调用的时候,也就意味着devfs中没有这个文件/文件夹。 + 综上,本函数直接返回NULL即可 + */ return NULL; } -static long devfs_mkdir(struct vfs_index_node_t *inode, struct vfs_dir_entry_t *dEntry, int mode) {} +/** + * @brief 在devfs中创建文件夹(作用是完善子文件夹的inode信息) + * + * @param inode 父目录的inode + * @param dEntry 目标dentry + * @param mode 创建模式 + * @return long 错误码 + */ +static long devfs_mkdir(struct vfs_index_node_t *inode, struct vfs_dir_entry_t *dEntry, int mode) +{ + dEntry->dir_inode = (struct vfs_index_node_t *)kzalloc(sizeof(struct vfs_index_node_t), 0); + dEntry->dir_inode->file_ops = &devfs_file_ops; + dEntry->dir_inode->inode_ops = &devfs_inode_ops; + + // todo: 增加private inode info + dEntry->dir_inode->private_inode_info = NULL; + dEntry->dir_inode->sb = &devfs_sb; + dEntry->dir_inode->attribute = VFS_ATTR_DIR; + return 0; +} + static long devfs_rmdir(struct vfs_index_node_t *inode, struct vfs_dir_entry_t *dEntry) {} static long devfs_rename(struct vfs_index_node_t *old_inode, struct vfs_dir_entry_t *old_dEntry, struct vfs_index_node_t *new_inode, struct vfs_dir_entry_t *new_dEntry) {} static long devfs_getAttr(struct vfs_dir_entry_t *dEntry, uint64_t *attr) {} static long devfs_setAttr(struct vfs_dir_entry_t *dEntry, uint64_t *attr) {} -static struct vfs_inode_operations_t devfs_inode_ops = { +struct vfs_inode_operations_t devfs_inode_ops = { .create = &devfs_create, .lookup = &devfs_lookup, .mkdir = &devfs_mkdir, @@ -141,7 +170,7 @@ static struct vfs_inode_operations_t devfs_inode_ops = { .setAttr = &devfs_setAttr, }; -static struct vfs_filesystem_type_t devfs_fs_type = +struct vfs_filesystem_type_t devfs_fs_type = { .name = "DEVFS", .fs_flags = 0, @@ -151,6 +180,7 @@ static struct vfs_filesystem_type_t devfs_fs_type = static __always_inline void __devfs_init_root_inode() { + devfs_root_dentry->dir_inode = (struct vfs_index_node_t *)kzalloc(sizeof(struct vfs_index_node_t), 0); devfs_root_dentry->dir_inode->file_ops = &devfs_file_ops; devfs_root_dentry->dir_inode->inode_ops = &devfs_inode_ops; @@ -168,31 +198,49 @@ static __always_inline void __devfs_init_root_dentry() list_init(&devfs_root_dentry->child_node_list); list_init(&devfs_root_dentry->subdirs_list); devfs_root_dentry->dir_ops = &devfs_dentry_ops; - devfs_root_dentry->dir_inode = (struct vfs_index_node_t *)kzalloc(sizeof(struct vfs_index_node_t), 0); + __devfs_init_root_inode(); } -int devfs_register_device() +/** + * @brief 在devfs中注册设备 + * + * @param name + * @param device_type + * @param sub_type + * @param file_ops + * @return int + */ +int devfs_register_device(uint16_t device_type, uint16_t sub_type, struct vfs_file_operations_t *file_ops) { - // 暂时只支持键盘文件 - char name[] = "keyboard.dev"; - struct vfs_dir_entry_t *dentry = vfs_alloc_dentry(sizeof(name)); - strcpy(dentry->name, name); - dentry->name_length = strlen(name); - dentry->dir_inode = (struct vfs_index_node_t *)kzalloc(sizeof(struct vfs_index_node_t), 0); - dentry->dir_ops = &devfs_dentry_ops; - dentry->dir_inode->file_ops = &ps2_keyboard_fops; - dentry->dir_inode->inode_ops = &devfs_inode_ops; - dentry->dir_inode->private_inode_info = NULL; // todo: - dentry->dir_inode->sb = &devfs_sb; - dentry->dir_inode->attribute = VFS_ATTR_DEVICE; - dentry->parent = devfs_root_dentry; - list_init(&dentry->child_node_list); - list_init(&dentry->subdirs_list); - list_append(&devfs_root_dentry->subdirs_list, &dentry->child_node_list); - kdebug("add dev: %s", dentry->name); - // devfs_create(&devfs_root_dentry->dir_inode, dentry->dir_inode, 0); + int retval = 0; + // 申请private info结构体 + struct devfs_private_inode_info_t *private_info = (struct devfs_private_inode_info_t *)kzalloc(sizeof(struct devfs_private_inode_info_t), 0); + private_info->f_ops = file_ops; + private_info->type = device_type; + private_info->sub_type = sub_type; + + struct vfs_dir_entry_t *dentry = NULL; // 该指针由对应类型设备的注册函数设置 + + switch (device_type) + { + case DEV_TYPE_CHAR: + retval = __devfs_chardev_register(private_info, &dentry); + break; + + default: + kerror("Unsupported device type [ %d ].", device_type); + retval = -ENOTSUP; + goto failed; + break; + } + + return retval; +failed:; + kfree(private_info); + return retval; } + /** * @brief 初始化devfs * @@ -201,7 +249,11 @@ void devfs_init() { __devfs_init_root_dentry(); vfs_register_filesystem(&devfs_fs_type); - vfs_mount_fs("/dev", "DEVFS", NULL); + vfs_mount_fs(__devfs_mount_path, "DEVFS", NULL); - devfs_register_device(); + + __devfs_chardev_init(); + + // todo: 当rootfs实现后,将ps/2键盘的注册改为在驱动程序中进行(目前没有rootfs,因此还不能在不依赖fat32的情况下,挂载设备) + devfs_register_device(DEV_TYPE_CHAR, CHAR_DEV_STYPE_PS2_KEYBOARD, &ps2_keyboard_fops); } \ No newline at end of file diff --git a/kernel/filesystem/devfs/devfs.h b/kernel/filesystem/devfs/devfs.h index 0436578a..b5be25c2 100644 --- a/kernel/filesystem/devfs/devfs.h +++ b/kernel/filesystem/devfs/devfs.h @@ -1,5 +1,6 @@ #pragma once +#include "devfs-types.h" /** * @brief 初始化devfs diff --git a/kernel/filesystem/devfs/internal.h b/kernel/filesystem/devfs/internal.h new file mode 100644 index 00000000..f0dfad53 --- /dev/null +++ b/kernel/filesystem/devfs/internal.h @@ -0,0 +1,109 @@ +#pragma once + +#include "devfs.h" +#include + +extern struct vfs_super_block_operations_t devfs_sb_ops; +extern struct vfs_dir_entry_operations_t devfs_dentry_ops; +extern struct vfs_file_operations_t devfs_file_ops; +extern struct vfs_inode_operations_t devfs_inode_ops; +extern struct vfs_superblock_t devfs_sb; + +// 分配inode +#define __devfs_alloc_inode() ((struct vfs_index_node_t *)kzalloc(sizeof(struct vfs_index_node_t), 0)) + +/** + * @brief 在devfs中注册字符设备(该函数只应被devfs调用) + * + * @param private_info inode私有信息 + * @param target_dentry 返回的dentry的指针 + * @return int 错误码 + */ +int __devfs_chardev_register(struct devfs_private_inode_info_t *private_info, struct vfs_dir_entry_t **target_dentry); + +/** + * @brief 初始化chardev管理机制 + * + */ +void __devfs_chardev_init(); + +/** + * @brief 在父dentry中寻找子dentry + * + * @param parent_dentry 父dentry结点 + * @param name 子目录项名称 + * @return struct vfs_dir_entry_t* + */ +static inline struct vfs_dir_entry_t *__devfs_find_dentry(struct vfs_dir_entry_t *parent_dentry, const char *name) +{ + struct List *list = &parent_dentry->subdirs_list; + while (list_next(list) != &parent_dentry->subdirs_list) + { + list = list_next(list); + // 获取目标dentry(由于是子目录项,因此是child_node_list) + struct vfs_dir_entry_t *target_dent = container_of(list, struct vfs_dir_entry_t, child_node_list); + if (strcmp(target_dent->name, name) == 0) + return target_dent; + } + return NULL; +} + +/** + * @brief 在父目录下查找子目录 + * + * @param parent_dentry 父目录 + * @param name 子目录名 + * @return struct vfs_dir_entry_t* 子目录的dentry (找不到则返回NULL) + */ +static inline struct vfs_dir_entry_t *__devfs_find_dir(struct vfs_dir_entry_t *parent_dentry, const char *name) +{ + struct vfs_dir_entry_t *target_dent = __devfs_find_dentry(parent_dentry, name); + if (target_dent->dir_inode->attribute & VFS_ATTR_DIR) // 名称相符且为目录,则返回dentry + return target_dent; + else + return NULL; // 否则直接返回空 +} + +/** + * @brief 将dentry和inode进行绑定,并填充inode + * + * @param dentry 目标dentry + * @param inode 目标inode + * @param inode_attr inode的属性 + * @param private_inode_data inode私有信息 + */ +static inline void __devfs_fill_inode(struct vfs_dir_entry_t *dentry, struct vfs_index_node_t *inode, uint64_t inode_attr, struct devfs_private_inode_info_t *private_inode_data) +{ + dentry->dir_inode = inode; + dentry->dir_inode->file_ops = private_inode_data->f_ops; + dentry->dir_inode->inode_ops = &devfs_inode_ops; + + dentry->dir_inode->private_inode_info = private_inode_data; + dentry->dir_inode->sb = &devfs_sb; + dentry->dir_inode->attribute = inode_attr; +} + +/** + * @brief 填充dentry中的内容 + * + * @param dentry 待填充的dentry + * @param name dentry名称 + */ +static inline void __devfs_fill_dentry(struct vfs_dir_entry_t *dentry, const char *name) +{ + strcpy(dentry->name, name); + dentry->name_length = strlen(name); + dentry->dir_ops = &devfs_dentry_ops; +} + +/** + * @brief 将dentry与父dentry进行绑定 + * @param parent 父目录项 + * @param dentry 子目录项 + */ +#define __devfs_dentry_bind_parent(parent_dentry, dentry) \ + do \ + { \ + (dentry)->parent = (parent_dentry); \ + list_append(&((parent_dentry)->subdirs_list), &((dentry)->child_node_list)); \ + } while (0) \ No newline at end of file diff --git a/kernel/filesystem/fat32/fat32.c b/kernel/filesystem/fat32/fat32.c index 6b907e64..21db82e0 100644 --- a/kernel/filesystem/fat32/fat32.c +++ b/kernel/filesystem/fat32/fat32.c @@ -900,6 +900,7 @@ fail:; * @param inode 父目录的inode * @param dEntry 新的文件夹的dentry * @param mode 创建文件夹的mode + * @return long 错误码 */ int64_t fat32_mkdir(struct vfs_index_node_t *parent_inode, struct vfs_dir_entry_t *dEntry, int mode) { @@ -1053,7 +1054,7 @@ int64_t fat32_setAttr(struct vfs_dir_entry_t *dEntry, uint64_t *attr) * @param file_ptr 文件结构体指针 * @param dirent 返回的dirent * @param filler 填充dirent的函数 - * @return int64_t + * @return uint64_t dirent的总大小 */ int64_t fat32_readdir(struct vfs_file_t *file_ptr, void *dirent, vfs_filldir_t filler) { diff --git a/kernel/lib/stdlib.c b/kernel/lib/stdlib.c new file mode 100644 index 00000000..6e03bd45 --- /dev/null +++ b/kernel/lib/stdlib.c @@ -0,0 +1,29 @@ +#include + +/** + * @brief 将长整型转换为字符串 + * + * @param input 输入的数据 + * @return const char* 结果字符串 + */ +const char *ltoa(long input) +{ + /* large enough for -9223372036854775808 */ + static char buffer[21] = {0}; + char *pos = buffer + sizeof(buffer) - 1; + int neg = input < 0; + unsigned long n = neg ? -input : input; + + *pos-- = '\0'; + do + { + *pos-- = '0' + n % 10; + n /= 10; + if (pos < buffer) + return pos + 1; + } while (n); + + if (neg) + *pos-- = '-'; + return pos + 1; +} \ No newline at end of file diff --git a/kernel/syscall/syscall.c b/kernel/syscall/syscall.c index 0098c451..de7ad2d1 100644 --- a/kernel/syscall/syscall.c +++ b/kernel/syscall/syscall.c @@ -425,7 +425,7 @@ uint64_t sys_chdir(struct pt_regs *regs) * @brief 获取目录中的数据 * * @param fd 文件描述符号 - * @return uint64_t + * @return uint64_t dirent的总大小 */ uint64_t sys_getdents(struct pt_regs *regs) { diff --git a/user/apps/shell/shell.c b/user/apps/shell/shell.c index 0cb915df..fb1c4c60 100644 --- a/user/apps/shell/shell.c +++ b/user/apps/shell/shell.c @@ -86,9 +86,9 @@ void main_loop(int kb_fd) int main() { // 打开键盘文件 - char kb_file_path[] = "/dev/keyboard.dev"; + char kb_file_path[] = "/dev/char/ps2.kb0"; + int kb_fd = open(kb_file_path, 0); - // printf("keyboard fd = %d\n", kb_fd); print_ascii_logo(); // printf("before mkdir\n"); // mkdir("/aaac", 0);