# userprog **Repository Path**: IvoryThule/userprog ## Basic Information - **Project Name**: userprog - **Description**: pintos2.1.3 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2025-05-25 - **Last Updated**: 2025-05-28 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # Pintos ## 实验目标 实现 Pintos 操作系统的用户进程系统调用接口,包括文件操作、进程管理等功能(虽然但是其实就是能通过那80个测试点) --- ## 实验步骤与关键实现 ### 1. 系统调用初始化 在 [`syscall_init`](userprog/syscall.c) 中注册系统调用中断处理函数: ```c void syscall_init (void) { intr_register_int (0x30, 3, INTR_ON, syscall_handler, "syscall"); } ``` --- ### 2. 系统调用分发与参数校验 在 [`syscall_handler`](userprog/syscall.c) 中,根据系统调用号分发到对应的处理函数,并对用户传入的指针参数进行校验: ```c static void syscall_handler (struct intr_frame *f UNUSED) { uint32_t* p = f->esp; check_ptr(p+1); int syscall_number = *p; p++; switch (syscall_number) { case SYS_HALT: sys_halt(); NOT_REACHED(); break; case SYS_EXIT: sys_exit(*p); break; // ... 其他系统调用 ... case SYS_READ: { int fd = *p; char *buffer = (char*)*(p+1); unsigned size = *(p+2); check_buffer(buffer, size); f->eax = sys_read(fd, buffer, size); break; } // ... default: printf("[ERROR] system call %d is unimplemented!\n", syscall_number); exit_special(); break; } } ``` --- ### 3. 用户指针校验 实现 [`check_ptr`](userprog/syscall.c) 和 [`check_buffer`](userprog/syscall.c) 对用户空间指针和缓冲区进行有效性检查,防止内核崩溃: ```c void *check_ptr(const void *vaddr) { if (!is_user_vaddr(vaddr)) exit_special(); void *ptr = pagedir_get_page(thread_current()->pagedir, vaddr); if (!ptr) exit_special(); // 检查4字节内容 for (uint8_t i = 0; i < 4; i++) { if (get_user((uint8_t *)vaddr + i) == -1) exit_special(); } return ptr; } ``` --- ### 4. 文件操作系统调用实现 #### 文件打开、关闭、读写、定位等 - 每个线程维护自己的文件描述符表(`file_list`),通过 [`find_file`](userprog/syscall.c) 查找。 - 文件操作均加锁,防止并发冲突。 关键代码示例: ```c int sys_open(const char*file) { acquire_file_lock(); struct file * open_file = filesys_open(file); release_file_lock(); struct thread *cur = thread_current(); if(open_file){ struct thread_file*temp = malloc(sizeof(struct thread_file)); temp->fd = cur->next_fd++; temp->file = open_file; list_push_back(&cur->file_list, &temp->file_elem); return temp->fd; } return -1; } int sys_read(int fd, char*buffer, unsigned size) { if(fd==0) { // 标准输入 for(int i=0;ifile, buffer, size); release_file_lock(); return res; } return -1; } } void sys_close(int fd) { struct thread_file*temp = find_file(fd); if(temp) { acquire_file_lock(); file_close(temp->file); release_file_lock(); list_remove(&temp->file_elem); free(temp); } } ``` --- ### 5. 进程管理系统调用实现 如 `sys_exit`、`sys_exec`、`sys_wait` 等,直接调用进程管理相关内核函数。 ```c void sys_exit (int status) { thread_current()->pcb->exitcode = status; thread_exit(); } ``` --- ### 6. 文件锁机制 为防止多线程/多进程并发访问文件系统时出现竞态,所有文件操作前后均调用 [`acquire_file_lock`](threads/thread.c) 和 [`release_file_lock`](threads/thread.c)。 --- ## 解决思路总结 1. **参数校验**:所有用户传入的指针都必须校验,防止非法访问内核空间。 2. **文件描述符管理**:每个线程维护自己的文件描述符表,分配唯一 fd。 3. **并发控制**:文件操作加锁,保证线程安全。 4. **系统调用分发**:通过中断和系统调用号分发到具体实现。 5. **资源回收**:进程退出时关闭所有打开的文件,释放资源。 --- ## 关键文件 - [`userprog/syscall.c`](userprog/syscall.c) - [`threads/thread.c`](threads/thread.c)