Browse Source

:new: 运行文件系统中的二进制程序

fslongjin 2 years ago
parent
commit
0aec6827ee

+ 5 - 1
.vscode/settings.json

@@ -88,7 +88,11 @@
         "typeinfo": "c",
         "x86_64_ipi.h": "c",
         "unistd.h": "c",
-        "syscall_num.h": "c"
+        "syscall_num.h": "c",
+        "stdint.h": "c",
+        "syscall.h": "c",
+        "fcntl.h": "c",
+        "types.h": "c"
     },
     "C_Cpp.errorSquiggles": "Enabled",
     "esbonio.sphinx.confDir": ""

+ 15 - 1
Makefile

@@ -1,8 +1,22 @@
-SUBDIRS = kernel
+SUBDIRS = kernel user
+
+
+
+
+export ARCH=x86_64
+export ROOT_PATH=$(shell pwd)
+
+export DEBUG=DEBUG
+export GLOBAL_CFLAGS := -mcmodel=large -fno-builtin -m64  -O0 -fno-stack-protector -D $(ARCH) 
+
+ifeq ($(DEBUG), DEBUG)
+GLOBAL_CFLAGS += -g 
+endif
 
 .PHONY: all
 all:
 	mkdir -p bin/kernel/
+	mkdir -p bin/user/
 	@list='$(SUBDIRS)'; for subdir in $$list; do \
     		echo "make all in $$subdir";\
     		cd $$subdir;\

+ 1 - 8
kernel/Makefile

@@ -7,17 +7,10 @@ DIR_LIB=lib
 lib_patterns := *.a
 LIB_FILES := $(foreach DIR,$(DIR_LIB),$(addprefix $(DIR)/,$(lib_patterns)))
 
-DEBUG=DEBUG
-CFLAGS := -mcmodel=large -fno-builtin -m64  -O0 -I . -fno-stack-protector
 
-ifeq ($(DEBUG), DEBUG)
-CFLAGS += -g
-endif
-
-ARCH=x86_64
 # 控制操作系统使用的中断控制器 _INTR_8259A_ _INTR_APIC_
 PIC := _INTR_APIC_
-CFLAGS += -D $(PIC) -D $(ARCH) 
+CFLAGS = $(GLOBAL_CFLAGS) -D $(PIC) -I .
 
 ASFLAGS := --64
 

+ 1 - 1
kernel/mm/mm.c

