Sfoglia il codice sorgente

fixme: 用户进程完善

simon 9 mesi fa
parent
commit
d807627ca3
16 ha cambiato i file con 196 aggiunte e 42 eliminazioni
  1. 5 0
      bochsrc
  2. 0 2
      kernel/.gitignore
  3. 11 11
      kernel/global.h
  4. 2 0
      kernel/init.c
  5. 6 2
      kernel/interrupt.c
  6. 28 1
      kernel/kernel.S
  7. 29 20
      kernel/main.c
  8. 0 0
      lib/user/.keep
  9. 41 0
      lib/user/syscall.c
  10. 10 0
      lib/user/syscall.h
  11. 15 4
      makefile
  12. 16 2
      thread/thread.c
  13. 2 0
      thread/thread.h
  14. 2 0
      userprog/process.c
  15. 20 0
      userprog/syscall-init.c
  16. 9 0
      userprog/syscall-init.h

+ 5 - 0
bochsrc

@@ -18,4 +18,9 @@ log: bochs_log.txt
 
 # logprefix: %t%e%d
 
+debug_symbols: file="build/bin/kernel.sym"
+
+print_timestamps: enabled=0
+
+
 memory: guest=32, host=32, block_size=512

+ 0 - 2
kernel/.gitignore

@@ -1,2 +0,0 @@
-*.o
-*.bin

+ 11 - 11
kernel/global.h

@@ -80,16 +80,16 @@
 #define EFLAGES_VIF (1 << 19) // 中断标志位
 
 /*---------------------- 定义 GDT 中描述符的结构 -----------------------------------------*/
-// ! 段描述符格式
-// !  31~24  23  22  21  20  19~16   15  14~13 12  11~8   7~0
-// !  ----------------------------------------------------------
-// ! |Base | G | D | L |AVL| Limit | P | DPL | S | TYPE | Base |
-// !  ----------------------------------------------------------
-
-// !        31~16                           15~0
-// !  ----------------------------------------------------------
-// ! |         Base                |        Limit              |
-// !  ----------------------------------------------------------
+//   段描述符格式
+//   31~24  23  22  21  20  19~16   15  14~13 12  11~8   7~0
+//   ----------------------------------------------------------
+//  |Base | G | D | L |AVL| Limit | P | DPL | S | TYPE | Base |
+//   ----------------------------------------------------------
+
+//         31~16                           15~0
+//   ----------------------------------------------------------
+//  |         Base                |        Limit              |
+//   ----------------------------------------------------------
 typedef struct gdt_desc
 {
     uint16_t limit_low_word; // 低 16 位
@@ -98,6 +98,6 @@ typedef struct gdt_desc
     uint8_t attr_low_byte;
     uint8_t limit_high_attr_high;
     uint8_t base_high_byte;
-} GdtDesc;
+} __attribute__((packed)) GdtDesc;
 
 #endif // __KERNEL_GLOBAL_H

+ 2 - 0
kernel/init.c

@@ -7,6 +7,7 @@
 #include "memory.h"
 #include "../thread/thread.h"
 #include "../userprog/tss.h"
+#include "../userprog/syscall-init.h"
 
 void init_all(void)
 {
@@ -18,4 +19,5 @@ void init_all(void)
     console_init();  // 初始化 console
     keyboard_init(); // 键盘初始化
     tss_init();      // tss_init
+    syscall_init();  // syscall_init
 }

+ 6 - 2
kernel/interrupt.c

@@ -4,7 +4,7 @@
 #include "../lib/kernel/print.h"
 #include "../lib/kernel/io.h"
 
-#define IDT_DESC_CNT 0x30 // 目前支持的中断数
+#define IDT_DESC_CNT 0x81 // 目前支持的中断数
 #define PIC_M_CTRL 0x20   // 主片的控制端口是 0x20
 #define PIC_M_DATA 0x21   // 主片的数据端口是 0x21
 #define PIC_S_CTRL 0xA0   // 从片的控制端口是 0xA0
