Bladeren bron

new: 在devfs中使用键盘文件(仍存在bug)

fslongjin 2 jaren geleden
bovenliggende
commit
d7423f36be

+ 20 - 0
kernel/common/glib.h

@@ -138,6 +138,26 @@ static inline void list_del(struct List *entry)
     entry->prev->next = entry->next;
 }
 
+/**
+ * @brief 将新的链表结点替换掉旧的链表结点,并使得旧的结点的前后指针均为NULL
+ * 
+ * @param old 要被替换的结点
+ * @param new 新的要换上去的结点
+ */
+static inline void list_replace(struct List* old, struct List * new)
+{
+    if(old->prev!=NULL)
+        old->prev->next=new;
+    new->prev = old->prev;
+    if(old->next!=NULL)
+        old->next->prev = new;
+    new->next = old->next;
+
+    old->prev = NULL;
+    old->next = NULL;
+}
+
+
 static inline bool list_empty(struct List *entry)
 {
     /**

+ 1 - 1
kernel/common/string.c

@@ -39,7 +39,7 @@ long strnlen(const char *src, unsigned long maxlen)
         FirstPart < SecondPart => -1
 */
 
-int strcmp(char *FirstPart, char *SecondPart)
+int strcmp(const char *FirstPart, const char *SecondPart)
 {
     register int __res;
     __asm__ __volatile__("cld	\n\t"

+ 1 - 1
kernel/common/string.h

@@ -38,7 +38,7 @@ long strnlen(const char *src, unsigned long maxlen);
         FirstPart < SecondPart => -1
 */
 
-int strcmp(char *FirstPart, char *SecondPart);
+int strcmp(const char *FirstPart, const char *SecondPart);
 
 char *strncpy(char *dst, const char *src, long count);
 

+ 302 - 26
kernel/filesystem/VFS/VFS.c

@@ -1,4 +1,5 @@
 #include "VFS.h"
+#include "mount.h"
 #include <common/kprint.h>
 #include <common/dirent.h>
 #include <common/string.h>
@@ -8,6 +9,9 @@
 #include <process/ptrace.h>
 #include <process/process.h>
 
+// todo: devfs完善后,删除这个
+extern struct vfs_file_operations_t ps2_keyboard_fops;
+
 // 为filesystem_type_t结构体实例化一个链表头
 static struct vfs_filesystem_type_t vfs_fs = {"filesystem", 0};
 struct vfs_superblock_t *vfs_root_sb = NULL;
@@ -23,6 +27,16 @@ struct vfs_superblock_t *vfs_root_sb = NULL;
 struct vfs_superblock_t *vfs_mount_fs(const char *path, char *name, struct block_device *blk)
 {
     // todo: 选择挂载点
+    // 判断挂载点是否存在
+    struct vfs_dir_entry_t *target_dentry = NULL;
+    // 由于目前还没有rootfs,因此挂载根目录时,不需要path walk
+    if (strcmp(path, "/") != 0)
+    {
+        target_dentry = vfs_path_walk(path, 0);
+        if (target_dentry == NULL)
+            return NULL;
+    }
+
     struct vfs_filesystem_type_t *p = NULL;
     for (p = &vfs_fs; p; p = p->next)
     {
@@ -31,6 +45,17 @@ struct vfs_superblock_t *vfs_mount_fs(const char *path, char *name, struct block
             struct vfs_superblock_t *sb = p->read_superblock(blk);
             if (strcmp(path, "/") == 0) // 如果挂载到的是'/'挂载点,则让其成为最顶层的文件系统
                 vfs_root_sb = sb;
+            else
+            {
+                kdebug("to mount %s", name);
+                // 调用mount机制,挂载文件系统
+                struct vfs_dir_entry_t *new_dentry = sb->root;
+                // 注意,umount的时候需要释放这些内存
+                new_dentry->name = kzalloc(target_dentry->name_length + 1, 0);
+                new_dentry->name_length = target_dentry->name_length;
+
+                do_mount(target_dentry, new_dentry);
+            }
             return sb;
         }
     }
@@ -76,6 +101,31 @@ uint64_t vfs_unregister_filesystem(struct vfs_filesystem_type_t *fs)
     return VFS_E_FS_NOT_EXIST;
 }
 
+/**
+ * @brief 在dentry的sub_dir_list中搜索指定名称的dentry
+ *
+ * @param dentry 目录项结构体dentry
+ * @param name 待搜索的dentry名称
+ * @return struct vfs_dir_entry_t* 目标dentry (无结果则返回NULL)
+ */
+static struct vfs_dir_entry_t *vfs_search_dentry_list(struct vfs_dir_entry_t *dentry, const char *name)
+{
+    if (list_empty(&dentry->subdirs_list))
+        return NULL;
+
+    struct List *ptr = &dentry->subdirs_list;
+    struct vfs_dir_entry_t *d_ptr = NULL;
+    do
+    {
+        ptr = list_next(ptr);
+        d_ptr = container_of(ptr, struct vfs_dir_entry_t, child_node_list);
+        if (strcmp(name, d_ptr->name) == 0)
+            return d_ptr;
+    } while (list_next(ptr) != (&dentry->subdirs_list));
+
+    return NULL;
+}
+
 /**
  * @brief 按照路径查找文件
  *
@@ -94,42 +144,56 @@ struct vfs_dir_entry_t *vfs_path_walk(const char *path, uint64_t flags)
     if ((!*path) || (*path == '\0'))
         return parent;
 
-    struct vfs_dir_entry_t *dentry;
+    struct vfs_dir_entry_t *dentry = NULL;
     // kdebug("path before walk:%s", path);
     while (true)
     {
         // 提取出下一级待搜索的目录名或文件名,并保存在dEntry_name中
-        const char *tmp_path = path;
+        char *tmp_path = path;
         while ((*path && *path != '\0') && (*path != '/'))
             ++path;
         int tmp_path_len = path - tmp_path;
-        dentry = (struct vfs_dir_entry_t *)kmalloc(sizeof(struct vfs_dir_entry_t), 0);
-        memset(dentry, 0, sizeof(struct vfs_dir_entry_t));
-        // 为目录项的名称分配内存
-        dentry->name = (char *)kmalloc(tmp_path_len + 1, 0);
-        // 貌似这里不需要memset,因为空间会被覆盖
-        // memset(dentry->name, 0, tmp_path_len+1);
-
-        memcpy(dentry->name, (void *)tmp_path, tmp_path_len);
-        dentry->name[tmp_path_len] = '\0';
-        // kdebug("tmp_path_len=%d, dentry->name= %s", tmp_path_len, dentry->name);
-        dentry->name_length = tmp_path_len;
+        // 搜索是否有dentry缓存
+        {
+            char bk = *(tmp_path + tmp_path_len);
+            *(tmp_path + tmp_path_len) = '\0';
+            kdebug("to search:%s", tmp_path);
+            dentry = vfs_search_dentry_list(parent, tmp_path);
+            kdebug("search done, dentry=%#018lx", dentry);
+            *(tmp_path + tmp_path_len) = bk;
+        }
 
-        if (parent->dir_inode->inode_ops->lookup(parent->dir_inode, dentry) == NULL)
+        // 如果没有找到dentry缓存,则申请新的dentry
+        if (dentry == NULL)
         {
-            // 搜索失败
-            // kerror("cannot find the file/dir : %s", dentry->name);
-            kfree(dentry->name);
-            kfree(dentry);
-            return 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);
+
+            memcpy(dentry->name, (void *)tmp_path, tmp_path_len);
+            dentry->name[tmp_path_len] = '\0';
+            // kdebug("tmp_path_len=%d, dentry->name= %s", tmp_path_len, dentry->name);
+            dentry->name_length = tmp_path_len;
+
+            if (parent->dir_inode->inode_ops->lookup(parent->dir_inode, dentry) == NULL)
+            {
+                // 搜索失败
+                // kerror("cannot find the file/dir : %s", dentry->name);
+                kfree(dentry->name);
+                kfree(dentry);
+                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);
         }
-        // 找到子目录项
-        // 初始化子目录项的entry
-        list_init(&dentry->child_node_list);
-        list_init(&dentry->subdirs_list);
-        dentry->parent = parent;
 
-        list_add(&parent->subdirs_list, &dentry->child_node_list);
         while (*path == '/')
             ++path;
 
@@ -151,7 +215,7 @@ struct vfs_dir_entry_t *vfs_path_walk(const char *path, uint64_t flags)
  * @brief 填充dentry
  *
  */
-int vfs_fill_dentry(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)
 {
     struct dirent *dent = (struct dirent *)buf;
 
@@ -264,4 +328,216 @@ uint64_t sys_mkdir(struct pt_regs *regs)
     list_add(&parent_dir->subdirs_list, &subdir_dentry->child_node_list);
     // kdebug("retval = %d", retval);
     return 0;
+}
+
+/**
+ * @brief 打开文件
+ * 
+ * @param filename 文件路径 
+ * @param flags 标志位
+ * @return uint64_t 错误码
+ */
+uint64_t do_open(const char *filename, int flags)
+{
+    long path_len = strnlen_user(filename, PAGE_4K_SIZE) + 1;
+
+    if (path_len <= 0) // 地址空间错误
+    {
+        return -EFAULT;
+    }
+    else if (path_len >= PAGE_4K_SIZE) // 名称过长
+    {
+        return -ENAMETOOLONG;
+    }
+
+    // 为待拷贝文件路径字符串分配内存空间
+    char *path = (char *)kmalloc(path_len, 0);
+    if (path == NULL)
+        return -ENOMEM;
+    memset(path, 0, path_len);
+
+    strncpy_from_user(path, filename, path_len);
+    // 去除末尾的 '/'
+    if (path_len >= 2 && path[path_len - 2] == '/')
+    {
+        path[path_len - 2] = '\0';
+        --path_len;
+    }
+
+    // 寻找文件
+    struct vfs_dir_entry_t *dentry = vfs_path_walk(path, 0);
+
+    // if (dentry != NULL)
+    //     printk_color(ORANGE, BLACK, "Found %s\nDIR_FstClus:%#018lx\tDIR_FileSize:%#018lx\n", path, ((struct fat32_inode_info_t *)(dentry->dir_inode->private_inode_info))->first_clus, dentry->dir_inode->file_size);
+    // else
+    //     printk_color(ORANGE, BLACK, "Can`t find file\n");
+    // kdebug("flags=%#018lx", flags);
+    if (dentry == NULL && flags & O_CREAT)
+    {
+        // 先找到倒数第二级目录
+        int tmp_index = -1;
+        for (int i = path_len - 1; i >= 0; --i)
+        {
+            if (path[i] == '/')
+            {
+                tmp_index = i;
+                break;
+            }
+        }
+
+        struct vfs_dir_entry_t *parent_dentry = NULL;
+        // kdebug("tmp_index=%d", tmp_index);
+        if (tmp_index > 0)
+        {
+
+            path[tmp_index] = '\0';
+            dentry = vfs_path_walk(path, 0);
+            if (dentry == NULL)
+            {
+                kfree(path);
+                return -ENOENT;
+            }
+            parent_dentry = dentry;
+        }
+        else
+            parent_dentry = vfs_root_sb->root;
+
+        // 创建新的文件
+        dentry = (struct vfs_dir_entry_t *)kmalloc(sizeof(struct vfs_dir_entry_t), 0);
+        memset(dentry, 0, sizeof(struct vfs_dir_entry_t));
+
+        dentry->name_length = path_len - tmp_index - 1;
+        dentry->name = (char *)kmalloc(dentry->name_length, 0);
+        memset(dentry->name, 0, dentry->name_length);
+        strncpy(dentry->name, path + tmp_index + 1, dentry->name_length);
+        // kdebug("to create new file:%s   namelen=%d", dentry->name, dentry->name_length)
+        dentry->parent = parent_dentry;
+        uint64_t retval = parent_dentry->dir_inode->inode_ops->create(parent_dentry->dir_inode, dentry, 0);
+        if (retval != 0)
+        {
+            kfree(dentry->name);
+            kfree(dentry);
+            kfree(path);
+            return retval;
+        }
+
+        list_init(&dentry->child_node_list);
+        list_init(&dentry->subdirs_list);
+        list_add(&parent_dentry->subdirs_list, &dentry->child_node_list);
+        // kdebug("created.");
+    }
+    kfree(path);
+    if (dentry == NULL)
+        return -ENOENT;
+
+    // 要求打开文件夹而目标不是文件夹
+    if ((flags & O_DIRECTORY) && (dentry->dir_inode->attribute != VFS_ATTR_DIR))
+        return -ENOTDIR;
+
+    // // 要找的目标是文件夹
+    // if ((flags & O_DIRECTORY) && dentry->dir_inode->attribute == VFS_ATTR_DIR)
+    //     return -EISDIR;
+
+    // // todo: 引入devfs后删除这段代码
+    // // 暂时遇到设备文件的话,就将其first clus设置为特定值
+    // if (path_len >= 5 && filename[0] == '/' && filename[1] == 'd' && filename[2] == 'e' && filename[3] == 'v' && filename[4] == '/')
+    // {
+    //     if (dentry->dir_inode->attribute & VFS_ATTR_FILE)
+    //     {
+    //         // 对于fat32文件系统上面的设备文件,设置其起始扇区
+    //         ((struct fat32_inode_info_t *)(dentry->dir_inode->private_inode_info))->first_clus |= 0xf0000000;
+    //         dentry->dir_inode->sb->sb_ops->write_inode(dentry->dir_inode);
+    //         dentry->dir_inode->attribute |= VFS_ATTR_DEVICE;
+    //     }
+    // }
+
+    // 创建文件描述符
+    struct vfs_file_t *file_ptr = (struct vfs_file_t *)kzalloc(sizeof(struct vfs_file_t), 0);
+
+    int errcode = -1;
+
+    file_ptr->dEntry = dentry;
+    file_ptr->mode = flags;
+
+    file_ptr->file_ops = dentry->dir_inode->file_ops;
+
+    // 如果文件系统实现了打开文件的函数
+    if (file_ptr->file_ops && file_ptr->file_ops->open)
+        errcode = file_ptr->file_ops->open(dentry->dir_inode, file_ptr);
+
+    if (errcode != VFS_SUCCESS)
+    {
+        kfree(file_ptr);
+        return -EFAULT;
+    }
+
+    if (file_ptr->mode & O_TRUNC) // 清空文件
+        file_ptr->dEntry->dir_inode->file_size = 0;
+
+    if (file_ptr->mode & O_APPEND)
+        file_ptr->position = file_ptr->dEntry->dir_inode->file_size;
+    else
+        file_ptr->position = 0;
+
+    struct vfs_file_t **f = current_pcb->fds;
+
+    int fd_num = -1;
+
+    // 在指针数组中寻找空位
+    // todo: 当pcb中的指针数组改为动态指针数组之后,需要更改这里(目前还是静态指针数组)
+    for (int i = 0; i < PROC_MAX_FD_NUM; ++i)
+    {
+        if (f[i] == NULL) // 找到指针数组中的空位
+        {
+            fd_num = i;
+            break;
+        }
+    }
+
+    // 指针数组没有空位了
+    if (fd_num == -1)
+    {
+        kfree(file_ptr);
+        return -EMFILE;
+    }
+    // 保存文件描述符
+    f[fd_num] = file_ptr;
+
+    return fd_num;
+}
+
+uint64_t sys_open(struct pt_regs *regs)
+{
+    char *filename = (char *)(regs->r8);
+    int flags = (int)(regs->r9);
+
+    return do_open(filename, flags);
+}
+
+/**
+ * @brief 动态分配dentry以及路径字符串名称
+ *
+ * @param name_size 名称字符串大小(字节)(注意考虑字符串最后需要有一个‘\0’作为结尾)
+ * @return struct vfs_dir_entry_t* 创建好的dentry
+ */
+struct vfs_dir_entry_t *vfs_alloc_dentry(const int name_size)
+{
+    if (unlikely(name_size > VFS_MAX_PATHLEN))
+        return NULL;
+    struct vfs_dir_entry_t *dentry = (struct vfs_dir_entry_t *)kzalloc(sizeof(struct vfs_dir_entry_t), 0);
+    dentry->name = (char *)kzalloc(name_size, 0);
+    list_init(&dentry->child_node_list);
+    list_init(&dentry->subdirs_list);
+    return dentry;
+}
+
+/**
+ * @brief 初始化vfs
+ *
+ * @return int 错误码
+ */
+int vfs_init()
+{
+    mount_init();
+    return 0;
 }

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

@@ -14,6 +14,7 @@
 #include <common/glib.h>
 #include <common/fcntl.h>
 #include <common/blk_types.h>
+#include <mm/slab.h>
 
 extern struct vfs_superblock_t *vfs_root_sb;
 
@@ -24,6 +25,8 @@ extern struct vfs_superblock_t *vfs_root_sb;
 #define VFS_E_FS_EXISTED 1   // 错误:文件系统已存在
 #define VFS_E_FS_NOT_EXIST 2 // 错误:文件系统不存在
 
+#define VFS_MAX_PATHLEN 1024
+
 /**
  * @brief 目录项的属性
  *
@@ -54,6 +57,7 @@ struct vfs_superblock_t
 {
     struct vfs_dir_entry_t *root;
     struct vfs_super_block_operations_t *sb_ops;
+    struct vfs_dir_entry_operations_t *dir_ops; // dentry's operations
     struct block_device *blk_device;
     void *private_sb_info;
 };
@@ -195,4 +199,28 @@ struct vfs_dir_entry_t *vfs_path_walk(const char *path, uint64_t flags);
  * @brief 填充dentry
  *
  */
-int vfs_fill_dentry(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);
+
+/**
+ * @brief 初始化vfs
+ *
+ * @return int 错误码
+ */
+int vfs_init();
+
+/**
+ * @brief 动态分配dentry以及路径字符串名称
+ *
+ * @param name_size 名称字符串大小(字节)(注意考虑字符串最后需要有一个‘\0’作为结尾)
+ * @return struct vfs_dir_entry_t* 创建好的dentry
+ */
+struct vfs_dir_entry_t *vfs_alloc_dentry(const int name_size);
+
+/**
+ * @brief 打开文件
+ * 
+ * @param filename 文件路径 
+ * @param flags 标志位
+ * @return uint64_t 错误码
+ */
+uint64_t do_open(const char *filename, int flags);

+ 47 - 0
kernel/filesystem/VFS/mount.c

@@ -0,0 +1,47 @@
+#include "mount.h"
+#include "VFS.h"
+#include <common/glib.h>
+#include <common/string.h>
+
+static struct List mnt_list_head; // 挂载点链表头
+
+/**
+ * @brief 初始化mount机制
+ *
+ * @return int 错误码
+ */
+int mount_init()
+{
+    list_init(&mnt_list_head);
+    return 0;
+}
+
+/**
+ * @brief 将new_dentry挂载
+ *
+ * @param old_dentry 挂载点的dentry
+ * @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)
+{
+    struct mountpoint *mp = (struct mountpoint *)kzalloc(sizeof(struct mountpoint), 0);
+    list_init(&mp->mnt_list);
+    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);
+    // 拷贝名称
+    strncpy(new_dentry->name, old_dentry->name, old_dentry->name_length);
+
+    list_init(&new_dentry->child_node_list);
+    list_init(&new_dentry->subdirs_list);
+    new_dentry->parent = old_dentry->parent;
+
+
+    // 将新的dentry的list结点替换掉父dentry的列表中的old_dentry的list结点
+    list_replace(&old_dentry->child_node_list, &new_dentry->child_node_list);
+    list_append(&mnt_list_head, &mp->mnt_list);
+
+    return 0;
+}

+ 29 - 0
kernel/filesystem/VFS/mount.h

@@ -0,0 +1,29 @@
+#pragma once
+#include <common/glib.h>
+
+/**
+ * @brief 挂载点结构体(用来表示dentry被挂载其他文件系统之后,原先存在的数据)
+ *
+ */
+struct mountpoint
+{
+    struct List mnt_list;                  // 挂载点串在一起的链表
+    struct vfs_dir_entry_t *dentry;        // 被挂载前,当前目录项的dentry
+    struct vfs_dir_entry_t *parent_dentry; // 被挂载前,父目录项的dentry
+};
+
+/**
+ * @brief 初始化mount机制
+ *
+ * @return int 错误码
+ */
+int mount_init();
+
+/**
+ * @brief 将new_dentry挂载
+ *
+ * @param old_dentry 挂载点的dentry
+ * @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);

+ 6 - 0
kernel/filesystem/devfs/chardev.c

@@ -0,0 +1,6 @@
+#include "chardev.h"
+
+int chardev_register()
+{
+    
+}

+ 4 - 0
kernel/filesystem/devfs/chardev.h

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

+ 34 - 0
kernel/filesystem/devfs/devfs-types.h

@@ -0,0 +1,34 @@
+#pragma once
+#include <filesystem/VFS/VFS.h>
+
+/**
+ * @brief devfs_private_file_info_t的type字段值
+ * 
+ */
+enum
+{
+    DEV_TYPE_UNDEF = 0,
+    DEV_TYPE_CHAR = 1,
+};
+
+/**
+ * @brief 字符设备的sub_type字段值
+ * 
+ */
+enum
+{
+    CHAR_DEV_STYPE_PS2 = 1,
+    CHAR_DEV_STYPE_USB,
+    CHAR_DEV_STYPE_BLUETOOTH,
+};
+
+/**
+ * @brief 设备文件私有信息结构体
+ *
+ */
+struct devfs_private_inode_info_t
+{
+    uint16_t type;     // 设备主类型
+    uint16_t sub_type; // 设备子类型
+    struct vfs_file_operations_t *f_ops;
+};

+ 163 - 2
kernel/filesystem/devfs/devfs.c

@@ -1,10 +1,171 @@
 #include "devfs.h"
+#include <filesystem/VFS/VFS.h>
+#include <common/glib.h>
+#include <common/string.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};
+
+extern struct vfs_file_operations_t ps2_keyboard_fops;
 
+/**
+ * @brief 创建devfs的super block
+ *
+ * @param blk 未使用(devfs为伪文件系统,不需要物理设备)
+ * @return struct vfs_superblock_t*
+ */
+struct vfs_superblock_t *devfs_read_superblock(struct block_device *blk)
+{
+    devfs_sb.blk_device = NULL;
+    devfs_sb.root = devfs_root_dentry;
+    devfs_sb.sb_ops = &devfs_sb_ops;
+    devfs_sb.dir_ops = &devfs_dentry_ops;
+    // todo: 为devfs增加私有信息
+    devfs_sb.private_sb_info = NULL;
+    kdebug("devfs read superblock done");
+    return &devfs_sb;
+}
+
+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 =
+    {
+        .write_superblock = &devfs_write_superblock,
+        .put_superblock = &devfs_put_superblock,
+        .write_inode = &devfs_write_inode,
+};
+
+static long devfs_compare(struct vfs_dir_entry_t *parent_dEntry, char *source_filename, char *dest_filename) {}
+
+static long devfs_hash(struct vfs_dir_entry_t *dEntry, char *filename) {}
+
+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 =
+    {
+        .compare = &devfs_compare,
+        .hash = &devfs_hash,
+        .release = &devfs_release,
+        .iput = &devfs_iput,
+};
+
+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) {}
+static long devfs_lseek(struct vfs_file_t *file_ptr, long offset, long origin) {}
+static long devfs_ioctl(struct vfs_index_node_t *inode, struct vfs_file_t *file_ptr, uint64_t cmd, uint64_t arg) {return 0;}
+static long devfs_readdir(struct vfs_file_t *file_ptr, void *dirent, vfs_filldir_t filler) {return 0;}
+
+static struct vfs_file_operations_t devfs_file_ops =
+    {
+        .open = &devfs_open,
+        .close = &devfs_close,
+        .read = &devfs_read,
+        .write = &devfs_write,
+        .lseek = &devfs_lseek,
+        .ioctl = &devfs_ioctl,
+        .readdir = &devfs_readdir,
+};
+
+/**
+ * @brief 创建新的文件
+ * @param parent_inode 父目录的inode结构体
+ * @param dest_dEntry 新文件的dentry
+ * @param 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)
+{
+    kdebug("devfs_lookup: %s", dest_dEntry->name);
+    return NULL;
+}
+static long devfs_mkdir(struct vfs_index_node_t *inode, struct vfs_dir_entry_t *dEntry, int mode) {}
+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 = {
+    .create = &devfs_create,
+    .lookup = &devfs_lookup,
+    .mkdir = &devfs_mkdir,
+    .rmdir = &devfs_rmdir,
+    .rename = &devfs_rename,
+    .getAttr = &devfs_getAttr,
+    .setAttr = &devfs_setAttr,
+};
+
+static struct vfs_filesystem_type_t devfs_fs_type =
+    {
+        .name = "DEVFS",
+        .fs_flags = 0,
+        .read_superblock = devfs_read_superblock,
+        .next = NULL,
+};
+
+static __always_inline void __devfs_init_root_inode()
+{
+    devfs_root_dentry->dir_inode->file_ops = &devfs_file_ops;
+    devfs_root_dentry->dir_inode->inode_ops = &devfs_inode_ops;
+
+    // todo: 增加private inode info
+    devfs_root_dentry->dir_inode->private_inode_info = NULL;
+    devfs_root_dentry->dir_inode->sb = &devfs_sb;
+}
+/**
+ * @brief 初始化devfs的根dentry
+ */
+static __always_inline void __devfs_init_root_dentry()
+{
+    devfs_root_dentry = (struct vfs_dir_entry_t *)kzalloc(sizeof(struct vfs_dir_entry_t), 0);
+    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()
+{
+    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->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);
+}
 /**
  * @brief 初始化devfs
- * 
+ *
  */
 void devfs_init()
 {
-    
+    __devfs_init_root_dentry();
+    vfs_register_filesystem(&devfs_fs_type);
+    vfs_mount_fs("/dev", "DEVFS", NULL);
+
+    devfs_register_device();
 }

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

@@ -1,5 +1,6 @@
 #pragma once
 
+
 /**
  * @brief 初始化devfs
  * 

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

@@ -343,6 +343,7 @@ struct vfs_superblock_t *fat32_read_superblock(struct block_device *blk)
     struct vfs_superblock_t *sb_ptr = (struct vfs_superblock_t *)kzalloc(sizeof(struct vfs_superblock_t), 0);
     blk->bd_superblock = sb_ptr;
     sb_ptr->sb_ops = &fat32_sb_ops;
+    sb_ptr->dir_ops = &fat32_dEntry_ops;
     sb_ptr->private_sb_info = kzalloc(sizeof(fat32_sb_info_t), 0);
     sb_ptr->blk_device = blk;
 

+ 3 - 0
kernel/process/process.c

@@ -12,6 +12,7 @@
 #include <driver/usb/usb.h>
 #include <exception/gate.h>
 #include <filesystem/fat32/fat32.h>
+#include <filesystem/devfs/devfs.h>
 #include <mm/slab.h>
 #include <common/spinlock.h>
 #include <syscall/syscall.h>
@@ -464,7 +465,9 @@ ul initial_kernel_thread(ul arg)
 {
     // kinfo("initial proc running...\targ:%#018lx", arg);
     ahci_init();
+    vfs_init();
     fat32_init();
+    devfs_init();
     // 使用单独的内核线程来初始化usb驱动程序
     int usb_pid = kernel_thread(usb_init, 0, 0);
 

+ 2 - 181
kernel/syscall/syscall.c

@@ -9,7 +9,6 @@
 #include <common/string.h>
 #include <filesystem/fat32/fat32.h>
 #include <filesystem/VFS/VFS.h>
-#include <driver/keyboard/ps2_keyboard.h>
 #include <process/process.h>
 #include <time/sleep.h>
 
@@ -19,6 +18,7 @@ extern void syscall_int(void);
 
 extern uint64_t sys_clock(struct pt_regs *regs);
 extern uint64_t sys_mstat(struct pt_regs *regs);
+extern uint64_t sys_open(struct pt_regs *regs);
 
 /**
  * @brief 导出系统调用处理函数的符号
@@ -121,186 +121,7 @@ ul sys_put_string(struct pt_regs *regs)
     return 0;
 }
 
-uint64_t sys_open(struct pt_regs *regs)
-{
-    char *filename = (char *)(regs->r8);
-    int flags = (int)(regs->r9);
-    // kdebug("filename=%s", filename);
-
-    long path_len = strnlen_user(filename, PAGE_4K_SIZE) + 1;
-
-    if (path_len <= 0) // 地址空间错误
-    {
-        return -EFAULT;
-    }
-    else if (path_len >= PAGE_4K_SIZE) // 名称过长
-    {
-        return -ENAMETOOLONG;
-    }
-
-    // 为待拷贝文件路径字符串分配内存空间
-    char *path = (char *)kmalloc(path_len, 0);
-    if (path == NULL)
-        return -ENOMEM;
-    memset(path, 0, path_len);
-
-    strncpy_from_user(path, filename, path_len);
-    // 去除末尾的 '/'
-    if (path_len >= 2 && path[path_len - 2] == '/')
-    {
-        path[path_len - 2] = '\0';
-        --path_len;
-    }
-
-    // 寻找文件
-    struct vfs_dir_entry_t *dentry = vfs_path_walk(path, 0);
-
-    // if (dentry != NULL)
-    //     printk_color(ORANGE, BLACK, "Found %s\nDIR_FstClus:%#018lx\tDIR_FileSize:%#018lx\n", path, ((struct fat32_inode_info_t *)(dentry->dir_inode->private_inode_info))->first_clus, dentry->dir_inode->file_size);
-    // else
-    //     printk_color(ORANGE, BLACK, "Can`t find file\n");
-    // kdebug("flags=%#018lx", flags);
-    if (dentry == NULL && flags & O_CREAT)
-    {
-        // 先找到倒数第二级目录
-        int tmp_index = -1;
-        for (int i = path_len - 1; i >= 0; --i)
-        {
-            if (path[i] == '/')
-            {
-                tmp_index = i;
-                break;
-            }
-        }
-
-        struct vfs_dir_entry_t *parent_dentry = NULL;
-        // kdebug("tmp_index=%d", tmp_index);
-        if (tmp_index > 0)
-        {
-
-            path[tmp_index] = '\0';
-            dentry = vfs_path_walk(path, 0);
-            if (dentry == NULL)
-            {
-                kfree(path);
-                return -ENOENT;
-            }
-            parent_dentry = dentry;
-        }
-        else
-            parent_dentry = vfs_root_sb->root;
-
-        // 创建新的文件
-        dentry = (struct vfs_dir_entry_t *)kmalloc(sizeof(struct vfs_dir_entry_t), 0);
-        memset(dentry, 0, sizeof(struct vfs_dir_entry_t));
-
-        dentry->name_length = path_len - tmp_index - 1;
-        dentry->name = (char *)kmalloc(dentry->name_length, 0);
-        memset(dentry->name, 0, dentry->name_length);
-        strncpy(dentry->name, path + tmp_index + 1, dentry->name_length);
-        // kdebug("to create new file:%s   namelen=%d", dentry->name, dentry->name_length)
-        dentry->parent = parent_dentry;
-        uint64_t retval = parent_dentry->dir_inode->inode_ops->create(parent_dentry->dir_inode, dentry, 0);
-        if (retval != 0)
-        {
-            kfree(dentry->name);
-            kfree(dentry);
-            kfree(path);
-            return retval;
-        }
-
-        list_init(&dentry->child_node_list);
-        list_init(&dentry->subdirs_list);
-        list_add(&parent_dentry->subdirs_list, &dentry->child_node_list);
-        // kdebug("created.");
-    }
-    kfree(path);
-    if (dentry == NULL)
-        return -ENOENT;
-
-    // 要求打开文件夹而目标不是文件夹
-    if ((flags & O_DIRECTORY) && (dentry->dir_inode->attribute != VFS_ATTR_DIR))
-        return -ENOTDIR;
-
-    // // 要找的目标是文件夹
-    // if ((flags & O_DIRECTORY) && dentry->dir_inode->attribute == VFS_ATTR_DIR)
-    //     return -EISDIR;
-
-    // todo: 引入devfs后删除这段代码
-    // 暂时遇到设备文件的话,就将其first clus设置为特定值
-    if (path_len >= 5 && filename[0] == '/' && filename[1] == 'd' && filename[2] == 'e' && filename[3] == 'v' && filename[4] == '/')
-    {
-        if (dentry->dir_inode->attribute & VFS_ATTR_FILE)
-        {
-            // 对于fat32文件系统上面的设备文件,设置其起始扇区
-            ((struct fat32_inode_info_t *)(dentry->dir_inode->private_inode_info))->first_clus |= 0xf0000000;
-            dentry->dir_inode->sb->sb_ops->write_inode(dentry->dir_inode);
-            dentry->dir_inode->attribute |= VFS_ATTR_DEVICE;
-        }
-    }
-
-    // 创建文件描述符
-    struct vfs_file_t *file_ptr = (struct vfs_file_t *)kmalloc(sizeof(struct vfs_file_t), 0);
-    memset(file_ptr, 0, sizeof(struct vfs_file_t));
-
-    int errcode = -1;
-
-    file_ptr->dEntry = dentry;
-    file_ptr->mode = flags;
-
-    // todo: 接入devfs
-    // 特判一下是否为键盘文件
-    if (dentry->dir_inode->attribute & VFS_ATTR_DEVICE)
-    {
-        file_ptr->file_ops = &ps2_keyboard_fops; // 如果是设备文件,暂时认为它是键盘文件
-    }
-    else
-        file_ptr->file_ops = dentry->dir_inode->file_ops;
-
-    // 如果文件系统实现了打开文件的函数
-    if (file_ptr->file_ops && file_ptr->file_ops->open)
-        errcode = file_ptr->file_ops->open(dentry->dir_inode, file_ptr);
-
-    if (errcode != VFS_SUCCESS)
-    {
-        kfree(file_ptr);
-        return -EFAULT;
-    }
-
-    if (file_ptr->mode & O_TRUNC) // 清空文件
-        file_ptr->dEntry->dir_inode->file_size = 0;
-
-    if (file_ptr->mode & O_APPEND)
-        file_ptr->position = file_ptr->dEntry->dir_inode->file_size;
-    else
-        file_ptr->position = 0;
 
-    struct vfs_file_t **f = current_pcb->fds;
-
-    int fd_num = -1;
-
-    // 在指针数组中寻找空位
-    // todo: 当pcb中的指针数组改为动态指针数组之后,需要更改这里(目前还是静态指针数组)
-    for (int i = 0; i < PROC_MAX_FD_NUM; ++i)
-    {
-        if (f[i] == NULL) // 找到指针数组中的空位
-        {
-            fd_num = i;
-            break;
-        }
-    }
-
-    // 指针数组没有空位了
-    if (fd_num == -1)
-    {
-        kfree(file_ptr);
-        return -EMFILE;
-    }
-    // 保存文件描述符
-    f[fd_num] = file_ptr;
-
-    return fd_num;
-}
 
 /**
  * @brief 关闭文件系统调用
@@ -624,7 +445,7 @@ uint64_t sys_getdents(struct pt_regs *regs)
 
     uint64_t retval = 0;
     if (filp->file_ops && filp->file_ops->readdir)
-        retval = filp->file_ops->readdir(filp, dirent, &vfs_fill_dentry);
+        retval = filp->file_ops->readdir(filp, dirent, &vfs_fill_dirent);
 
     return retval;
 }