From 0aec6827eeaeae11f349d83449293a7040543328 Mon Sep 17 00:00:00 2001 From: fslongjin Date: Fri, 6 May 2022 00:25:32 +0800 Subject: [PATCH] =?UTF-8?q?:new:=20=E8=BF=90=E8=A1=8C=E6=96=87=E4=BB=B6?= =?UTF-8?q?=E7=B3=BB=E7=BB=9F=E4=B8=AD=E7=9A=84=E4=BA=8C=E8=BF=9B=E5=88=B6?= =?UTF-8?q?=E7=A8=8B=E5=BA=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .vscode/settings.json | 6 +- Makefile | 16 +++++- kernel/Makefile | 9 +-- kernel/mm/mm.c | 2 +- kernel/process/process.c | 98 ++++++++++++++++----------------- kernel/syscall/syscall.c | 11 ++-- kernel/syscall/syscall_num.h | 2 + run.sh | 10 +++- user/Makefile | 33 +++++++++++ user/init.c | 31 +++++++++++ user/init.lds | 50 +++++++++++++++++ user/libs/Makefile | 11 ++++ user/libs/libc/Makefile | 12 ++++ user/libs/libc/errno.h | 101 ++++++++++++++++++++++++++++++++++ user/libs/libc/fcntl.c | 15 +++++ user/libs/libc/fcntl.h | 42 ++++++++++++++ user/libs/libc/stdio.h | 7 +++ user/libs/libc/sys/types.h | 83 ++++++++++++++++++++++++++++ user/libs/libc/unistd.c | 65 ++++++++++++++++++++++ user/libs/libc/unistd.h | 79 ++++++++++++++++++++++++++ user/libs/libsystem/Makefile | 8 +++ user/libs/libsystem/syscall.c | 20 +++++++ user/libs/libsystem/syscall.h | 30 ++++++++++ user/sys_api_lib | Bin 0 -> 13264 bytes 24 files changed, 673 insertions(+), 68 deletions(-) create mode 100644 user/Makefile create mode 100644 user/init.c create mode 100644 user/init.lds create mode 100644 user/libs/Makefile create mode 100644 user/libs/libc/Makefile create mode 100644 user/libs/libc/errno.h create mode 100644 user/libs/libc/fcntl.c create mode 100644 user/libs/libc/fcntl.h create mode 100644 user/libs/libc/stdio.h create mode 100644 user/libs/libc/sys/types.h create mode 100644 user/libs/libc/unistd.c create mode 100644 user/libs/libc/unistd.h create mode 100644 user/libs/libsystem/Makefile create mode 100644 user/libs/libsystem/syscall.c create mode 100644 user/libs/libsystem/syscall.h create mode 100644 user/sys_api_lib diff --git a/.vscode/settings.json b/.vscode/settings.json index cebee843..1d046e64 100644 --- a/.vscode/settings.json +++ b/.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": "" diff --git a/Makefile b/Makefile index 789a951c..c56da388 100644 --- a/Makefile +++ b/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;\ diff --git a/kernel/Makefile b/kernel/Makefile index 90b5cf04..759e2ac1 100644 --- a/kernel/Makefile +++ b/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 diff --git a/kernel/mm/mm.c b/kernel/mm/mm.c index ca8633e7..6a2b5486 100644 --- a/kernel/mm/mm.c +++ b/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) diff --git a/kernel/process/process.c b/kernel/process/process.c index 98765fbc..7cc23bc3 100644 --- a/kernel/process/process.c +++ b/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; + + + 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"); - // 将程序代码拷贝到对应的内存中 - 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!"); 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; diff --git a/kernel/syscall/syscall.c b/kernel/syscall/syscall.c index f6bea54d..6ed953a1 100644 --- a/kernel/syscall/syscall.c +++ b/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}; diff --git a/kernel/syscall/syscall_num.h b/kernel/syscall/syscall_num.h index a8a2eaeb..e892e2c5 100644 --- a/kernel/syscall/syscall_num.h +++ b/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的系统调用 \ No newline at end of file diff --git a/run.sh b/run.sh index 0fc37995..afe14c21 100644 --- a/run.sh +++ b/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 diff --git a/user/Makefile b/user/Makefile new file mode 100644 index 00000000..b36d0601 --- /dev/null +++ b/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) \ No newline at end of file diff --git a/user/init.c b/user/init.c new file mode 100644 index 00000000..3a99b454 --- /dev/null +++ b/user/init.c @@ -0,0 +1,31 @@ +#include +#include +#include + +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) + ; +} \ No newline at end of file diff --git a/user/init.lds b/user/init.lds new file mode 100644 index 00000000..d5888a55 --- /dev/null +++ b/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 = .; + + +} \ No newline at end of file diff --git a/user/libs/Makefile b/user/libs/Makefile new file mode 100644 index 00000000..5bf89bbf --- /dev/null +++ b/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 \ No newline at end of file diff --git a/user/libs/libc/Makefile b/user/libs/libc/Makefile new file mode 100644 index 00000000..82960d60 --- /dev/null +++ b/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 diff --git a/user/libs/libc/errno.h b/user/libs/libc/errno.h new file mode 100644 index 00000000..a1ebef05 --- /dev/null +++ b/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. */ \ No newline at end of file diff --git a/user/libs/libc/fcntl.c b/user/libs/libc/fcntl.c new file mode 100644 index 00000000..1e7630e7 --- /dev/null +++ b/user/libs/libc/fcntl.c @@ -0,0 +1,15 @@ +#include +#include + +/** + * @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); +} \ No newline at end of file diff --git a/user/libs/libc/fcntl.h b/user/libs/libc/fcntl.h new file mode 100644 index 00000000..bb797cac --- /dev/null +++ b/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, ...); \ No newline at end of file diff --git a/user/libs/libc/stdio.h b/user/libs/libc/stdio.h new file mode 100644 index 00000000..c232081b --- /dev/null +++ b/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 diff --git a/user/libs/libc/sys/types.h b/user/libs/libc/sys/types.h new file mode 100644 index 00000000..8ece224d --- /dev/null +++ b/user/libs/libc/sys/types.h @@ -0,0 +1,83 @@ +#pragma once + +#include + +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; \ No newline at end of file diff --git a/user/libs/libc/unistd.c b/user/libs/libc/unistd.c new file mode 100644 index 00000000..f45af458 --- /dev/null +++ b/user/libs/libc/unistd.c @@ -0,0 +1,65 @@ +#include +#include + + +/** + * @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); +} \ No newline at end of file diff --git a/user/libs/libc/unistd.h b/user/libs/libc/unistd.h new file mode 100644 index 00000000..d6102881 --- /dev/null +++ b/user/libs/libc/unistd.h @@ -0,0 +1,79 @@ +#pragma once +#include +#include + +// 字体颜色的宏定义 +#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); + diff --git a/user/libs/libsystem/Makefile b/user/libs/libsystem/Makefile new file mode 100644 index 00000000..f360387d --- /dev/null +++ b/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 diff --git a/user/libs/libsystem/syscall.c b/user/libs/libsystem/syscall.c new file mode 100644 index 00000000..3090ffa1 --- /dev/null +++ b/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; +} diff --git a/user/libs/libsystem/syscall.h b/user/libs/libsystem/syscall.h new file mode 100644 index 00000000..75d65ff5 --- /dev/null +++ b/user/libs/libsystem/syscall.h @@ -0,0 +1,30 @@ +#pragma once + +#include + +// 系统调用号 +#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); \ No newline at end of file diff --git a/user/sys_api_lib b/user/sys_api_lib new file mode 100644 index 0000000000000000000000000000000000000000..2ef8834a221629e51035e5536d75ed1e3127cb28 GIT binary patch literal 13264 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 J(Q57T{{