From c5aa5922bd5f90515100c2ab78ffaee99f1513c4 Mon Sep 17 00:00:00 2001 From: Jiajie Chen Date: Thu, 7 Mar 2019 14:21:26 +0800 Subject: [PATCH] Fix forking and sys_dup2, implement sys_getsockopt and update sys_exec --- kernel/src/arch/x86_64/interrupt/trapframe.rs | 2 ++ kernel/src/process/structs.rs | 10 +++++++ kernel/src/syscall/fs.rs | 26 +++++++++++++++---- kernel/src/syscall/mod.rs | 5 ++-- kernel/src/syscall/net.rs | 23 ++++++++++++++++ kernel/src/syscall/proc.rs | 17 ++++++++---- 6 files changed, 71 insertions(+), 12 deletions(-) diff --git a/kernel/src/arch/x86_64/interrupt/trapframe.rs b/kernel/src/arch/x86_64/interrupt/trapframe.rs index 8fd5b2f..f4531d9 100644 --- a/kernel/src/arch/x86_64/interrupt/trapframe.rs +++ b/kernel/src/arch/x86_64/interrupt/trapframe.rs @@ -181,6 +181,8 @@ impl Context { tf: { let mut tf = tf.clone(); tf.rax = 0; + // skip syscall inst; + tf.rip = tf.rip + 2; tf }, }.push_at(kstack_top) diff --git a/kernel/src/process/structs.rs b/kernel/src/process/structs.rs index 91b720c..78d3aa4 100644 --- a/kernel/src/process/structs.rs +++ b/kernel/src/process/structs.rs @@ -1,4 +1,5 @@ use alloc::{boxed::Box, collections::BTreeMap, string::String, sync::Arc, vec::Vec}; +use core::fmt; use log::*; use rcore_fs::vfs::INode; @@ -43,6 +44,15 @@ pub enum FileLike { Socket(SocketWrapper) } +impl fmt::Debug for FileLike { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + FileLike::File(_) => write!(f, "File"), + FileLike::Socket(_) => write!(f, "Socket"), + } + } +} + pub struct Process { pub memory_set: MemorySet, pub files: BTreeMap, diff --git a/kernel/src/syscall/fs.rs b/kernel/src/syscall/fs.rs index 6394e6e..d1b6657 100644 --- a/kernel/src/syscall/fs.rs +++ b/kernel/src/syscall/fs.rs @@ -27,6 +27,7 @@ pub fn sys_write(fd: usize, base: *const u8, len: usize) -> SysResult { info!("write: fd: {}, base: {:?}, len: {:#x}", fd, base, len); let mut proc = process(); proc.memory_set.check_array(base, len)?; + match proc.files.get(&fd) { Some(FileLike::File(_)) => sys_write_file(&mut proc, fd, base, len), Some(FileLike::Socket(_)) => sys_write_socket(&mut proc, fd, base, len), @@ -300,9 +301,13 @@ pub fn sys_open(path: *const u8, flags: usize, mode: usize) -> SysResult { pub fn sys_close(fd: usize) -> SysResult { info!("close: fd: {:?}", fd); let mut proc = process(); + sys_close_internal(&mut proc, fd) +} + +fn sys_close_internal(proc: &mut Process, fd: usize) -> SysResult { match proc.files.remove(&fd) { Some(FileLike::File(_)) => Ok(0), - Some(FileLike::Socket(wrapper)) => sys_close_socket(&mut proc, fd, wrapper.handle), + Some(FileLike::Socket(wrapper)) => sys_close_socket(proc, fd, wrapper.handle), None => Err(SysError::EINVAL), } } @@ -415,11 +420,22 @@ pub fn sys_dup2(fd1: usize, fd2: usize) -> SysResult { info!("dup2: {} {}", fd1, fd2); let mut proc = process(); if proc.files.contains_key(&fd2) { - return Err(SysError::EINVAL); + // close fd2 first if it is opened + sys_close_internal(&mut proc, fd2)?; + } + + match proc.files.get(&fd1) { + Some(FileLike::File(file)) => { + let new_file = FileLike::File(file.clone()); + proc.files.insert(fd2, new_file); + Ok(fd2 as isize) + }, + Some(FileLike::Socket(wrapper)) => { + let new_wrapper = wrapper.clone(); + sys_dup2_socket(&mut proc, new_wrapper, fd2) + }, + None => Err(SysError::EINVAL) } - let file = proc.get_file(fd1)?.clone(); - proc.files.insert(fd2, FileLike::File(file)); - Ok(0) } pub fn sys_chdir(path: *const u8) -> SysResult { diff --git a/kernel/src/syscall/mod.rs b/kernel/src/syscall/mod.rs index 1901595..167c2b7 100644 --- a/kernel/src/syscall/mod.rs +++ b/kernel/src/syscall/mod.rs @@ -68,12 +68,12 @@ pub fn syscall(id: usize, args: [usize; 6], tf: &mut TrapFrame) -> isize { 050 => sys_listen(args[0], args[1]), 051 => sys_getsockname(args[0], args[1] as *mut u8, args[2] as *mut u32), 054 => sys_setsockopt(args[0], args[1], args[2], args[3] as *const u8, args[4]), -// 055 => sys_getsockopt(), + 055 => sys_getsockopt(args[0], args[1], args[2], args[3] as *mut u8, args[4] as *mut u32), // 056 => sys_clone(), 057 => sys_fork(tf), // use fork for vfork 058 => sys_fork(tf), - 059 => sys_exec(args[0] as *const u8, args[1] as usize, args[2] as *const *const u8, tf), + 059 => sys_exec(args[0] as *const u8, args[1] as *const *const u8, args[2] as *const *const u8, tf), 060 => sys_exit(args[0] as isize), 061 => sys_wait(args[0], args[1] as *mut i32), // TODO: wait4 062 => sys_kill(args[0]), @@ -222,6 +222,7 @@ pub enum SysError { ENOSYS = 38, ENOTEMPTY = 39, ENOTSOCK = 80, + ENOPROTOOPT = 92, EPFNOSUPPORT = 96, EAFNOSUPPORT = 97, ENOBUFS = 105, diff --git a/kernel/src/syscall/net.rs b/kernel/src/syscall/net.rs index bf056bd..88ba1e9 100644 --- a/kernel/src/syscall/net.rs +++ b/kernel/src/syscall/net.rs @@ -148,6 +148,21 @@ pub fn sys_setsockopt( Ok(0) } +pub fn sys_getsockopt( + fd: usize, + level: usize, + optname: usize, + optval: *mut u8, + optlen: *mut u32, +) -> SysResult { + info!( + "getsockopt: fd: {}, level: {}, optname: {} optval: {:?} optlen: {:?}", + fd, level, optname, optval, optlen + ); + warn!("sys_getsockopt is unimplemented"); + Err(SysError::ENOPROTOOPT) +} + #[repr(C)] struct SockaddrIn { sin_family: u16, @@ -700,3 +715,11 @@ pub fn poll_socket(wrapper: &SocketWrapper) -> (bool, bool, bool) { (input, output, err) } + +pub fn sys_dup2_socket(proc: &mut Process, wrapper: SocketWrapper, fd: usize) -> SysResult { + proc.files.insert( + fd, + FileLike::Socket(wrapper), + ); + Ok(fd as isize) +} \ No newline at end of file diff --git a/kernel/src/syscall/proc.rs b/kernel/src/syscall/proc.rs index 7c42037..1bcfc02 100644 --- a/kernel/src/syscall/proc.rs +++ b/kernel/src/syscall/proc.rs @@ -48,23 +48,28 @@ pub fn sys_wait(pid: usize, code: *mut i32) -> SysResult { } } -pub fn sys_exec(name: *const u8, argc: usize, argv: *const *const u8, tf: &mut TrapFrame) -> SysResult { +pub fn sys_exec(name: *const u8, argv: *const *const u8, envp: *const *const u8, tf: &mut TrapFrame) -> SysResult { + info!("exec: name: {:?}, argv: {:?} envp: {:?}", name, argv, envp); let proc = process(); let name = if name.is_null() { String::from("") } else { unsafe { proc.memory_set.check_and_clone_cstr(name)? } }; - if argc <= 0 { + + if argv.is_null() { return Err(SysError::EINVAL); } // Check and copy args to kernel let mut args = Vec::new(); unsafe { - for &ptr in slice::from_raw_parts(argv, argc) { - let arg = proc.memory_set.check_and_clone_cstr(ptr)?; + let mut current_argv = argv as *const *const u8; + while !(*current_argv).is_null() { + let arg = proc.memory_set.check_and_clone_cstr(*current_argv)?; args.push(arg); + current_argv = current_argv.add(1); } } - info!("exec: name: {:?}, args: {:?}", name, args); + info!("exec: args {:?}", args); + info!("exec {:?}", proc.files); // Read program file let path = args[0].as_str(); @@ -77,6 +82,8 @@ pub fn sys_exec(name: *const u8, argc: usize, argv: *const *const u8, tf: &mut T // Make new Thread let iter = args.iter().map(|s| s.as_str()); let mut thread = Thread::new_user(buf.as_slice(), iter); + thread.proc.lock().files = proc.files.clone(); + thread.proc.lock().cwd = proc.cwd.clone(); // Activate new page table unsafe { thread.proc.lock().memory_set.activate(); }