From: acevest Date: Tue, 30 Apr 2024 14:44:21 +0000 (+0800) Subject: ... X-Git-Url: http://zhaoyanbai.com/repos/tz-link.htm?a=commitdiff_plain;h=refs%2Fheads%2Fdev%2Ftmp;p=kernel.git ... --- diff --git a/fs/ext2.c b/fs/ext2.c index 36345ce..ffa6e1b 100644 --- a/fs/ext2.c +++ b/fs/ext2.c @@ -17,11 +17,14 @@ superblock_t *ext2_read_super(superblock_t *sb, void *data) { return sb; } fs_type_t ext2_fs_type = { - "ext2", - ext2_read_super, - 0, + .name = "ext2", + .read_super = ext2_read_super, + .next = 0, }; +void ext2_setup() { vfs_register_filesystem(&ext2_fs_type); } + +//-------------------------------------------------------------------------- struct { ext2_sb_t ext2_sb; ext2_gd_t *ext2_gd; @@ -30,9 +33,9 @@ struct { extern void blk_rw(dev_t dev, u64_t offset, u32_t scnt, char *buf); extern void kmem_cache_free(kmem_cache_t *cache, void *addr); -#define BLKRW(blkid, blkcnt, buf) \ - do { \ - blk_rw(system.root_dev, 1ULL * (blkid)*EXT2_BLOCK_SIZE, (blkcnt)*EXT2_BLOCK_SIZE, buf); \ +#define BLKRW(blkid, blkcnt, buf) \ + do { \ + blk_rw(system.root_dev, 1ULL * (blkid) * EXT2_BLOCK_SIZE, (blkcnt) * EXT2_BLOCK_SIZE, buf); \ } while (0) kmem_cache_t *ext2_block_cache; @@ -213,7 +216,9 @@ void ext2_setup_fs() { memset(&ext2_fs, 0, sizeof(ext2_fs)); char *buf = kmalloc(EXT2_BLOCK_SIZE, 0); - if (buf == 0) panic("out of memory"); + if (buf == 0) { + panic("out of memory"); + } BLKRW(1, 1, buf); // now blocksize == 1024, so blkid == 1 diff --git a/fs/fs.c b/fs/fs.c index 0088189..cde27a8 100644 --- a/fs/fs.c +++ b/fs/fs.c @@ -14,13 +14,26 @@ #include #include +// void ramfs_setup(); +// void ext2_setup(); + +// void setup_fs() { +// ramfs_setup(); + +// // ext2_setup(); +// } + +//-------------------------------------------------------------------------- + extern chrdev_t cnsl_chrdev; chrdev_t *chrdev[CHRDEV_SIZE] = {&cnsl_chrdev}; -void ext2_setup_fs(); +// void ext2_setup_fs(); unsigned int ext2_search_inpath(const char *path); -void setup_fs() { ext2_setup_fs(); } +// void setup_fs() { +// ext2_setup_fs(); +// } unsigned int namei(const char *path) { return ext2_search_inpath(path); } diff --git a/fs/open.c b/fs/open.c index 46ff07e..54c57b3 100644 --- a/fs/open.c +++ b/fs/open.c @@ -18,4 +18,40 @@ #include #include -int sysc_open(const char *path, int flags, mode_t mode) { return 0; } +int get_unused_fd() { + int fd; + task_files_t *files = &(current->files); + + for (int i = 0; i < NR_TASK_OPEN_CNT; i++) { + if (files->fds[i] == 0) { + return i; + } + } + + printk("too many open files for %s\n", current->name); + return -EMFILE; +} + +file_t *filp_open(const char *path, int flags, mode_t mode) { + int ret = 0; + + // ret = open_path(path, flags, mode, nd); + + return NULL; +} + +int sysc_open(const char *path, int flags, mode_t mode) { + int fd = 0; + + fd = get_unused_fd(); + + if (fd < 0) { + return fd; + } + + file_t *fp = filp_open(path, flags, mode); + + current->files.fds[fd] = fp; + + return 0; +} diff --git a/fs/path.c b/fs/path.c new file mode 100644 index 0000000..0e02240 --- /dev/null +++ b/fs/path.c @@ -0,0 +1,131 @@ +/* + * ------------------------------------------------------------------------ + * File Name: path.c + * Author: Zhao Yanbai + * 2024-04-20 19:24:42 Saturday CST + * Description: none + * ------------------------------------------------------------------------ + */ + +#include +#include +#include +#include +#include + +bool path_init(const char *path, unsigned int flags, namei_t *ni) { + if (path == NULL) { + return false; + } + + if (*path == '/') { + ni->mnt = current->mnt_root; + ni->dentry = current->dentry_root; + } + + ni->mnt = current->mnt_pwd; + ni->dentry = current->dentry_pwd; + + return true; +} + +void follow_dotdot(namei_t *ni) { + while (1) { + dentry_t *dentry = NULL; + vfsmount_t *parent = NULL; + + // 如果当前目录已经是根目录 + if (ni->dentry == current->dentry_root) { + assert(ni->mnt == current->mnt_root); + // do nothing + return; + } + + // 如果当前目录不是挂载的根目录 + if (ni->dentry != ni->mnt->root) { + dentry = ni->dentry->d_parent; + ni->dentry = dentry; + return; + } + + // 当前目录是挂载的根目录,这就需要找到挂载点的上一层目录 + // 所以先找到挂载点的父挂载点vfsmount + parent = ni->mnt->parent; + + // 如果当前挂载点已经是最开始的挂载点vfsmount了 + if (ni->mnt == parent) { + return; + } + + // 如果当前挂载点有父挂载点 + // 就记录当前挂载点的dentry和它所在的挂载vfsmount + dentry = ni->mnt->mount_point; + ni->dentry = dentry; + ni->mnt = parent; + + // 此时有两种情况 + // 1. dentry 是根目录,就需要继续往上找 + // 2. dentry 不是根目录,也需要再往上找一层dentry + } +} + +int path_walk(const char *path, namei_t *ni) { + if (path == NULL) { + return -EINVAL; + } + + // 先跳过最开始的 '/' + while (*path == '/') { + path++; + } + + // 所有连续'/'之后立即就是'\0' + if (*path == 0) { + return 0; + } + + // 拿到当前目录的 inode + inode_t *inode = ni->dentry->d_inode; + + while (1) { + qstr_t this; + this.name = path; + + do { + path++; + } while (*path && (*path != '/')); + + this.len = path - this.name; + + // 看是不是路径的最后一个文件名 + if (*path == 0) { + // + } + + // 跳过所有连续的 '/' + while (*path == '/') { + path++; + } + + // 看是不是路径其实是以'/'结尾的 + if (*path == 0) { + // + } + + // 开始解析name(到这里这个name后跟着的所有的'/'都已经跳过了) + if (this.name[0] == '.') { + if (this.len == 1) { + // 目录无变化,继续下一轮解析 + continue; + } else if (this.len == 2 && this.name[1] == '.') { + follow_dotdot(ni); + inode = ni->dentry->d_inode; + continue; + } + } + + // + } + + return 0; +} diff --git a/fs/ramfs.c b/fs/ramfs.c new file mode 100644 index 0000000..e1caf28 --- /dev/null +++ b/fs/ramfs.c @@ -0,0 +1,40 @@ +/* + * ------------------------------------------------------------------------ + * File Name: ramfs.c + * Author: Zhao Yanbai + * 2024-04-13 23:43:49 Saturday CST + * Description: none + * ------------------------------------------------------------------------ + */ + +#include "ramfs.h" + +#include "fs.h" +#include "mm.h" +#include "string.h" +#include "system.h" +#include "vfs.h" + +superblock_t *ramfs_read_super(superblock_t *sb, void *data); +fs_type_t ramfs_type = { + .name = "ramfs", + .read_super = ramfs_read_super, + .next = 0, +}; + +typedef struct ramfs_superblock { + // +} ramfs_superblock_t; + +typedef struct ramfs_dentry { + // d + +} ramfs_dentry_t; + +typedef struct ramfs_inode { + // d +} ramfs_inode_t; + +void ramfs_init() { vfs_register_filesystem(&ramfs_type); } + +superblock_t *ramfs_read_super(superblock_t *sb, void *data) { return sb; } diff --git a/fs/ramfs.h b/fs/ramfs.h new file mode 100644 index 0000000..4fd1d9a --- /dev/null +++ b/fs/ramfs.h @@ -0,0 +1,10 @@ +/* + * ------------------------------------------------------------------------ + * File Name: ramfs.h + * Author: Zhao Yanbai + * 2024-04-13 23:43:53 Saturday CST + * Description: none + * ------------------------------------------------------------------------ + */ + +#pragma once diff --git a/fs/vfs.c b/fs/vfs.c index d1ab375..509e9d7 100644 --- a/fs/vfs.c +++ b/fs/vfs.c @@ -8,6 +8,7 @@ */ #include +#include #include // 要访问一个文件就必需先访问一个目录,才能根据文件名从目录中找到该文件的目录项,进而找到其inode @@ -42,3 +43,24 @@ void vfs_register_filesystem(fs_type_t *fs) { add->next = fs; fs->next = 0; } + +fs_type_t *vfs_find_filesystem(const char *name) { + for (fs_type_t *fs = &file_systems; fs != 0; fs = fs->next) { + if (strcmp(fs->name, name) == 0) { + return fs; + } + } + + return NULL; +} + +void ramfs_init(); +void vfs_init() { + ramfs_init(); + fs_type_t *fs = vfs_find_filesystem("ramfs"); + if (NULL == fs) { + panic("no ramfs"); + } + + superblock_t *sb = fs->read_super(NULL, NULL); +} diff --git a/fs/vfs.h b/fs/vfs.h index af9dee5..cfd215e 100644 --- a/fs/vfs.h +++ b/fs/vfs.h @@ -10,6 +10,7 @@ #pragma once #include +#include typedef struct dentry dentry_t; @@ -20,9 +21,11 @@ typedef struct dentry_operations dentry_operations_t; // super block typedef struct superblock { - // + // 该超级起的根目录的 dentry dentry_t *sb_root; + // void *sb_private; + // sb_operations_t *sb_ops; } superblock_t; @@ -47,6 +50,11 @@ typedef struct inode { // 缓存的pages list_head_t i_pages; + + dev_t i_dev; // inode存储在该设备上 + dev_t i_rdev; // inode所代表的设备号 + + loff_t i_size; } inode_t; struct dentry { @@ -67,6 +75,12 @@ struct dentry { // 但多个dentry可以指向同一个inode(不实现) inode_t *d_inode; + // 需要一个标记自己已经成为挂载点的标志? + // uint32_t d_flags; + // 也可以用一个指向vfsmount的指针,非0表示挂载? + // 貌似应该搞个链表,因为一个点可以重复挂N次,N个文件系统 + list_head_t d_vfsmnt; // 所有挂载到这个目录的挂载点 + // dentry_operations_t *d_ops; @@ -75,17 +89,18 @@ struct dentry { }; struct sb_operations { - // + // read_inode }; -struct file_operations { - // open - // close - // read - // write - // lseek - // ioctl -}; +// struct file_operations { +// // open +// // close +// // read +// // write +// // lseek +// // ioctl + +// }; struct inode_operations { // }; @@ -94,18 +109,39 @@ struct dentry_operations { // // hash // compare + // d_release 关闭文件 + // d_delete 删除文件 + // }; // 每当将一个存储设备安装到现有文件系统中的某个节点时,内核就要为之建立一个vfsmount结构 // 这个结构中即包含着该设备的有关信息,也包含了安装点的信息 // 系统中的每个文件系统,包括根设备的根文件系统,都要经过安装 +// +// 在安装文件系统时内核主要做如下的事情 +// 创建一个vfsmount +// 为被安装的设备创建一个superblock,并由该设备对应的文件系统来设置这个superblock +// 为被安装的设备的根目录创建一个dentry +// 为被安装的设备的根目录创建一个inode,由sb->sb_ops->read_inode来实现 +// 将superblock与被安装设备根目录的dentry关联 +// 将vfsmount与被安装设备的根目录dentry关联 typedef struct vfsmount { + dentry_t *mount_point; // 挂载点 dentry + dentry_t *root; // 设备根目录 dentry + superblock_t *sb; // 被安装的设备的superblock + struct vfsmount *parent; + // sb->sb_ops->read_inode得到被安装设备根目录的inode + + list_head_t list; // vfsmount 链表 + + // 先简单实现:不支持一个设备挂载多次,或一个目录被挂载多次 } vfsmount_t; typedef struct fs_type { const char *name; superblock_t *(*read_super)(superblock_t *, void *); struct fs_type *next; + list_head_t sbs; // 同属于这个文件系统的所有超级块链表 } fs_type_t; extern superblock_t *root_sb; diff --git a/include/fs.h b/include/fs.h index 7750690..7a0a9a6 100644 --- a/include/fs.h +++ b/include/fs.h @@ -15,6 +15,7 @@ #include #include +#include /* 分区表开始的位置 */ #define PARTS_POS 0x1BE @@ -32,10 +33,10 @@ #define DEV_MINOR_MASK ((1UL << DEV_MAJOR_BITS) - 1) #define MAKE_DEV(major, minor) ((major) << DEV_MAJOR_BITS | minor) -#define MAKE_DISK_DEV(drv_no, part_no) MAKE_DEV(DEV_MAJOR_DISK, (((drv_no)&0x03) << 8) | (((part_no)&0xFF) << 0)) +#define MAKE_DISK_DEV(drv_no, part_no) MAKE_DEV(DEV_MAJOR_DISK, (((drv_no) & 0x03) << 8) | (((part_no) & 0xFF) << 0)) #define DEV_MAJOR(dev) ((unsigned int)((dev) >> DEV_MAJOR_BITS)) -#define DEV_MINOR(dev) ((unsigned int)((dev)&DEV_MINOR_MASK)) +#define DEV_MINOR(dev) ((unsigned int)((dev) & DEV_MINOR_MASK)) // #define MAX_SUPT_FILE_SIZE (1) #define NR_FILES (1) @@ -53,8 +54,28 @@ enum { CHRDEV_CNSL, CHRDEV_SIZE }; extern chrdev_t *chrdev[]; -typedef struct { -} file_t; +typedef struct file file_t; + +typedef struct file_operations { + int (*open)(inode_t *, file_t *); + ssize_t (*read)(file_t *, char *, size_t, loff_t *); +} file_operations_t; + +struct file { + // 多个打开的文件可能是同一个文件 + dentry_t *f_dentry; + file_operations_t *f_ops; +}; + +typedef struct namei { + vfsmount_t *mnt; + dentry_t *dentry; +} namei_t; + +typedef struct qstr { + const char *name; + unsigned int len; +} qstr_t; #if 0 #define NR_FILES (PAGE_SIZE / sizeof(File)) @@ -107,6 +128,4 @@ static inline pInode find_empty_inode() } #endif -typedef uint32_t dev_t; - #endif //_FS_H diff --git a/include/task.h b/include/task.h index d47538e..1ff15ce 100644 --- a/include/task.h +++ b/include/task.h @@ -22,6 +22,7 @@ #include #include #include +#include // #include enum { @@ -40,6 +41,12 @@ enum { #define TASK_MAGIC 0xAABBCCDD11223344 +#define NR_TASK_OPEN_CNT 32 +typedef struct task_files { + // 暂时先不用bitmap,直接线性搜索 + file_t *fds[NR_TASK_OPEN_CNT]; +} task_files_t; + typedef union task_union { struct { uint32_t esp0; /* kernel stack */ @@ -68,6 +75,14 @@ typedef union task_union { char name[TASK_NAME_SIZE]; + task_files_t files; + + dentry_t *dentry_root; + dentry_t *dentry_pwd; + + vfsmount_t *mnt_root; + vfsmount_t *mnt_pwd; + list_head_t list; // 所有进程串成一个链表 list_head_t pend; // 某些条件串成一个链表 diff --git a/include/types.h b/include/types.h index 04a3aaa..62c2b65 100644 --- a/include/types.h +++ b/include/types.h @@ -50,6 +50,10 @@ typedef long int32_t; typedef unsigned long long uint64_t; typedef long long int64_t; +typedef uint64_t loff_t; + +typedef uint32_t dev_t; + typedef unsigned long pid_t; typedef unsigned long mode_t; diff --git a/kernel/irq.c b/kernel/irq.c index b6f6a5b..30cd001 100644 --- a/kernel/irq.c +++ b/kernel/irq.c @@ -89,6 +89,8 @@ __attribute__((regparm(1))) void irq_handler(pt_regs_t *regs) { assert(irq_disabled()); reenter++; + // TODO 判断打断的是否是内核态代码 + // 屏蔽当前中断 p->chip->disable(irq); diff --git a/kernel/sched.c b/kernel/sched.c index b2af86e..e175399 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -83,6 +83,10 @@ void init_root_task() { wrmsr(MSR_SYSENTER_ESP, root_task.esp0, 0); #endif + for (i = 0; i < NR_TASK_OPEN_CNT; i++) { + root_task.files.fds[i] = NULL; + } + printk("init_root_task tss.esp0 %08x\n", tss.esp0); }