From d7423f36beab61634afe1f7575af26b6a1aa0dcf Mon Sep 17 00:00:00 2001 From: fslongjin Date: Wed, 7 Sep 2022 00:05:34 +0800 Subject: [PATCH 1/4] =?UTF-8?q?new:=20=E5=9C=A8devfs=E4=B8=AD=E4=BD=BF?= =?UTF-8?q?=E7=94=A8=E9=94=AE=E7=9B=98=E6=96=87=E4=BB=B6=EF=BC=88=E4=BB=8D?= =?UTF-8?q?=E5=AD=98=E5=9C=A8bug=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- kernel/common/glib.h | 20 ++ kernel/common/string.c | 2 +- kernel/common/string.h | 2 +- kernel/filesystem/VFS/VFS.c | 330 +++++++++++++++++++++++--- kernel/filesystem/VFS/VFS.h | 30 ++- kernel/filesystem/VFS/mount.c | 47 ++++ kernel/filesystem/VFS/mount.h | 29 +++ kernel/filesystem/devfs/chardev.c | 6 + kernel/filesystem/devfs/chardev.h | 4 + kernel/filesystem/devfs/devfs-types.h | 34 +++ kernel/filesystem/devfs/devfs.c | 165 ++++++++++++- kernel/filesystem/devfs/devfs.h | 1 + kernel/filesystem/fat32/fat32.c | 1 + kernel/process/process.c | 3 + kernel/syscall/syscall.c | 183 +------------- 15 files changed, 644 insertions(+), 213 deletions(-) create mode 100644 kernel/filesystem/VFS/mount.c create mode 100644 kernel/filesystem/VFS/mount.h create mode 100644 kernel/filesystem/devfs/chardev.c create mode 100644 kernel/filesystem/devfs/chardev.h create mode 100644 kernel/filesystem/devfs/devfs-types.h diff --git a/kernel/common/glib.h b/kernel/common/glib.h index ee814a2a..3cd8cc0f 100644 --- a/kernel/common/glib.h +++ b/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) { /** diff --git a/kernel/common/string.c b/kernel/common/string.c index 15d240f3..bbb59ed7 100644 --- a/kernel/common/string.c +++ b/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" diff --git a/kernel/common/string.h b/kernel/common/string.h index 1f3244bb..0eadc258 100644 --- a/kernel/common/string.h +++ b/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); diff --git a/kernel/filesystem/VFS/VFS.c b/kernel/filesystem/VFS/VFS.c index 27489a90..f3c28d57 100644 --- a/kernel/filesystem/VFS/VFS.c +++ b/kernel/filesystem/VFS/VFS.c @@ -1,4 +1,5 @@ #include "VFS.h" +#include "mount.h" #include #include #include @@ -8,6 +9,9 @@ #include #include +// 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; - - if (parent->dir_inode->inode_ops->lookup(parent->dir_inode, dentry) == NULL) + // 搜索是否有dentry缓存 { - // 搜索失败 - // kerror("cannot find the file/dir : %s", dentry->name); - kfree(dentry->name); - kfree(dentry); - return NULL; + 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; + } + + // 如果没有找到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); + + 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; } \ No newline at end of file diff --git a/kernel/filesystem/VFS/VFS.h b/kernel/filesystem/VFS/VFS.h index 0de27e06..8bb1bbaa 100644 --- a/kernel/filesystem/VFS/VFS.h +++ b/kernel/filesystem/VFS/VFS.h @@ -14,6 +14,7 @@ #include #include #include +#include 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); \ No newline at end of file +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); \ No newline at end of file diff --git a/kernel/filesystem/VFS/mount.c b/kernel/filesystem/VFS/mount.c new file mode 100644 index 00000000..0d55b275 --- /dev/null +++ b/kernel/filesystem/VFS/mount.c @@ -0,0 +1,47 @@ +#include "mount.h" +#include "VFS.h" +#include +#include + +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; +} \ No newline at end of file diff --git a/kernel/filesystem/VFS/mount.h b/kernel/filesystem/VFS/mount.h new file mode 100644 index 00000000..13ec7d55 --- /dev/null +++ b/kernel/filesystem/VFS/mount.h @@ -0,0 +1,29 @@ +#pragma once +#include + +/** + * @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); \ No newline at end of file diff --git a/kernel/filesystem/devfs/chardev.c b/kernel/filesystem/devfs/chardev.c new file mode 100644 index 00000000..a1595630 --- /dev/null +++ b/kernel/filesystem/devfs/chardev.c @@ -0,0 +1,6 @@ +#include "chardev.h" + +int chardev_register() +{ + +} \ No newline at end of file diff --git a/kernel/filesystem/devfs/chardev.h b/kernel/filesystem/devfs/chardev.h new file mode 100644 index 00000000..54dd7d38 --- /dev/null +++ b/kernel/filesystem/devfs/chardev.h @@ -0,0 +1,4 @@ +#pragma once + +#include + diff --git a/kernel/filesystem/devfs/devfs-types.h b/kernel/filesystem/devfs/devfs-types.h new file mode 100644 index 00000000..909adf0e --- /dev/null +++ b/kernel/filesystem/devfs/devfs-types.h @@ -0,0 +1,34 @@ +#pragma once +#include + +/** + * @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; +}; diff --git a/kernel/filesystem/devfs/devfs.c b/kernel/filesystem/devfs/devfs.c index 5a92bb3f..6e8f3f4f 100644 --- a/kernel/filesystem/devfs/devfs.c +++ b/kernel/filesystem/devfs/devfs.c @@ -1,10 +1,171 @@ #include "devfs.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}; + +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(); } \ No newline at end of file diff --git a/kernel/filesystem/devfs/devfs.h b/kernel/filesystem/devfs/devfs.h index ff58063b..0436578a 100644 --- a/kernel/filesystem/devfs/devfs.h +++ b/kernel/filesystem/devfs/devfs.h @@ -1,5 +1,6 @@ #pragma once + /** * @brief 初始化devfs * diff --git a/kernel/filesystem/fat32/fat32.c b/kernel/filesystem/fat32/fat32.c index e26a4917..6b907e64 100644 --- a/kernel/filesystem/fat32/fat32.c +++ b/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; diff --git a/kernel/process/process.c b/kernel/process/process.c index 47e203eb..09ab037f 100644 --- a/kernel/process/process.c +++ b/kernel/process/process.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -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); diff --git a/kernel/syscall/syscall.c b/kernel/syscall/syscall.c index 116e4e50..0098c451 100644 --- a/kernel/syscall/syscall.c +++ b/kernel/syscall/syscall.c @@ -9,7 +9,6 @@ #include #include #include -#include #include #include