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:
parent
781630e06d
commit
c5aa5922bd
@ -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)
|
||||
|
@ -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>,
|
||||
|
@ -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 {
|
||||
|
@ -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,
|
||||
|
@ -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)
|
||||
}
|
@ -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(); }
|
||||
|
Loading…
Reference in New Issue
Block a user