@@ -624,7 +624,7 @@ void mm_map_phys_addr_user(ul virt_addr_start, ul phys_addr_start, ul length, ul
  */
 void mm_map_proc_page_table(ul proc_page_table_addr, bool is_phys, ul virt_addr_start, ul phys_addr_start, ul length, ul flags, bool user)
 {
-    // kdebug("proc_page_table_addr=%#018lx",proc_page_table_addr);
+    kdebug("proc_page_table_addr=%#018lx",proc_page_table_addr);
     // 计算线性地址对应的pml4页表项的地址
     ul *tmp;
     if (is_phys)

+ 48 - 50
kernel/process/process.c

@@ -322,6 +322,37 @@ void user_level_function()
     while (1)
         pause();
 }
+
+/**
+ * @brief 打开要执行的程序文件
+ *
+ * @param path
+ * @return struct vfs_file_t*
+ */
+struct vfs_file_t *process_open_exec_file(char *path)
+{
+    struct vfs_dir_entry_t *dentry = NULL;
+    struct vfs_file_t *filp = NULL;
+
+    dentry = vfs_path_walk(path, 0);
+
+    if (dentry == NULL)
+        return (void *)-ENOENT;
+    if (dentry->dir_inode->attribute == VFS_ATTR_DIR)
+        return (void *)-ENOTDIR;
+
+    filp = (struct vfs_file_t *)kmalloc(sizeof(struct vfs_file_t), 0);
+    if (filp == NULL)
+        return (void *)-ENOMEM;
+
+    filp->position = 0;
+    filp->mode = 0;
+    filp->dEntry = dentry;
+    filp->mode = ATTR_READ_ONLY;
+    filp->file_ops = dentry->dir_inode->file_ops;
+
+    return filp;
+}
 /**
  * @brief 使当前进程去执行新的代码
  *
@@ -340,7 +371,7 @@ ul do_execve(struct pt_regs *regs, char *path)
     regs->rflags = 0x200246;
     regs->rax = 1;
     regs->es = 0;
-
+    
     kdebug("do_execve is running...");
 
     // 当前进程正在与父进程共享地址空间,需要创建
@@ -362,7 +393,6 @@ ul do_execve(struct pt_regs *regs, char *path)
         // 拷贝内核空间的页表指针
         memcpy(phys_2_virt(new_mms->pgd) + 256, phys_2_virt(initial_proc[proc_current_cpu_id]) + 256, PAGE_4K_SIZE / 2);
     }
-
     /**
      * @todo: 加载elf文件并映射对应的页
      *
@@ -371,7 +401,6 @@ ul do_execve(struct pt_regs *regs, char *path)
     unsigned long code_start_addr = 0x800000;
     unsigned long stack_start_addr = 0xa00000;
 
-    // mm_map_phys_addr_user(code_start_addr, alloc_pages(ZONE_NORMAL, 1, PAGE_PGT_MAPPED)->addr_phys, PAGE_2M_SIZE, PAGE_USER_PAGE);
     mm_map_proc_page_table((uint64_t)current_pcb->mm->pgd, true, code_start_addr, alloc_pages(ZONE_NORMAL, 1, PAGE_PGT_MAPPED)->addr_phys, PAGE_2M_SIZE, PAGE_USER_PAGE, true);
 
     process_switch_mm(current_pcb);
@@ -394,24 +423,21 @@ ul do_execve(struct pt_regs *regs, char *path)
 
     // 关闭之前的文件描述符
     process_exit_files(current_pcb);
+
     // 清除进程的vfork标志位
     current_pcb->flags &= ~PF_VFORK;
 
-    int fd_num = enter_syscall_int(SYS_OPEN, path, ATTR_READ_ONLY, 0, 0, 0, 0, 0, 0);
-    if (fd_num < 0)
-        return fd_num;
-    memset((void *)code_start_addr, 0, PAGE_2M_SIZE);
 
-    // 将程序代码拷贝到对应的内存中
-    int retval = enter_syscall_int(SYS_READ, fd_num, code_start_addr, PAGE_2M_SIZE, 0, 0, 0, 0, 0);
-    if (retval)
-    {
-        enter_syscall_int(SYS_CLOSE, fd_num, 0, 0, 0, 0, 0, 0, 0);
-        return retval;
-    }
-    retval = enter_syscall_int(SYS_CLOSE, fd_num, 0, 0, 0, 0, 0, 0, 0);
 
-    // kdebug("program copied!");
+    struct vfs_file_t* filp = process_open_exec_file(path);
+    if((unsigned long)filp <= 0 )
+		return (unsigned long)filp;
+    
+    memset((void *)code_start_addr, 0, PAGE_2M_SIZE);
+    uint64_t pos = 0;
+    int retval = filp->file_ops->read(filp, code_start_addr, PAGE_2M_SIZE, &pos);
+    kdebug("execve ok");
+
     return 0;
 }
 
@@ -430,13 +456,12 @@ ul initial_kernel_thread(ul arg)
 
     current_pcb->thread->rip = (ul)ret_from_system_call;
     current_pcb->thread->rsp = (ul)current_pcb + STACK_SIZE - sizeof(struct pt_regs);
-    current_pcb->thread->fs = USER_DS|0x3;
-    current_pcb->thread->gs = USER_DS|0x3;
+    current_pcb->thread->fs = USER_DS | 0x3;
+    current_pcb->thread->gs = USER_DS | 0x3;
 
     // 主动放弃内核线程身份
     current_pcb->flags &= (~PF_KTHREAD);
 
-
     // current_pcb->mm->pgd = kmalloc(PAGE_4K_SIZE, 0);
     // memset((void*)current_pcb->mm->pgd, 0, PAGE_4K_SIZE);
 
@@ -445,11 +470,12 @@ ul initial_kernel_thread(ul arg)
     current_pcb->flags = 0;
     // 将返回用户层的代码压入堆栈,向rdx传入regs的地址,然后jmp到do_execve这个系统调用api的处理函数  这里的设计思路和switch_proc类似
     // 加载用户态程序:init.bin
+    char init_path[] = "/init.bin";
+    uint64_t addr = (uint64_t)&init_path;
     __asm__ __volatile__("movq %1, %%rsp   \n\t"
                          "pushq %2    \n\t"
                          "jmp do_execve  \n\t" ::"D"(current_pcb->thread->rsp),
-                         "S"("/init.bin"),
-                         "m"(current_pcb->thread->rsp), "m"(current_pcb->thread->rip)
+                         "m"(current_pcb->thread->rsp), "m"(current_pcb->thread->rip), "S"("/init.bin")
                          : "memory");
 
     return 1;
@@ -662,35 +688,6 @@ copy_flags_failed:;
     kfree(tsk);
     return retval;
 
-    /*
-    // 将线程结构体放置在pcb的后面
-    struct thread_struct *thd = (struct thread_struct *)(tsk + 1);
-    memset(thd, 0, sizeof(struct thread_struct));
-    tsk->thread = thd;
-    // kdebug("333\tregs.rip = %#018lx", regs->rip);
-    //  将寄存器信息存储到进程的内核栈空间的顶部
-    memcpy((void *)((ul)tsk + STACK_SIZE - sizeof(struct pt_regs)), regs, sizeof(struct pt_regs));
-
-    // kdebug("regs.rip = %#018lx", regs->rip);
-    // 设置进程的内核栈
-    thd->rbp = (ul)tsk + STACK_SIZE;
-    thd->rip = regs->rip;
-    thd->rsp = (ul)tsk + STACK_SIZE - sizeof(struct pt_regs);
-    thd->fs = KERNEL_DS;
-    thd->gs = KERNEL_DS;
-
-    // kdebug("do_fork() thd->rsp=%#018lx", thd->rsp);
-    //  若进程不是内核层的进程,则跳转到ret from system call
-    if (!(tsk->flags & PF_KTHREAD))
-        thd->rip = regs->rip = (ul)ret_from_system_call;
-    else
-        kdebug("is kernel proc.");
-
-    tsk->state = PROC_RUNNING;
-
-    sched_cfs_enqueue(tsk);
-    */
-
     return 0;
 }
 