@@ -13,6 +13,8 @@
 #define EFLAGS_IF 0x200 // eflags寄存器中的if位为1
 #define GET_EFLAGS(EFLAG_VAR) asm volatile("pushfl; popl %0" : "=g"(EFLAG_VAR))
 
+extern uint32_t syscall_handle(void);
+
 /* 中断门描述符结构体 */
 // Example type_attributes values that people are likely to use (assuming DPL is 0):
 // 32-bit Interrupt Gate: 0x8E (p=1, dpl=0b00, type=0b1110 => type_attributes=0b1000_1110=0x8E)
@@ -49,11 +51,13 @@ static void make_idt_desc(gate_desc *p_gdesc, uint8_t attr, intr_handler functio
 /* 初始化中断描述符表*/
 static void itd_desc_init(void)
 {
-    int i;
+    int i, last_index = IDT_DESC_CNT - 1;
     for (i = 0; i < IDT_DESC_CNT; i++)
     {
         make_idt_desc(&idt[i], IDT_DESC_ATTR_DPL0, intr_entry_table[i]);
     }
+    // syscall_handle int 0x80  -> dpl 为 3
+    make_idt_desc(&idt[last_index], IDT_DESC_ATTR_DPL3, syscall_handle);
     put_str("   idt_desc_init done\n");
 }
 

+ 28 - 1
kernel/kernel.S

@@ -98,4 +98,31 @@ VECTOR 0x2b, ZERO ; 保留
 VECTOR 0x2c, ZERO ; ps/2 鼠标
 VECTOR 0x2d, ZERO ; fpu 浮点单元异常
 VECTOR 0x2e, ZERO ; 硬盘
-VECTOR 0x2f, ZERO ; 保留
+VECTOR 0x2f, ZERO ; 保留
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 0x80 号中断 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+[bits 32]
+extern syscall_table
+section .text 
+global syscall_handle
+syscall_handle:               
+    ; 保存上下文环境
+    push 0     ; 压入 0,使栈中格式统一
+    push ds
+    push es 
+    push fs 
+    push gs
+    pushad      ; 保存通用寄存器的值, 依次是 eax, ecx, edx, ebx, esp, ebp, esi, edi
+    
+    push 0x80
+    ; 为系统调用子功能传入参数
+    push edx      ; 系统调用中第 3 个参数
+    push ecx      ; 系统调用中第 2 个参数
+    push ebx      ; 系统调用中第 1 个参数
+    ; 调用子功能处理函数
+    call [syscall_table + eax*4]
+    add esp, 12   ; 跨过上面的三个参数
+
+    ; 将 call 调用后的返回值存入当前内核栈中 eax 的位置
+    mov [esp + 8 *4], eax
+    jmp intr_exit    ; 返回,恢复上下文

+ 29 - 20
kernel/main.c

@@ -8,6 +8,8 @@
 #include "../device/ioqueue.h"
 #include "../device/keyboard.h"
 #include "../userprog/process.h"
+#include "../userprog/syscall-init.h"
+#include "../lib/user/syscall.h"
 
 void kernel_thread_a_func(void *);
 void kernel_thread_b_func(void *);
@@ -15,6 +17,7 @@ void user_prog_a(void *);
 void user_prog_b(void *);
 
 int test_var_a = 0, test_var_b = 0;
+int prog_a_pid = 0, prog_b_pid = 0;
 
 int main(void)
 {
@@ -28,12 +31,16 @@ int main(void)
     // put_int((uintptr_t)addr);
     // put_str("\n");
 
-    thread_start("kernel_thread_a_func", 31, kernel_thread_a_func, "argA ");
-    thread_start("kernel_thread_a_func", 31, kernel_thread_b_func, "argB ");
     process_execute(user_prog_a, "user_prog_a");
     // process_execute(user_prog_b, "user_prog_b");
 
     intr_enable(); // 打开中断,使中断起作用
+    console_put_str(" main_pid:0x");
+    console_put_int(sys_getpid());
+    console_put_str("\n");
+
+    thread_start("kernel_thread_a_func", 31, kernel_thread_a_func, "argA ");
+    thread_start("kernel_thread_a_func", 31, kernel_thread_b_func, "argB ");
     // 主线程会一直执行, 直到被中断或被其他线程强制结束
     while (1)
         ;
@@ -41,36 +48,38 @@ int main(void)
 }
 
 /*在线程中运行的函数*/
-void kernel_thread_a_func(void *UNUSED(arg))
+void kernel_thread_a_func(void *arg)
 {
     // 用 void 来表示通用类型,这样就可以传递任意类型的参数
-    while (1)
-    {
-        console_put_str("v_a:0x");
-        console_put_int(test_var_a);
-    }
+    char *para = arg;
+    console_put_str(" thread_a_pid:0x");
+    console_put_int(sys_getpid());
+    console_put_char('\n');
+    console_put_str(" prog_a_pid:0x");
+    console_put_int(prog_a_pid);
+    console_put_char('\n');
 }
-void kernel_thread_b_func(void *UNUSED(arg))
+void kernel_thread_b_func(void *arg)
 {
-    while (1)
-    {
-        console_put_str(" v_b:0x");
-        console_put_int(test_var_b);
-    }
+    char *para = arg;
+    console_put_str(" thread_b_pid:0x");
+    console_put_int(sys_getpid());
+    console_put_char('\n');
+    console_put_str(" prog_b_pid:0x");
+    console_put_int(prog_b_pid);
+    console_put_char('\n');
 }
 
 /*测试用户进程*/
 void user_prog_a(void *UNUSED(arg))
 {
+    prog_a_pid = getpid();
     while (1)
-    {
-        test_var_a++;
-    }
+        ;
 }
 void user_prog_b(void *UNUSED(arg))
 {
+    prog_b_pid = getpid();
     while (1)
-    {
-        test_var_b++;
-    }
+        ;
 }

+ 0 - 0
lib/user/.keep


+ 41 - 0
lib/user/syscall.c

@@ -0,0 +1,41 @@
+#include "syscall.h"
+
+#define _syscall0(NUMBER) ({                                           \
+    int retval;                                                        \
+    asm volatile("int $0x80" : "=a"(retval) : "a"(NUMBER) : "memory"); \
+    retval;                                                            \
+})
+#define _syscall1(NUMBER, ARG1) ({ \
+    int retval;                    \
+    asm volatile(                  \
+        "int $0x80"                \
+        : "=a"(retval)             \
+        : "a"(NUMBER), "b"(ARG1)   \
+        : "memory");               \
+    retval;                        \
+})
+
+#define _syscall2(NUMBER, ARG1, ARG2) ({    \
+    int retval;                             \
+    asm volatile(                           \
+        "int $0x80"                         \
+        : "=a"(retval)                      \
+        : "a"(NUMBER), "b"(ARG1), "c"(ARG2) \
+        : "memory");                        \
+    retval;                                 \
+})
+
+#define _syscall3(NUMBER, ARG1, ARG2, ARG3) ({         \
+    int retval;                                        \
+    asm volatile(                                      \
+        "int $0x80"                                    \
+        : "=a"(retval)                                 \
+        : "a"(NUMBER), "b"(ARG1), "c"(ARG2), "d"(ARG3) \
+        : "memory");                                   \
+    retval;                                            \
+})
+
+uint32_t getpid(void)
+{
+    return _syscall0(SYS_GETPID);
+}

