Browse Source

:new: sys_open系统调用

fslongjin 2 years ago
parent
commit
966d67fcde

+ 3 - 1
.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": ""

+ 31 - 0
kernel/common/fcntl.h

@@ -0,0 +1,31 @@
+/**
+ * @file fcntl.h
+ * @author fslongjin ([email protected])
+ * @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

+ 52 - 6
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;
 }

+ 79 - 8
kernel/filesystem/VFS/VFS.c

@@ -1,10 +1,10 @@
 #include "VFS.h"
 #include <common/kprint.h>
+#include <mm/slab.h>
 
 // 为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;
+    }
 }

+ 16 - 2
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);
+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);

+ 1 - 70
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

+ 0 - 9
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文件系统的超级块

+ 6 - 5
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();
 

+ 3 - 2
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

+ 26 - 24
kernel/process/process.c

@@ -7,6 +7,7 @@
 #include "../syscall/syscall_num.h"
 #include <mm/slab.h>
 #include <sched/sched.h>
+#include <filesystem/fat32/fat32.h>
 
 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;

+ 14 - 6
kernel/process/process.h

@@ -16,6 +16,11 @@
 #include "../syscall/syscall.h"
 #include "ptrace.h"
 
+#include <filesystem/VFS/VFS.h>
+
+// 进程最大可拥有的文件描述符数量
+#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");                                                           \

+ 3 - 1
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();
 }
 
 /**

+ 108 - 10
kernel/syscall/syscall.c

@@ -3,6 +3,10 @@
 #include <exception/gate.h>
 #include <exception/irq.h>
 #include <driver/disk/ahci/ahci.h>
+#include <mm/slab.h>
+#include <common/errno.h>
+#include <common/fcntl.h>
+#include <filesystem/fat32/fat32.h>
 
 // 导出系统调用入口函数,定义在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};

+ 1 - 0
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的系统调用