Browse Source

new:chardev的挂载

fslongjin 2 years ago
parent
commit
ef7d20c0fb

+ 9 - 0
kernel/common/stdlib.h

@@ -0,0 +1,9 @@
+#pragma once
+
+/**
+ * @brief 将长整型转换为字符串
+ * 
+ * @param input 输入的数据
+ * @return const char* 结果字符串
+ */
+const char* ltoa(long input);

+ 1 - 1
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);
     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;
     current_pcb->state = PROC_STOPPED;
     sched();
     sched();
 }
 }

+ 34 - 21
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};
 static struct vfs_filesystem_type_t vfs_fs = {"filesystem", 0};
 struct vfs_superblock_t *vfs_root_sb = NULL;
 struct vfs_superblock_t *vfs_root_sb = NULL;
 
 
+struct vfs_dir_entry_t *vfs_alloc_dentry(const int name_size);
+
 /**
 /**
  * @brief 挂载文件系统
  * @brief 挂载文件系统
  *
  *
@@ -166,11 +168,7 @@ struct vfs_dir_entry_t *vfs_path_walk(const char *path, uint64_t flags)
         // 如果没有找到dentry缓存,则申请新的dentry
         // 如果没有找到dentry缓存,则申请新的dentry
         if (dentry == NULL)
         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);
             memcpy(dentry->name, (void *)tmp_path, tmp_path_len);
             dentry->name[tmp_path_len] = '\0';
             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;
                 return NULL;
             }
             }
             // 找到子目录项
             // 找到子目录项
-            // 初始化子目录项的entry
-            list_init(&dentry->child_node_list);
-            list_init(&dentry->subdirs_list);
             dentry->parent = parent;
             dentry->parent = parent;
 
 
             list_add(&parent->subdirs_list, &dentry->child_node_list);
             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
  * @brief 填充dentry
  *
  *
+ * @return dirent的总大小
  */
  */
 int vfs_fill_dirent(void *buf, ino_t d_ino, char *name, int namelen, unsigned char type, off_t offset)
 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 创建文件夹
  * @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;
     uint32_t pathlen;
-    if (regs->cs & USER_CS)
+    if (from_userland)
         pathlen = strnlen_user(path, PAGE_4K_SIZE - 1);
         pathlen = strnlen_user(path, PAGE_4K_SIZE - 1);
     else
     else
         pathlen = strnlen(path, PAGE_4K_SIZE - 1);
         pathlen = strnlen(path, PAGE_4K_SIZE - 1);
@@ -279,7 +273,7 @@ uint64_t sys_mkdir(struct pt_regs *regs)
     memset(buf, 0, pathlen + 1);
     memset(buf, 0, pathlen + 1);
 
 
     // 拷贝字符串(不包含要被创建的部分)
     // 拷贝字符串(不包含要被创建的部分)
-    if (regs->cs & USER_CS)
+    if (from_userland)
         strncpy_from_user(buf, path, last_slash);
         strncpy_from_user(buf, path, last_slash);
     else
     else
         strncpy(buf, path, last_slash);
         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);
     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));
     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] == '/')
     if (path[pathlen - 1] == '/')
         subdir_dentry->name_length = pathlen - last_slash - 2;
         subdir_dentry->name_length = pathlen - last_slash - 2;
     else
     else
@@ -325,10 +320,29 @@ uint64_t sys_mkdir(struct pt_regs *regs)
     subdir_dentry->parent = parent_dir;
     subdir_dentry->parent = parent_dir;
     // kdebug("to mkdir, parent name=%s", parent_dir->name);
     // 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);
     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);
     // kdebug("retval = %d", retval);
     return 0;
     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 打开文件
  * @brief 打开文件
@@ -502,7 +516,6 @@ uint64_t do_open(const char *filename, int flags)
     }
     }
     // 保存文件描述符
     // 保存文件描述符
     f[fd_num] = file_ptr;
     f[fd_num] = file_ptr;
-
     return fd_num;
     return fd_num;
 }
 }
 
 

+ 11 - 1
kernel/filesystem/VFS/VFS.h

@@ -223,4 +223,14 @@ struct vfs_dir_entry_t *vfs_alloc_dentry(const int name_size);
  * @param flags 标志位
  * @param flags 标志位
  * @return uint64_t 错误码
  * @return uint64_t 错误码
  */
  */
-uint64_t do_open(const char *filename, int flags);
+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);

+ 16 - 1
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->dentry = old_dentry;
     mp->parent_dentry = old_dentry->parent;
     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);
     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结点
     // 将新的dentry的list结点替换掉父dentry的列表中的old_dentry的list结点
     list_replace(&old_dentry->child_node_list, &new_dentry->child_node_list);
     list_replace(&old_dentry->child_node_list, &new_dentry->child_node_list);