+ 10 - 0
lib/user/syscall.h

@@ -0,0 +1,10 @@
+#ifndef __LIB_USER_SYSCALL_H
+#define __LIB_USER_SYSCALL_H
+#include "stdint.h"
+enum SYSCALL_NR
+{
+    SYS_GETPID // 系统调用子功能号
+};
+
+uint32_t getpid(void);
+#endif // !__LIB_USER_SYSCALL_H

+ 15 - 4
makefile

@@ -5,6 +5,7 @@ DIS_IMG = ./hd30M.img
 AS = nasm
 CC = /usr/local/i386elfgcc/bin/i386-elf-gcc
 LD = /usr/local/i386elfgcc/bin/i386-elf-ld
+NM = /usr/local/i386elfgcc/bin/i386-elf-nm
 LIB = -I lib/ -I lib/kernel -I lib/user/ -I kernel/ -I device/ -I thread/
 BOOTLIB = -I boot/include/
 ASFLAGS = -f elf
@@ -16,7 +17,7 @@ OBJS = $(BUILD_O_DIR)/main.o $(BUILD_O_DIR)/init.o $(BUILD_O_DIR)/interrupt.o  \
 	$(BUILD_O_DIR)/memory.o $(BUILD_O_DIR)/thread.o $(BUILD_O_DIR)/list.o  \
 	$(BUILD_O_DIR)/switch.o $(BUILD_O_DIR)/sync.o $(BUILD_O_DIR)/console.o \
 	$(BUILD_O_DIR)/keyboard.o $(BUILD_O_DIR)/ioqueue.o $(BUILD_O_DIR)/tss.o \