@@ -953,6 +950,7 @@ uint64_t process_copy_thread(uint64_t clone_flags, struct process_control_block
     struct pt_regs *child_regs = (struct pt_regs *)((uint64_t)pcb + STACK_SIZE - sizeof(struct pt_regs));
     memcpy(child_regs, current_regs, sizeof(struct pt_regs));
 
+    // 设置子进程的返回值为0
     child_regs->rax = 0;
     child_regs->rsp = stack_start;
 

+ 5 - 6
kernel/syscall/syscall.c

@@ -97,10 +97,7 @@ long enter_syscall_int(ul syscall_id, ul arg0, ul arg1, ul arg2, ul arg3, ul arg
 ul sys_put_string(struct pt_regs *regs)
 {
 
-    if (regs->r9 == 0 && regs->r10 == 0)
-        printk((char *)regs->r8);
-    else
-        printk_color(regs->r9, regs->r10, (char *)regs->r8);
+    printk_color(regs->r9, regs->r10, (char *)regs->r8);
     // printk_color(BLACK, WHITE, (char *)regs->r8);
 
     return 0;
@@ -310,7 +307,7 @@ uint64_t sys_write(struct pt_regs *regs)
  * @param fd_num 文件描述符号
  * @param offset 偏移量
  * @param whence 调整模式
- * @return uint64_t
+ * @return uint64_t 调整结束后的文件访问位置
  */
 uint64_t sys_lseek(struct pt_regs *regs)
 {
@@ -370,5 +367,7 @@ system_call_t system_call_table[MAX_SYSTEM_CALL_NUM] =
         [4] = sys_read,
         [5] = sys_write,
         [6] = sys_lseek,
-        [7 ... 254] = system_call_not_exists,
+        [7] = sys_fork,
+        [8] = sys_vfork,
+        [9 ... 254] = system_call_not_exists,
         [255] = sys_ahci_end_req};

+ 2 - 0
kernel/syscall/syscall_num.h

@@ -16,5 +16,7 @@
 #define SYS_READ 4
 #define SYS_WRITE 5
 #define SYS_LSEEK 6
+#define SYS_FORK 7
+#define SYS_VFORK 8
 
 #define SYS_AHCI_END_REQ 255    // AHCI DMA请求结束end_request的系统调用

+ 9 - 1
run.sh

@@ -22,7 +22,7 @@ iso_boot_grub='./iso/boot/grub'
 iso_boot='./iso/boot/'
 iso='./DragonOS.iso'
 iso_folder='./iso/'
-
+root_folder="$(pwd)"
 
 # toolchain
 OS=`uname -s`
@@ -88,6 +88,14 @@ else
   flag_can_run=1
 fi
 
+# 拷贝init文件到硬盘
+cd tools
+bash m*
+sudo cp ${root_folder}/bin/user/init.bin ${root_folder}/bin/disk_mount
+sync
+bash u*
+cd ..
+
 if [ $flag_can_run -eq 1 ]; then
   if [ ${IA32_USE_QEMU} == 0 ]; then
         bochs -q -f ${bochsrc} -rc ./tools/bochsinit

+ 33 - 0
user/Makefile

@@ -0,0 +1,33 @@
+user_sub_dirs = libs
+
+SUBDIR_ROOTS := . 
+DIRS := . $(shell find $(SUBDIR_ROOTS) -type d)
+GARBAGE_PATTERNS := *.o *.s~ *.s *.S~ *.c~ *.h~ kernel 
+GARBAGE := $(foreach DIR,$(DIRS),$(addprefix $(DIR)/,$(GARBAGE_PATTERNS)))
+
+
+objs := 
+CFLAGS := $(GLOBAL_CFLAGS) 
+current_CFLAGS := $(CFLAGS) -I $(shell pwd)/libs
+all: 
+	
+	@list='$(user_sub_dirs)'; for subdir in $$list; do \
+    		echo "make all in $$subdir";\
+    		cd $$subdir;\
+    		 $(MAKE) all CFLAGS="$(CFLAGS)";\
+    		cd ..;\
+	done
+	$(MAKE) init.o
+	$(MAKE) sys_api_lib
+	
+	objcopy -I elf64-x86-64 -S -R ".eh_frame" -R ".comment" -O binary sys_api_lib $(ROOT_PATH)/bin/user/init.bin
+
+sys_api_lib: init.o
+	
+
+	ld -b elf64-x86-64 -z muldefs -o sys_api_lib init.o $(shell find . -name "*.o") -T init.lds
+
+init.o: init.c 
+	gcc $(current_CFLAGS) -c init.c -o init.o
+clean: 
+	rm -rf $(GARBAGE)

+ 31 - 0
user/init.c

@@ -0,0 +1,31 @@
+#include <libc/unistd.h>
+#include <libc/stdio.h>
+#include <libc/fcntl.h>
+
+int main()
+{
+
+    char string[] = "333.txt";
+    uint8_t buf[128] = {0};
+    char tips_str[] = "The first application 'init.bin' started successfully!\n";
+    put_string(tips_str, COLOR_GREEN, COLOR_BLACK);
+    int fd = open(string, 0);
+    read(fd, buf, 128);
+    
+    put_string(buf, COLOR_ORANGE, COLOR_BLACK);
+
+    lseek(fd, 0, SEEK_SET);
+    write(fd, tips_str, sizeof(tips_str)-1);
+    lseek(fd, 0, SEEK_SET);
+    
+    // 由于暂时没有实现用户态的memset,因此先手动清零
+    for(int i=0;i<128;++i)
+        buf[i] = 0;
+    
+    read(fd, buf, 128);
+    put_string(buf, COLOR_YELLOW, COLOR_BLACK);
+    close(fd);
+
+    while (1)
+        ;
+}

+ 50 - 0
user/init.lds

@@ -0,0 +1,50 @@
+
+OUTPUT_FORMAT("elf64-x86-64","elf64-x86-64","elf64-x86-64")
+OUTPUT_ARCH(i386:x86-64)
+ENTRY(main)
+
+SECTIONS
+{
+
+	. = 0x800000;
+	
+	
+	.text :
+	{
+		_text = .;
+		
+		init.o(.text)
+		
+		_etext = .;
+	}
+	. = ALIGN(8);
+	
+	.data :
+	{
+		_data = .;
+		*(.data)
+		
+		_edata = .;
+	}
+
+
+	rodata_start_pa = .;
+	.rodata :
+	{
+		_rodata = .;	
+		*(.rodata)
+		_erodata = .;
+	}
+
+	
+	.bss :
+	{
+		_bss = .;
+		*(.bss)
+		_ebss = .;
+	}
+
+	_end = .;
+
+
+}

+ 11 - 0
user/libs/Makefile

@@ -0,0 +1,11 @@
+
+user_libs_sub_dirs=libc libsystem
+
+
+all:
+	@list='$(user_libs_sub_dirs)'; for subdir in $$list; do \
+    		echo "make all in $$subdir";\
+    		cd $$subdir;\
+    		$(MAKE) all CFLAGS="$(CFLAGS) -I $(shell pwd)";\
+    		cd ..;\
+	done

+ 12 - 0
user/libs/libc/Makefile

@@ -0,0 +1,12 @@
+all: libc
+
+CFLAGS += -I .
+
+
+libc: unistd.o fcntl.o
+
+unistd.o: unistd.c
+	gcc $(CFLAGS) -c unistd.c -o unistd.o
+
+fcntl.o: fcntl.c
+	gcc $(CFLAGS) -c fcntl.c -o fcntl.o

+ 101 - 0
user/libs/libc/errno.h

@@ -0,0 +1,101 @@
+/**
+ * @file errno.h
+ * @author fslongjin (longjin@RinGoTek.cn)
+ * @brief
+ * @version 0.1
+ * @date 2022-04-22
+ *
+ * @copyright Copyright (c) 2022
+ *
+ */
+#pragma once
+
+#define E2BIG 1            /* 参数列表过长,或者在输出buffer中缺少空间 或者参数比系统内建的最大值要大 Argument list too long. */
+#define EACCES 2           /* 访问被拒绝 Permission denied */
+#define EADDRINUSE 3       /* 地址正在被使用 Address in use.*/
+#define EADDRNOTAVAIL 4    /* 地址不可用 Address  not available.*/
+#define EAFNOSUPPORT 5     /* 地址family不支持 Address family not supported. */
+#define EAGAIN 6           /* 资源不可用,请重试。 Resource unavailable, try again (may be the same value as [EWOULDBLOCK]).*/
+#define EALREADY 7         /* 连接已经在处理 Connection already in progress. */
+#define EBADF 8            /* 错误的文件描述符 Bad file descriptor. */
+#define EBADMSG 9          /* 错误的消息 Bad message. */
+
+#define EBUSY 10           /* 设备或资源忙 Device or resource busy. */
+#define ECANCELED 11       /* 操作被取消 Operation canceled. */
+#define ECHILD 12          /* 没有子进程 No child processes. */
+#define ECONNABORTED 13    /* 连接已断开 Connection aborted. */
+#define ECONNREFUSED 14    /* 连接被拒绝 Connection refused. */
+#define ECONNRESET 15      /* 连接被重置 Connection reset. */
+#define EDEADLK 16         /* 资源死锁将要发生 Resource deadlock would occur. */
+#define EDESTADDRREQ 17    /* 需要目标地址 Destination address required.*/
+#define EDOM 18            /* 数学参数超出作用域 Mathematics argument out of domain of function. */
+#define EDQUOT 19          /* 保留使用 Reserved */
+
+#define EEXIST 20          /* 文件已存在 File exists. */
+#define EFAULT 21          /* 错误的地址 Bad address */
+#define EFBIG 22           /* 文件太大 File too large. */
+#define EHOSTUNREACH 23    /* 主机不可达 Host is unreachable.*/
+#define EIDRM 24           /* 标志符被移除 Identifier removed. */
+#define EILSEQ 25          /* 不合法的字符序列 Illegal byte sequence. */
+#define EINPROGRESS 26     /* 操作正在处理 Operation in progress. */
+#define EINTR 27           /* 被中断的函数 Interrupted function. */
+#define EINVAL 28          /* 不可用的参数 Invalid argument. */
+#define EIO 29             /* I/O错误 I/O error. */
+
+#define EISCONN 30         /* 套接字已连接 Socket is connected. */
+#define EISDIR 31          /* 是一个目录 Is a directory */
+#define ELOOP 32           /* 符号链接级别过多 Too many levels of symbolic links. */
+#define EMFILE 33          /* 文件描述符的值过大 File descriptor value too large. */
+#define EMLINK 34          /* 链接数过多 Too many links. */
+#define EMSGSIZE 35        /* 消息过大 Message too large. */
+#define EMULTIHOP 36       /* 保留使用 Reserved. */
+#define ENAMETOOLONG 37    /* 文件名过长 Filename too long. */
+#define ENETDOWN 38        /* 网络已关闭 Network is down. */
+#define ENETRESET 39       /* 网络连接已断开 Connection aborted by network. */
+
+#define ENETUNREACH 40     /* 网络不可达 Network unreachable. */
+#define ENFILE 41          /* 系统中打开的文件过多 Too many files open in system.*/
+#define ENOBUFS 42         /* 缓冲区空间不足 No buffer space available. */
+#define ENODATA 43         /* 队列头没有可读取的消息 No message is available on the STREAM head read queue. */
+#define ENODEV 44          /* 没有指定的设备 No such device. */
+#define ENOENT 45          /* 没有指定的文件或目录 No such file or directory. */
+#define ENOEXEC 46         /* 可执行文件格式错误 Executable file format error. */
+#define ENOLCK 47          /* 没有可用的锁 No locks available. */
+#define ENOLINK 48         /* 保留 Reserved. */
+#define ENOMEM 49          /* 没有足够的空间 Not enough space. */
+
+#define ENOMSG 50          /* 没有期待类型的消息 No message of the desired type. */
+#define ENOPROTOOPT 51     /* 协议不可用 Protocol not available. */
+#define ENOSPC 52          /* 设备上没有空间 No space left on device. */
+#define ENOSR 53           /* 没有STREAM资源  No STREAM resources.*/
+#define ENOSTR 54          /* 不是STREAM Not a STREAM */
+#define ENOSYS 55          /* 功能不支持 Function not supported. */
+#define ENOTCONN 56        /* 套接字未连接 The socket is not connected. */
+#define ENOTDIR 57         /* 不是目录 Not a directory. */
+#define ENOTEMPTY 58       /* 目录非空 Directory not empty. */
+#define ENOTRECOVERABLE 59 /* 状态不可覆盖 State not recoverable. */
+
+#define ENOTSOCK 60        /* 不是一个套接字 Not a socket.*/
+#define ENOTSUP 61         /* 不被支持 Not supported (may be the same value as [EOPNOTSUPP]). */
+#define ENOTTY 62          /* 不正确的I/O控制操作 Inappropriate I/O control operation. */
+#define ENXIO 63           /* 没有这样的设备或地址 No such device or address. */
+#define EOPNOTSUPP 64      /* 套接字不支持该操作 Operation not supported on socket (may be the same value as [ENOTSUP]). */
+#define EOVERFLOW 65       /* 数值过大,产生溢出 Value too large to be stored in data type. */
+#define EOWNERDEAD 66      /* 之前的拥有者挂了 Previous owner died. */
+#define EPERM 67           /* 操作不被允许 Operation not permitted. */
+#define EPIPE 68           /* 断开的管道 Broken pipe. */
+#define EPROTO 69          /* 协议错误 Protocol error. */
+
+#define EPROTONOSUPPORT 70 /* 协议不被支持 Protocol not supported. */
+#define EPROTOTYPE 71      /* 对于套接字而言,错误的协议 Protocol wrong type for socket. */
+#define ERANGE 72          /* 结果过大 Result too large. */
+#define EROFS 73           /* 只读的文件系统 Read-only file system. */
+#define ESPIPE 74          /* 错误的寻道 Invalid seek. */
+#define ESRCH 75           /* 没有这样的进程 No such process. */
+#define ESTALE 76          /* 保留 Reserved. */
+#define ETIME 77           /* 流式ioctl()超时 Stream ioctl() timeout */
+#define ETIMEDOUT 78       /* 连接超时 Connection timed out.*/
+#define ETXTBSY 79         /* 文本文件忙 Text file busy. */
+
+#define EWOULDBLOCK 80     /* 操作将被禁止 Operation would block (may be the same value as [EAGAIN]). */
+#define EXDEV 81           /* 跨设备连接 Cross-device link. */

+ 15 - 0
user/libs/libc/fcntl.c

@@ -0,0 +1,15 @@
+#include <libc/fcntl.h>
+#include <libsystem/syscall.h>
+
+/**
+ * @brief 打开文件的接口
+ *
+ * @param path 文件路径
+ * @param options 打开选项
+ * @param ...
+ * @return int 文件描述符
+ */
+int open(const char *path, int options, ...)
+{
+    return syscall_invoke(SYS_OPEN, (uint64_t)path, 0, 0, 0, 0, 0, 0, 0);
+}

+ 42 - 0
user/libs/libc/fcntl.h

@@ -0,0 +1,42 @@
+/**
+ * @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
+
+
+/**
+ * @brief 打开文件的接口
+ * 
+ * @param path 文件路径
+ * @param options 打开选项
+ * @param ... 
+ * @return int 文件描述符
+ */
+int open(const char * path, int options, ...);

+ 7 - 0
user/libs/libc/stdio.h

@@ -0,0 +1,7 @@
+#pragma once
+
+#define	SEEK_SET	0	/* Seek relative to start-of-file */
+#define	SEEK_CUR	1	/* Seek relative to current position */
+#define	SEEK_END	2	/* Seek relative to end-of-file */
+
+#define SEEK_MAX	3

+ 83 - 0
user/libs/libc/sys/types.h

@@ -0,0 +1,83 @@
+#pragma once
+
+#include <stdint.h>
+
+typedef unsigned char u_char;
+typedef unsigned short u_short;
+typedef unsigned int u_int;
+typedef unsigned long u_long;
+
+typedef uint32_t uid_t;
+typedef uint32_t gid_t;
+typedef long long ssize_t;
+
+typedef int __pid_t;
+#define pid_t __pid_t
+typedef __SIZE_TYPE__ size_t;
+
+typedef char *caddr_t;
+
+typedef int id_t;
+
+typedef uint64_t ino_t;
+typedef int64_t off_t;
+
+typedef uint32_t blkcnt_t;
+typedef uint32_t blksize_t;
+typedef uint32_t dev_t;
+typedef uint16_t mode_t;
+typedef uint32_t nlink_t;
+
+typedef int64_t time_t;
+typedef uint32_t useconds_t;
+typedef int32_t suseconds_t;
+typedef uint32_t clock_t;
+
+typedef uint64_t fsblkcnt_t;
+typedef uint64_t fsfilcnt_t;
+
+#define __socklen_t_defined
+#define __socklen_t uint32_t
+typedef __socklen_t socklen_t;
+
+struct utimbuf
+{
+    time_t actime;
+    time_t modtime;
+};
+
+typedef int pthread_t;
+typedef int pthread_key_t;
+typedef uint32_t pthread_once_t;
+
+typedef struct __pthread_mutex_t
+{
+    uint32_t lock;
+    pthread_t owner;
+    int level;
+    int type;
+} pthread_mutex_t;
+
+typedef void *pthread_attr_t;
+typedef struct __pthread_mutexattr_t
+{
+    int type;
+} pthread_mutexattr_t;
+
+typedef struct __pthread_cond_t
+{
+    pthread_mutex_t *mutex;
+    uint32_t value;
+    int clockid; // clockid_t
+} pthread_cond_t;
+
+typedef uint64_t pthread_rwlock_t;
+typedef void *pthread_rwlockattr_t;
+typedef struct __pthread_spinlock_t
+{
+    int m_lock;
+} pthread_spinlock_t;
+typedef struct __pthread_condattr_t
+{
+    int clockid; // clockid_t
+} pthread_condattr_t;

+ 65 - 0
user/libs/libc/unistd.c

@@ -0,0 +1,65 @@
+#include <libc/unistd.h>
+#include <libsystem/syscall.h>
+
+
+/**
+ * @brief 往屏幕上输出字符串
+ * 
+ * @param str 字符串指针
+ * @param front_color 前景色
+ * @param bg_color 背景色
+ * @return int64_t 
+ */
+int64_t put_string(char* str, uint64_t front_color, uint64_t bg_color)
+{
+    return syscall_invoke(SYS_PUT_STRING, str, front_color, bg_color,0,0,0,0,0);
+}
+/**
+ * @brief 关闭文件接口
+ *
+ * @param fd 文件描述符
+ * @return int
+ */
+int close(int fd)
+{
+    return syscall_invoke(SYS_CLOSE, fd, 0, 0, 0, 0, 0, 0, 0);
+}
+
+/**
+ * @brief 从文件读取数据的接口
+ *
+ * @param fd 文件描述符
+ * @param buf 缓冲区
+ * @param count 待读取数据的字节数
+ * @return ssize_t 成功读取的字节数
+ */
+ssize_t read(int fd, void *buf, size_t count)
+{
+    return (ssize_t)syscall_invoke(SYS_READ, fd, buf, count,0,0,0,0,0);
+}
+
+/**
+ * @brief 向文件写入数据的接口
+ *
+ * @param fd 文件描述符
+ * @param buf 缓冲区
+ * @param count 待写入数据的字节数
+ * @return ssize_t 成功写入的字节数
+ */
+ssize_t write(int fd, void const *buf, size_t count)
+{
+    return (ssize_t)syscall_invoke(SYS_WRITE, fd, buf, count,0,0,0,0,0);
+}
+
+/**
+ * @brief 调整文件的访问位置
+ *
+ * @param fd 文件描述符号
+ * @param offset 偏移量
+ * @param whence 调整模式
+ * @return uint64_t 调整结束后的文件访问位置
+ */
+off_t lseek(int fd, off_t offset, int whence)
+{
+    return (off_t)syscall_invoke(SYS_LSEEK, fd, offset, whence, 0,0,0,0,0);
+}

+ 79 - 0
user/libs/libc/unistd.h

@@ -0,0 +1,79 @@
+#pragma once
+#include <stdint.h>
+#include <libc/sys/types.h>
+
+// 字体颜色的宏定义
+#define COLOR_WHITE 0x00ffffff  //白
+#define COLOR_BLACK 0x00000000  //黑
+#define COLOR_RED 0x00ff0000    //红
+#define COLOR_ORANGE 0x00ff8000 //橙
+#define COLOR_YELLOW 0x00ffff00 //黄
+#define COLOR_GREEN 0x0000ff00  //绿
+#define COLOR_BLUE 0x000000ff   //蓝
+#define COLOR_INDIGO 0x0000ffff //靛
+#define COLOR_PURPLE 0x008000ff //紫
+
+
+/**
+ * @brief 往屏幕上输出字符串
+ * 
+ * @param str 字符串指针
+ * @param front_color 前景色
+ * @param bg_color 背景色
+ * @return int64_t 
+ */
+int64_t put_string(char* str, uint64_t front_color, uint64_t bg_color);
+
+
+/**
+ * @brief 关闭文件接口
+ *
+ * @param fd 文件描述符
+ * @return int
+ */
+int close(int fd);
+
+/**
+ * @brief 从文件读取数据的接口
+ *
+ * @param fd 文件描述符
+ * @param buf 缓冲区
+ * @param count 待读取数据的字节数
+ * @return ssize_t 成功读取的字节数
+ */
+ssize_t read(int fd, void *buf, size_t count);
+
+/**
+ * @brief 向文件写入数据的接口
+ *
+ * @param fd 文件描述符
+ * @param buf 缓冲区
+ * @param count 待写入数据的字节数
+ * @return ssize_t 成功写入的字节数
+ */
+ssize_t write(int fd, void const *buf, size_t count);
+
+/**
+ * @brief 调整文件的访问位置
+ *
+ * @param fd 文件描述符号
+ * @param offset 偏移量
+ * @param whence 调整模式
+ * @return uint64_t 调整结束后的文件访问位置
+ */
+off_t lseek(int fd, off_t offset, int whence);
+
+/**
+ * @brief fork当前进程
+ * 
+ * @return pid_t 
+ */
+pid_t fork(void);
+
+/**
+ * @brief fork当前进程,但是与父进程共享VM、flags、fd
+ * 
+ * @return pid_t 
+ */
+pid_t vfork(void);
+

+ 8 - 0
user/libs/libsystem/Makefile

@@ -0,0 +1,8 @@
+all: libsystem
+# echo $(shell pwd)
+
+
+libsystem: syscall.o
+
+syscall.o: syscall.c
+	gcc $(CFLAGS) -c syscall.c  -o syscall.o

+ 20 - 0
user/libs/libsystem/syscall.c

@@ -0,0 +1,20 @@
+#include "syscall.h"
+
+long syscall_invoke(uint64_t syscall_id, uint64_t arg0, uint64_t arg1, uint64_t arg2, uint64_t arg3, uint64_t arg4, uint64_t arg5, uint64_t arg6, uint64_t arg7)
+{
+    long err_code;
+    __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"(syscall_id), "m"(arg0), "m"(arg1), "m"(arg2), "m"(arg3), "m"(arg4), "m"(arg5), "m"(arg6), "m"(arg7)
+        : "memory", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "rcx", "rdx");
+    return err_code;
+}

+ 30 - 0
user/libs/libsystem/syscall.h

@@ -0,0 +1,30 @@
+#pragma once
+
+#include <stdint.h>
+
+// 系统调用号
+#define SYS_NOT_EXISTS 0
+#define SYS_PUT_STRING 1
+#define SYS_OPEN 2
+#define SYS_CLOSE 3
+#define SYS_READ 4
+#define SYS_WRITE 5
+#define SYS_LSEEK 6
+#define SYS_FORK 7
+#define SYS_VFORK 8
+
+/**
+ * @brief 用户态系统调用函数
+ *
+ * @param syscall_id
+ * @param arg0
+ * @param arg1
+ * @param arg2
+ * @param arg3
+ * @param arg4
+ * @param arg5
+ * @param arg6
+ * @param arg7
+ * @return long
+ */
+long syscall_invoke(uint64_t syscall_id, uint64_t arg0, uint64_t arg1, uint64_t arg2, uint64_t arg3, uint64_t arg4, uint64_t arg5, uint64_t arg6, uint64_t arg7);

BIN
user/sys_api_lib