+
+    // 后挂载的dentry在链表的末尾(umount恢复的时候需要依赖这个性质)
     list_append(&mnt_list_head, &mp->mnt_list);
     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;
     return 0;
 }
 }

+ 9 - 1
kernel/filesystem/VFS/mount.h

@@ -26,4 +26,12 @@ int mount_init();
  * @param new_dentry 待挂载的新的dentry(需使用vfs_alloc_dentry来分配)
  * @param new_dentry 待挂载的新的dentry(需使用vfs_alloc_dentry来分配)
  * @return int 错误码
  * @return int 错误码
  */
  */
-int do_mount(struct vfs_dir_entry_t *old_dentry, struct vfs_dir_entry_t *new_dentry);
+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);

+ 81 - 2
kernel/filesystem/devfs/chardev.c

@@ -1,6 +1,85 @@
 #include "chardev.h"
 #include "chardev.h"
+#include "internal.h"
+#include <common/mutex.h>
+#include <common/stdlib.h>
+#include <common/string.h>
+#include <common/printk.h>
 
 
-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");
 }
 }

+ 2 - 1
kernel/filesystem/devfs/chardev.h

@@ -1,4 +1,5 @@
 #pragma once
 #pragma once
 
 
-#include <filesystem/VFS/VFS.h>
+#include "devfs.h"
+
 
 

+ 15 - 5
kernel/filesystem/devfs/devfs-types.h