-	$(BUILD_O_DIR)/process.o
+	$(BUILD_O_DIR)/process.o $(BUILD_O_DIR)/syscall.o $(BUILD_O_DIR)/syscall-init.o
 
 ################################ C 代码编译 ################################
 $(BUILD_O_DIR)/main.o: kernel/main.c lib/kernel/print.h lib/stdint.h kernel/init.h
@@ -67,6 +68,12 @@ $(BUILD_O_DIR)/tss.o: userprog/tss.c userprog/tss.h
 $(BUILD_O_DIR)/process.o: userprog/process.c userprog/process.h
 	$(CC) $(CFLAGS) $< -o $@
 
+$(BUILD_O_DIR)/syscall.o: lib/user/syscall.c lib/user/syscall.h
+	$(CC) $(CFLAGS) $< -o $@
+
+$(BUILD_O_DIR)/syscall-init.o: userprog/syscall-init.c userprog/syscall-init.h
+	$(CC) $(CFLAGS) $< -o $@
+
 ################################ 汇编代码编译 ################################
 $(BUILD_O_DIR)/kernel.o: kernel/kernel.S
 	$(AS) $(ASFLAGS) $< -o $@
@@ -87,8 +94,10 @@ $(BUILD_BIN_DIR)/loader.bin: boot/loader.S
 $(BUILD_BIN_DIR)/kernel.bin: $(OBJS)
 	$(LD) $(LDFLAGS) $^ -o $@
 
+$(BUILD_BIN_DIR)/kernel.sym: $(BUILD_BIN_DIR)/kernel.bin
+	$(NM) $< | grep -i ' T ' | awk '{print $$1" "$$3}' > $@
 
-.PHONY:clean mk_dir mbr loader K create_img hd run build all
+.PHONY:clean mk_dir mbr loader K create_img hd run build sym all
 
 mk_dir:
 	@if [ ! -d $(BUILD_O_DIR) ]; then mkdir $(BUILD_O_DIR); fi
@@ -110,7 +119,9 @@ clean: mk_dir
 	rm -rf $(DIS_IMG)
 	rm -rf bochs_log.txt
 
-K: mk_dir $(BUILD_BIN_DIR)/kernel.bin 
+K: mk_dir $(BUILD_BIN_DIR)/kernel.bin
+
+sym: K $(BUILD_BIN_DIR)/kernel.sym
 
 mbr: mk_dir $(BUILD_BIN_DIR)/mbr.bin
 
@@ -119,5 +130,5 @@ loader: mk_dir $(BUILD_BIN_DIR)/loader.bin
 run: hd
 	bochs -f bochsrc -q
 
-all: mk_dir mbr loader K
+all: mk_dir mbr loader K sym
 	@echo "编译完成"

+ 16 - 2
thread/thread.c

@@ -1,4 +1,5 @@
 #include "thread.h"
+#include "sync.h"
 #include "../lib/string.h"
 #include "../kernel/interrupt.h"
 #include "../kernel/debug.h"
