1
0
mirror of https://github.com/rcore-os/rCore.git synced 2024-11-25 17:33:28 +04:00

Fix forking and sys_dup2, implement sys_getsockopt and update sys_exec

This commit is contained in:
Jiajie Chen 2019-03-07 14:21:26 +08:00
parent 781630e06d
commit c5aa5922bd
6 changed files with 71 additions and 12 deletions

View File

@ -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)

View File

@ -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<usize, FileLike>,

View File

@ -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 {

View File

@ -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,

View File

@ -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)
}

View File

@ -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(); }