@@ -3,23 +3,33 @@
 
 
 /**
 /**
  * @brief devfs_private_file_info_t的type字段值
  * @brief devfs_private_file_info_t的type字段值
- * 
+ *
  */
  */
 enum
 enum
 {
 {
     DEV_TYPE_UNDEF = 0,
     DEV_TYPE_UNDEF = 0,
     DEV_TYPE_CHAR = 1,
     DEV_TYPE_CHAR = 1,
+    DEV_TYPE_USB,
+    DEV_TYPE_BLOCK,
+    DEV_TYPE_NET,
+    DEV_TYPE_BUS,
+
 };
 };
 
 
 /**
 /**
  * @brief 字符设备的sub_type字段值
  * @brief 字符设备的sub_type字段值
- * 
+ *
  */
  */
 enum
 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, // 结束标志
 };
 };
 
 
 /**
 /**

+ 90 - 38
kernel/filesystem/devfs/devfs.c

@@ -1,17 +1,18 @@
 #include "devfs.h"
 #include "devfs.h"
+#include "internal.h"
 #include <filesystem/VFS/VFS.h>
 #include <filesystem/VFS/VFS.h>
 #include <common/glib.h>
 #include <common/glib.h>
 #include <common/string.h>
 #include <common/string.h>
 #include <mm/slab.h>
 #include <mm/slab.h>
 
 
-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;
 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_put_superblock(struct vfs_superblock_t *sb) {}
 
 
 static void devfs_write_inode(struct vfs_index_node_t *inode) {}
 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,
         .write_superblock = &devfs_write_superblock,
         .put_superblock = &devfs_put_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 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,
         .compare = &devfs_compare,
         .hash = &devfs_hash,
         .hash = &devfs_hash,
@@ -60,7 +61,10 @@ static struct vfs_dir_entry_operations_t devfs_dentry_ops =
         .iput = &devfs_iput,
         .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_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_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) {}
 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;
     ++file_ptr->position;
     // 获取目标dentry(由于是子目录项,因此是child_node_list)
     // 获取目标dentry(由于是子目录项,因此是child_node_list)
     struct vfs_dir_entry_t *target_dent = container_of(list, struct vfs_dir_entry_t, 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);
     // kdebug("target name=%s, namelen=%d", target_dent->name, target_dent->name_length);
 
 
     char *name = (char *)kzalloc(target_dent->name_length + 1, 0);
     char *name = (char *)kzalloc(target_dent->name_length + 1, 0);
@@ -101,7 +104,7 @@ failed:;
     return 0;
     return 0;
 }
 }
 
 
-static struct vfs_file_operations_t devfs_file_ops =
+struct vfs_file_operations_t devfs_file_ops =
     {
     {
         .open = &devfs_open,
         .open = &devfs_open,
         .close = &devfs_close,
         .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 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)
 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;
     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_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_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_getAttr(struct vfs_dir_entry_t *dEntry, uint64_t *attr) {}
 static long devfs_setAttr(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,
     .create = &devfs_create,
     .lookup = &devfs_lookup,
     .lookup = &devfs_lookup,
     .mkdir = &devfs_mkdir,
     .mkdir = &devfs_mkdir,
@@ -141,7 +170,7 @@ static struct vfs_inode_operations_t devfs_inode_ops = {
     .setAttr = &devfs_setAttr,
     .setAttr = &devfs_setAttr,
 };
 };
 
 
-static struct vfs_filesystem_type_t devfs_fs_type =
+struct vfs_filesystem_type_t devfs_fs_type =
     {
     {
         .name = "DEVFS",
         .name = "DEVFS",
         .fs_flags = 0,
         .fs_flags = 0,
@@ -151,6 +180,7 @@ static struct vfs_filesystem_type_t devfs_fs_type =
 
 
 static __always_inline void __devfs_init_root_inode()
 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->file_ops = &devfs_file_ops;
     devfs_root_dentry->dir_inode->inode_ops = &devfs_inode_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->child_node_list);
     list_init(&devfs_root_dentry->subdirs_list);
     list_init(&devfs_root_dentry->subdirs_list);
     devfs_root_dentry->dir_ops = &devfs_dentry_ops;
     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();
     __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
  * @brief 初始化devfs
  *
  *
@@ -201,7 +249,11 @@ void devfs_init()
 {
 {
     __devfs_init_root_dentry();
     __devfs_init_root_dentry();
     vfs_register_filesystem(&devfs_fs_type);
     vfs_register_filesystem(&devfs_fs_type);
-    vfs_mount_fs("/dev", "DEVFS", NULL);
+    vfs_mount_fs(__devfs_mount_path, "DEVFS", NULL);
+
+
+    __devfs_chardev_init();
 
 
-    devfs_register_device();
+    // todo: 当rootfs实现后,将ps/2键盘的注册改为在驱动程序中进行(目前没有rootfs,因此还不能在不依赖fat32的情况下,挂载设备)
+    devfs_register_device(DEV_TYPE_CHAR, CHAR_DEV_STYPE_PS2_KEYBOARD, &ps2_keyboard_fops);
 }
 }

+ 1 - 0
kernel/filesystem/devfs/devfs.h

@@ -1,5 +1,6 @@
 #pragma once
 #pragma once
 
 
+#include "devfs-types.h"
 
 
 /**
 /**
  * @brief 初始化devfs
  * @brief 初始化devfs

+ 109 - 0
kernel/filesystem/devfs/internal.h

@@ -0,0 +1,109 @@
+#pragma once
+
+#include "devfs.h"
+#include <common/string.h>
+
+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)

+ 2 - 1
kernel/filesystem/fat32/fat32.c

@@ -900,6 +900,7 @@ fail:;
  * @param inode 父目录的inode
  * @param inode 父目录的inode
  * @param dEntry 新的文件夹的dentry
  * @param dEntry 新的文件夹的dentry
  * @param mode 创建文件夹的mode
  * @param mode 创建文件夹的mode
+ * @return long 错误码
  */
  */
 int64_t fat32_mkdir(struct vfs_index_node_t *parent_inode, struct vfs_dir_entry_t *dEntry, int mode)
 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 file_ptr 文件结构体指针
  * @param dirent 返回的dirent
  * @param dirent 返回的dirent
  * @param filler 填充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)
 int64_t fat32_readdir(struct vfs_file_t *file_ptr, void *dirent, vfs_filldir_t filler)
 {
 {

+ 29 - 0
kernel/lib/stdlib.c

@@ -0,0 +1,29 @@
+#include <common/stdlib.h>
+
+/**
+ * @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;
+}

+ 1 - 1
kernel/syscall/syscall.c

@@ -425,7 +425,7 @@ uint64_t sys_chdir(struct pt_regs *regs)
  * @brief 获取目录中的数据
  * @brief 获取目录中的数据
  *
  *
  * @param fd 文件描述符号
  * @param fd 文件描述符号
- * @return uint64_t
+ * @return uint64_t dirent的总大小
  */
  */
 uint64_t sys_getdents(struct pt_regs *regs)
 uint64_t sys_getdents(struct pt_regs *regs)
 {
 {

+ 2 - 2
user/apps/shell/shell.c

@@ -86,9 +86,9 @@ void main_loop(int kb_fd)
 int main()
 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);
     int kb_fd = open(kb_file_path, 0);
-    // printf("keyboard fd = %d\n", kb_fd);
     print_ascii_logo();
     print_ascii_logo();
     // printf("before mkdir\n");
     // printf("before mkdir\n");
     // mkdir("/aaac", 0);
     // mkdir("/aaac", 0);