@@ -10,6 +11,9 @@ struct task_struct *main_thread;     // 主线程 PCB
 struct list thread_ready_list;       // 就绪队列
 struct list thread_all_list;         // 所有任务队列
 static struct list_elem *thread_tag; // 用于保存队列中的线程节点
+static pid_t allocate_pid(void);     // 分配 pid
+
+struct lock pid_lock;
 
 extern void switch_to(struct task_struct *cur, struct task_struct *next);
 
@@ -44,12 +48,21 @@ void thread_create(struct task_struct *pthread, thread_func function, void *func
     kthread_stack->func_arg = func_arg;
     kthread_stack->ebp = kthread_stack->ebx = kthread_stack->edi = kthread_stack->esi = 0;
 }
-
+// 分配 pid
+static pid_t allocate_pid(void)
+{
+    static pid_t next_pid = 0;
+    lock_acquire(&pid_lock);
+    next_pid++;
+    lock_release(&pid_lock);
+    return next_pid;
+}
 // 初始化线程基本信息
 void init_thread(struct task_struct *pthread, char *name, int prio)
 {
     _memset(pthread, 0, sizeof(*pthread)); // 全部置为 0
-    _strcpy(pthread->name, name);
+    pthread->pid = allocate_pid();         // 分配 pid
+    _strcpy(pthread->name, name);          // name
 
     // 线程状态, 目前只有两种状态: TASK_RUNNING, TASK_READY
     if (pthread == main_thread)
@@ -173,6 +186,7 @@ void thread_init(void)
     put_str("thread_init start\n");
     list_init(&thread_ready_list);
     list_init(&thread_all_list);
+    lock_init(&pid_lock);
     make_main_thread(); // 将当前 main 函数创建为线程
     put_str("thread_init end\n");
 }

+ 2 - 0
thread/thread.h

@@ -6,6 +6,7 @@
 
 // 通用函数类型,它将在很多线程函数中作为参数类型
 typedef void thread_func(void *);
+typedef int16_t pid_t;
 
 // 线程的状态
 enum task_status
@@ -83,6 +84,7 @@ struct thread_stack
 struct task_struct
 {
     uint32_t *self_kstack;   // 各内核线程都用自己的内核栈
+    pid_t pid;               // 任务pid
     enum task_status status; // 线程状态
     char name[16];           // 进程或线程的名字
     uint8_t priority;        // 线程优先级

+ 2 - 0
userprog/process.c

@@ -78,6 +78,8 @@ uint32_t *create_page_dir(void)
     //! 内核占据页目录表 768~1023 目录项, 即 0xc0000000 以上的地址空间
     /* 用户进程的页表不能让用户直接访问到,所以在内核空间来申请 */
     uint32_t *page_dir_vaddr = get_kernel_pages(1);
+    // put_str("create_page_dir: page_dir_vaddr: ");
+    // put_int((uintptr_t)page_dir_vaddr);
     if (page_dir_vaddr == NULL)
     {
         console_put_str("create_page_dir failed: get_kernel_pages failed!");

+ 20 - 0
userprog/syscall-init.c

@@ -0,0 +1,20 @@
+#include "syscall-init.h"
+#include "../thread/thread.h"
+#include "../lib/kernel/print.h"
+
+#define syscall_nr 32 // 最大支持的系统调用子功能个数
+typedef void *syscall;
+syscall syscall_table[syscall_nr];
+
+/* 返回当前任务的 pid */
+uint32_t sys_getpid(void)
+{
+    return running_thread()->pid;
+}
+
+void syscall_init(void)
+{
+    put_str("syscall_init start\n");
+    syscall_table[SYS_GETPID] = sys_getpid;
+    put_str("syscall_init done\n");
+}

+ 9 - 0
userprog/syscall-init.h

@@ -0,0 +1,9 @@
+#ifndef __USERPROG_SYSCALL_INIT_H
+#define __USERPROG_SYSCALL_INIT_H
+#include "../lib/stdint.h"
+#include "../lib/user/syscall.h"
+
+uint32_t sys_getpid(void);
+void syscall_init(void);
+
+#endif // !__USERPROG_SYSCALL_INIT_H