From 966d67fcde4fca2eac1e7f353daa888995137b24 Mon Sep 17 00:00:00 2001 From: fslongjin Date: Wed, 27 Apr 2022 00:39:02 +0800 Subject: [PATCH] =?UTF-8?q?:new:=20sys=5Fopen=E7=B3=BB=E7=BB=9F=E8=B0=83?= =?UTF-8?q?=E7=94=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .vscode/settings.json | 4 +- kernel/common/fcntl.h | 31 +++++++++ kernel/common/glib.h | 58 ++++++++++++++-- kernel/filesystem/VFS/VFS.c | 87 ++++++++++++++++++++--- kernel/filesystem/VFS/VFS.h | 18 ++++- kernel/filesystem/fat32/fat32.c | 71 +------------------ kernel/filesystem/fat32/fat32.h | 9 --- kernel/main.c | 11 +-- kernel/mm/mm.h | 5 +- kernel/process/process.c | 50 +++++++------- kernel/process/process.h | 20 ++++-- kernel/sched/sched.c | 4 +- kernel/syscall/syscall.c | 118 +++++++++++++++++++++++++++++--- kernel/syscall/syscall_num.h | 1 + 14 files changed, 343 insertions(+), 144 deletions(-) create mode 100644 kernel/common/fcntl.h diff --git a/.vscode/settings.json b/.vscode/settings.json index 866adea6..cebee843 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -86,7 +86,9 @@ "cinttypes": "c", "cstdbool": "c", "typeinfo": "c", - "x86_64_ipi.h": "c" + "x86_64_ipi.h": "c", + "unistd.h": "c", + "syscall_num.h": "c" }, "C_Cpp.errorSquiggles": "Enabled", "esbonio.sphinx.confDir": "" diff --git a/kernel/common/fcntl.h b/kernel/common/fcntl.h new file mode 100644 index 00000000..19387931 --- /dev/null +++ b/kernel/common/fcntl.h @@ -0,0 +1,31 @@ +/** + * @file fcntl.h + * @author fslongjin (longjin@RinGoTek.cn) + * @brief + * @version 0.1 + * @date 2022-04-26 + * + * @copyright Copyright (c) 2022 + * + */ +#pragma once + +#define O_RDONLY 00000000 // Open Read-only +#define O_WRONLY 00000001 // Open Write-only +#define O_RDWR 00000002 // Open read/write +#define O_ACCMODE 00000003 // Mask for file access modes + +#define O_CREAT 00000100 // Create file if it does not exist +#define O_EXCL 00000200 // Fail if file already exists +#define O_NOCTTY 00000400 // Do not assign controlling terminal + +#define O_TRUNC 00001000 // 文件存在且是普通文件,并以O_RDWR或O_WRONLY打开,则它会被清空 + +#define O_APPEND 00002000 // 文件指针会被移动到文件末尾 + +#define O_NONBLOCK 00004000 // 非阻塞式IO模式 + +#define O_EXEC 00010000 // 以仅执行的方式打开(非目录文件) +#define O_SEARCH 00020000 // Open the directory for search only +#define O_DIRECTORY 00040000 // 打开的必须是一个目录 +#define O_NOFOLLOW 00100000 // Do not follow symbolic links diff --git a/kernel/common/glib.h b/kernel/common/glib.h index 0ae7c448..fe202c3b 100644 --- a/kernel/common/glib.h +++ b/kernel/common/glib.h @@ -456,11 +456,11 @@ bool verify_area(uint64_t addr_start, uint64_t length) /** * @brief 从用户空间搬运数据到内核空间 - * + * * @param dst 目的地址 * @param src 源地址 * @param size 搬运的大小 - * @return uint64_t + * @return uint64_t */ static inline uint64_t copy_from_user(void *dst, void *src, uint64_t size) { @@ -470,7 +470,7 @@ static inline uint64_t copy_from_user(void *dst, void *src, uint64_t size) /** * @brief 先每次搬运8 bytes,剩余就直接一个个byte搬运 - * + * */ asm volatile("rep \n\t" "movsq \n\t" @@ -484,11 +484,11 @@ static inline uint64_t copy_from_user(void *dst, void *src, uint64_t size) /** * @brief 从内核空间搬运数据到用户空间 - * + * * @param dst 目的地址 * @param src 源地址 * @param size 搬运的大小 - * @return uint64_t + * @return uint64_t */ static inline uint64_t copy_to_user(void *dst, void *src, uint64_t size) { @@ -498,7 +498,7 @@ static inline uint64_t copy_to_user(void *dst, void *src, uint64_t size) /** * @brief 先每次搬运8 bytes,剩余就直接一个个byte搬运 - * + * */ asm volatile("rep \n\t" "movsq \n\t" @@ -508,4 +508,50 @@ static inline uint64_t copy_to_user(void *dst, void *src, uint64_t size) : "=&c"(size), "=&D"(tmp0), "=&S"(tmp1) : "r"(size & 7), "0"(size >> 3), "1"(dst), "2"(src)); return size; +} + +/** + * @brief 测量来自用户空间的字符串的长度,会检验地址空间是否属于用户空间 + * @param src + * @param maxlen + * @return long + */ +long strnlen_user(void *src, unsigned long maxlen) +{ + + unsigned long size = strlen(src); + + // 地址不合法 + if (!verify_area((uint64_t)src, size)) + return 0; + + return size <= maxlen ? size : maxlen; +} + +char *strncpy(char *Dest, char *Src, long Count) +{ + __asm__ __volatile__("cld \n\t" + "1: \n\t" + "decq %2 \n\t" + "js 2f \n\t" + "lodsb \n\t" + "stosb \n\t" + "testb %%al, %%al \n\t" + "jne 1b \n\t" + "rep \n\t" + "stosb \n\t" + "2: \n\t" + : + : "S"(Src), "D"(Dest), "c"(Count) + : "ax", "memory"); + return Dest; +} + +long strncpy_from_user(void *dst, void *src, unsigned long size) +{ + if (!verify_area((uint64_t)src, size)) + return 0; + + strncpy(dst, src, size); + return size; } \ No newline at end of file diff --git a/kernel/filesystem/VFS/VFS.c b/kernel/filesystem/VFS/VFS.c index bea51f74..7c3f3139 100644 --- a/kernel/filesystem/VFS/VFS.c +++ b/kernel/filesystem/VFS/VFS.c @@ -1,10 +1,10 @@ #include "VFS.h" #include +#include // 为filesystem_type_t结构体实例化一个链表头 static struct vfs_filesystem_type_t vfs_fs = {"filesystem", 0}; - /** * @brief 挂载文件系统 * @@ -31,16 +31,16 @@ struct vfs_superblock_t *vfs_mount_fs(char *name, void *DPTE, uint8_t DPT_type, /** * @brief 在VFS中注册文件系统 - * + * * @param fs 文件系统类型结构体 - * @return uint64_t + * @return uint64_t */ uint64_t vfs_register_filesystem(struct vfs_filesystem_type_t *fs) { struct vfs_filesystem_type_t *p = NULL; - for(p = &vfs_fs; p;p = p->next) + for (p = &vfs_fs; p; p = p->next) { - if(!strcmp(p->name,fs->name)) // 已经注册相同名称的文件系统 + if (!strcmp(p->name, fs->name)) // 已经注册相同名称的文件系统 return VFS_E_FS_EXISTED; } @@ -52,15 +52,86 @@ uint64_t vfs_register_filesystem(struct vfs_filesystem_type_t *fs) uint64_t vfs_unregister_filesystem(struct vfs_filesystem_type_t *fs) { struct vfs_filesystem_type_t *p = &vfs_fs; - while(p->next) + while (p->next) { - if(p->next == fs) + if (p->next == fs) { p->next = p->next->next; fs->next = NULL; return VFS_SUCCESS; } - else p = p->next; + else + p = p->next; } return VFS_E_FS_NOT_EXIST; +} + +/** + * @brief 按照路径查找文件 + * + * @param path 路径 + * @param flags 1:返回父目录项, 0:返回结果目录项 + * @return struct vfs_dir_entry_t* 目录项 + */ +struct vfs_dir_entry_t *vfs_path_walk(char *path, uint64_t flags) +{ + + struct vfs_dir_entry_t *parent = vfs_root_sb->root; + // 去除路径前的斜杠 + while (*path == '/') + ++path; + + if ((!*path) || (*path == '\0')) + return parent; + + struct vfs_dir_entry_t *dentry; + + while (true) + { + // 提取出下一级待搜索的目录名或文件名,并保存在dEntry_name中 + 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, tmp_path, tmp_path_len); + dentry->name[tmp_path_len] = '\0'; + 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; + + while (*path == '/') + ++path; + + if ((!*path) || (*path == '\0')) // 已经到达末尾 + { + if (flags & 1) // 返回父目录 + { + return parent; + } + + return dentry; + } + + parent = dentry; + } } \ No newline at end of file diff --git a/kernel/filesystem/VFS/VFS.h b/kernel/filesystem/VFS/VFS.h index 539dfd1b..e7ec1707 100644 --- a/kernel/filesystem/VFS/VFS.h +++ b/kernel/filesystem/VFS/VFS.h @@ -71,13 +71,17 @@ struct vfs_index_node_t void *private_inode_info; }; +/** + * @brief 文件描述符 + * + */ struct vfs_file_t { long position; uint64_t mode; struct vfs_dir_entry_t *dEntry; - struct vfs_file_opeartions_t *file_ops; + struct vfs_file_operations_t *file_ops; void *private_data; }; @@ -147,4 +151,14 @@ uint64_t vfs_unregister_filesystem(struct vfs_filesystem_type_t *fs); * @param buf 文件系统的引导扇区 * @return struct vfs_superblock_t* */ -struct vfs_superblock_t *vfs_mount_fs(char *name, void *DPTE, uint8_t DPT_type, void *buf, int8_t ahci_ctrl_num, int8_t ahci_port_num, int8_t part_num); \ No newline at end of file +struct vfs_superblock_t *vfs_mount_fs(char *name, void *DPTE, uint8_t DPT_type, void *buf, int8_t ahci_ctrl_num, int8_t ahci_port_num, int8_t part_num); + + +/** + * @brief 按照路径查找文件 + * + * @param path 路径 + * @param flags 1:返回父目录项, 0:返回结果目录项 + * @return struct vfs_dir_entry_t* 目录项 + */ +struct vfs_dir_entry_t *vfs_path_walk(char *path, uint64_t flags); \ No newline at end of file diff --git a/kernel/filesystem/fat32/fat32.c b/kernel/filesystem/fat32/fat32.c index 34cae370..10b23442 100644 --- a/kernel/filesystem/fat32/fat32.c +++ b/kernel/filesystem/fat32/fat32.c @@ -344,76 +344,6 @@ find_lookup_success:; // 找到目标dentry return dest_dentry; } -/** - * @brief 按照路径查找文件 - * - * @param part_id fat32分区id - * @param path - * @param flags 1:返回父目录项, 0:返回结果目录项 - * @return struct vfs_dir_entry_t* 目录项 - */ -struct vfs_dir_entry_t *fat32_path_walk(char *path, uint64_t flags) -{ - - struct vfs_dir_entry_t *parent = vfs_root_sb->root; - // 去除路径前的斜杠 - while (*path == '/') - ++path; - - if ((!*path) || (*path == '\0')) - return parent; - - struct vfs_dir_entry_t *dentry; - - while (true) - { - // 提取出下一级待搜索的目录名或文件名,并保存在dEntry_name中 - 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, tmp_path, tmp_path_len); - dentry->name[tmp_path_len] = '\0'; - 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; - - while (*path == '/') - ++path; - - if ((!*path) || (*path == '\0')) // 已经到达末尾 - { - if (flags & 1) // 返回父目录 - { - return parent; - } - - return dentry; - } - - parent = dentry; - } -} /** * @brief 创建fat32文件系统的超级块 @@ -610,6 +540,7 @@ struct vfs_dir_entry_operations_t fat32_dEntry_ops = // todo: open long fat32_open(struct vfs_index_node_t *inode, struct vfs_file_t *file_ptr) { + return VFS_SUCCESS; } // todo: close diff --git a/kernel/filesystem/fat32/fat32.h b/kernel/filesystem/fat32/fat32.h index d8e628e2..c96ffc29 100644 --- a/kernel/filesystem/fat32/fat32.h +++ b/kernel/filesystem/fat32/fat32.h @@ -176,15 +176,6 @@ typedef struct fat32_inode_info_t fat32_inode_info_t; */ struct vfs_superblock_t *fat32_register_partition(uint8_t ahci_ctrl_num, uint8_t ahci_port_num, uint8_t part_num); -/** - * @brief 按照路径查找文件 - * - * @param part_id fat32分区id - * @param path - * @param flags 1:返回父目录项, 0:返回结果目录项 - * @return struct vfs_dir_entry_t* 目录项 - */ -struct vfs_dir_entry_t *fat32_path_walk(char *path, uint64_t flags); /** * @brief 创建fat32文件系统的超级块 diff --git a/kernel/main.c b/kernel/main.c index 44f6956c..b17ace39 100644 --- a/kernel/main.c +++ b/kernel/main.c @@ -156,8 +156,8 @@ void system_initialize() process_init(); HPET_init(); - fat32_init(); - + // fat32_init(); + // 系统初始化到此结束,剩下的初始化功能应当放在初始内核线程中执行 } @@ -185,19 +185,20 @@ void Start_Kernel(void) system_initialize(); + /* // int part_id = fat32_register_partition(0, 0, 0); - struct vfs_dir_entry_t *dentry = fat32_path_walk("a.txt", 0); + struct vfs_dir_entry_t *dentry = vfs_path_walk("a.txt", 0); if (dentry != NULL) printk_color(ORANGE, BLACK, "Found a.txt\nDIR_FstClus:%#018lx\tDIR_FileSize:%#018lx\n", ((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"); - dentry = fat32_path_walk("xx/12.png", 0); + dentry = vfs_path_walk("xx/12.png", 0); if (dentry != NULL) printk_color(ORANGE, BLACK, "Found xx/12.png\nDIR_FstClus:%#018lx\tDIR_FileSize:%#018lx\n", ((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"); - + */ // show_welcome(); // test_mm(); diff --git a/kernel/mm/mm.h b/kernel/mm/mm.h index d2b27e5f..50a9e57c 100644 --- a/kernel/mm/mm.h +++ b/kernel/mm/mm.h @@ -7,8 +7,9 @@ #define PTRS_PER_PGT 512 // 内核层的起始地址 -#define PAGE_OFFSET ((unsigned long)0xffff800000000000) -#define KERNEL_BASE_LINEAR_ADDR ((unsigned long)0xffff800000000000) +#define PAGE_OFFSET (0xffff800000000000UL) +#define KERNEL_BASE_LINEAR_ADDR (0xffff800000000000UL) +#define USER_MAX_LINEAR_ADDR 0x00007fffffffffffUL; #define PAGE_4K_SHIFT 12 #define PAGE_2M_SHIFT 21 diff --git a/kernel/process/process.c b/kernel/process/process.c index 16e05b3e..2482303f 100644 --- a/kernel/process/process.c +++ b/kernel/process/process.c @@ -7,6 +7,7 @@ #include "../syscall/syscall_num.h" #include #include +#include extern void system_call(void); extern void kernel_thread_func(void); @@ -72,16 +73,9 @@ void user_level_function() long ret = 0; // printk_color(RED,BLACK,"user_level_function task is running\n"); - char string[] = "User level process.\n"; /* - __asm__ __volatile__("leaq sysexit_return_address(%%rip), %%rdx \n\t" - "movq %%rsp, %%rcx \n\t" - "sysenter \n\t" - "sysexit_return_address: \n\t" - : "=a"(ret) - : "0"(1), "D"(string) - : "memory"); - */ + // 测试sys put string + char string[] = "User level process.\n"; long err_code = 1; ul addr = (ul)string; __asm__ __volatile__( @@ -90,19 +84,26 @@ void user_level_function() : "=a"(err_code) : "a"(SYS_PUT_STRING), "m"(addr) : "memory", "r8"); - if (err_code == 0) - { - char str[] = "errno is 0\n"; - addr = (ul)str; - __asm__ __volatile__( - "movq %2, %%r8 \n\t" - "int $0x80 \n\t" - : "=a"(err_code) - : "a"(SYS_PUT_STRING), "m"(addr) - : "memory", "r8"); - } - // enter_syscall_int(SYS_PRINTF, (ul) "test_sys_printf\n", 0, 0, 0, 0, 0, 0, 0); - // kinfo("Return from syscall id 15..."); + */ + + // 测试sys_open + char string[] = "/xx/12.png"; + long err_code = 1; + int zero = 0; + uint64_t addr = (ul)string; + __asm__ __volatile__( + "movq %2, %%r8 \n\t" + "movq %3, %%r9 \n\t" + "movq %4, %%r10 \n\t" + "movq %5, %%r11 \n\t" + "movq %6, %%r12 \n\t" + "movq %7, %%r13 \n\t" + "movq %8, %%r14 \n\t" + "movq %9, %%r15 \n\t" + "int $0x80 \n\t" + : "=a"(err_code) + : "a"(SYS_OPEN), "m"(addr), "m"(zero), "m"(zero), "m"(zero), "m"(zero), "m"(zero), "m"(zero), "m"(zero) + : "memory", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "rcx", "rdx"); while (1) pause(); @@ -151,7 +152,7 @@ ul do_execve(struct pt_regs *regs) mm_map_phys_addr_user(addr, alloc_pages(ZONE_NORMAL, 1, PAGE_PGT_MAPPED)->addr_phys, PAGE_2M_SIZE, PAGE_USER_PAGE); if (!(current_pcb->flags & PF_KTHREAD)) - current_pcb->addr_limit = KERNEL_BASE_LINEAR_ADDR; + current_pcb->addr_limit = USER_MAX_LINEAR_ADDR; // 将程序代码拷贝到对应的内存中 memcpy((void *)0x800000, user_level_function, 1024); @@ -168,6 +169,7 @@ ul do_execve(struct pt_regs *regs) ul initial_kernel_thread(ul arg) { // kinfo("initial proc running...\targ:%#018lx", arg); + fat32_init(); struct pt_regs *regs; @@ -377,7 +379,7 @@ unsigned long do_fork(struct pt_regs *regs, unsigned long clone_flags, unsigned // 将寄存器信息存储到进程的内核栈空间的顶部 memcpy((void *)((ul)tsk + STACK_SIZE - sizeof(struct pt_regs)), regs, sizeof(struct pt_regs)); - kdebug("regs.rip = %#018lx", regs->rip); + // kdebug("regs.rip = %#018lx", regs->rip); // 设置进程的内核栈 thd->rbp = (ul)tsk + STACK_SIZE; thd->rip = regs->rip; diff --git a/kernel/process/process.h b/kernel/process/process.h index 4d7ab9e5..c8eb6d5b 100644 --- a/kernel/process/process.h +++ b/kernel/process/process.h @@ -16,6 +16,11 @@ #include "../syscall/syscall.h" #include "ptrace.h" +#include + +// 进程最大可拥有的文件描述符数量 +#define PROC_MAX_FD_NUM 16 + // 进程的内核栈大小 32K #define STACK_SIZE 32768 @@ -116,6 +121,10 @@ struct process_control_block long pid; long priority; // 优先级 long virtual_runtime; // 虚拟运行时间 + + // 进程拥有的文件描述符的指针数组 + // todo: 改用动态指针数组 + struct vfs_file_t *fds[PROC_MAX_FD_NUM]; }; // 将进程的pcb和内核栈融合到一起,8字节对齐 @@ -138,7 +147,8 @@ union proc_union .signal = 0, \ .priority = 2, \ .preempt_count = 0, \ - .cpu_id = 0 \ + .cpu_id = 0, \ + .fds = { 0 } \ } /** @@ -211,19 +221,17 @@ struct process_control_block *get_current_pcb() #define switch_proc(prev, next) \ do \ { \ - __asm__ __volatile__("cli \n\t" \ - "pushq %%rbp \n\t" \ + __asm__ __volatile__("pushq %%rbp \n\t" \ "pushq %%rax \n\t" \ "movq %%rsp, %0 \n\t" \ "movq %2, %%rsp \n\t" \ - "leaq switch_proc_ret_addr(%%rip), %%rax \n\t" \ + "leaq switch_proc_ret_addr(%%rip), %%rax \n\t" \ "movq %%rax, %1 \n\t" \ "pushq %3 \n\t" \ "jmp __switch_to \n\t" \ - "switch_proc_ret_addr: \n\t" \ + "switch_proc_ret_addr: \n\t" \ "popq %%rax \n\t" \ "popq %%rbp \n\t" \ - "sti \n\t" \ : "=m"(prev->thread->rsp), "=m"(prev->thread->rip) \ : "m"(next->thread->rsp), "m"(next->thread->rip), "D"(prev), "S"(next) \ : "memory"); \ diff --git a/kernel/sched/sched.c b/kernel/sched/sched.c index 39cbd055..0e93e583 100644 --- a/kernel/sched/sched.c +++ b/kernel/sched/sched.c @@ -50,7 +50,7 @@ void sched_cfs_enqueue(struct process_control_block *pcb) */ void sched_cfs() { - + cli(); current_pcb->flags &= ~PROC_NEED_SCHED; struct process_control_block *proc = sched_cfs_dequeue(); @@ -100,6 +100,8 @@ void sched_cfs() } } } + + sti(); } /** diff --git a/kernel/syscall/syscall.c b/kernel/syscall/syscall.c index 107a1ff6..26eb9de9 100644 --- a/kernel/syscall/syscall.c +++ b/kernel/syscall/syscall.c @@ -3,6 +3,10 @@ #include #include #include +#include +#include +#include +#include // 导出系统调用入口函数,定义在entry.S中 extern void system_call(void); @@ -10,11 +14,11 @@ extern void syscall_int(void); /** * @brief 导出系统调用处理函数的符号 - * + * */ #define SYSCALL_COMMON(syscall_num, symbol) extern unsigned long symbol(struct pt_regs *regs); -SYSCALL_COMMON(0, system_call_not_exists); // 导出system_call_not_exists函数 -#undef SYSCALL_COMMON // 取消前述宏定义 +SYSCALL_COMMON(0, system_call_not_exists); // 导出system_call_not_exists函数 +#undef SYSCALL_COMMON // 取消前述宏定义 /** * @brief 重新定义为:把系统调用函数加入系统调用表 @@ -23,8 +27,6 @@ SYSCALL_COMMON(0, system_call_not_exists); // 导出system_call_not_exists函 */ #define SYSCALL_COMMON(syscall_num, symbol) [syscall_num] = symbol, - - /** * @brief sysenter的系统调用函数,从entry.S中跳转到这里 * @@ -44,7 +46,7 @@ void syscall_init() { kinfo("Initializing syscall..."); - set_system_trap_gate(0x80, 0, syscall_int); // 系统调用门 + set_system_intr_gate(0x80, 0, syscall_int); // 系统调用门 } /** @@ -92,7 +94,7 @@ long enter_syscall_int(ul syscall_id, ul arg0, ul arg1, ul arg2, ul arg3, ul arg * @param arg2 背景色 * @return ul 返回值 */ -ul sys_printf(struct pt_regs *regs) +ul sys_put_string(struct pt_regs *regs) { if (regs->r9 == 0 && regs->r10 == 0) @@ -104,6 +106,102 @@ ul sys_printf(struct pt_regs *regs) return 0; } +uint64_t sys_open(struct pt_regs *regs) +{ + + char *filename = (char *)(regs->r8); + int flags = (int)(regs->r9); + + long path_len = strnlen_user(filename, PAGE_4K_SIZE); + + 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); + + // 寻找文件 + struct vfs_dir_entry_t *dentry = vfs_path_walk(path, 0); + kfree(path); + + 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"); + + if (dentry == NULL) + return -ENOENT; + + // 暂时认为目标是目录是一种错误 + if (dentry->dir_inode->attribute == VFS_ATTR_DIR) + return -EISDIR; + + // 创建文件描述符 + struct vfs_file_t *file_ptr = (struct vfs_f2ile_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; + 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; +} + ul sys_ahci_end_req(struct pt_regs *regs) { ahci_end_request(); @@ -118,10 +216,10 @@ void do_syscall_int(struct pt_regs *regs, unsigned long error_code) regs->rax = ret; // 返回码 } - system_call_t system_call_table[MAX_SYSTEM_CALL_NUM] = { [0] = system_call_not_exists, - [1] = sys_printf, - [2 ... 254] = system_call_not_exists, + [1] = sys_put_string, + [2] = sys_open, + [3 ... 254] = system_call_not_exists, [255] = sys_ahci_end_req}; diff --git a/kernel/syscall/syscall_num.h b/kernel/syscall/syscall_num.h index 26a636d9..f035e8cf 100644 --- a/kernel/syscall/syscall_num.h +++ b/kernel/syscall/syscall_num.h @@ -11,5 +11,6 @@ #define SYS_NOT_EXISTS 0 #define SYS_PUT_STRING 1 +#define SYS_OPEN 2 #define SYS_AHCI_END_REQ 255 // AHCI DMA请求结束end_request的系统调用 \ No newline at end of file