running busybox ash until poll

This commit is contained in:
Jianfeng Jiang 2022-11-15 14:08:21 +08:00
parent 4c344f79f2
commit 9cf8fe1777
25 changed files with 615 additions and 31 deletions

3
.gitattributes vendored
View File

@ -4,4 +4,5 @@ src/kxos-user/hello_c/hello filter=lfs diff=lfs merge=lfs -text
src/kxos-user/execve/execve filter=lfs diff=lfs merge=lfs -text
src/kxos-user/execve/hello filter=lfs diff=lfs merge=lfs -text
src/kxos-user/fork_c/fork filter=lfs diff=lfs merge=lfs -text
src/kxos-user/signal_c/signal_test filter=lfs diff=lfs merge=lfs -text
src/kxos-user/signal_c/signal_test filter=lfs diff=lfs merge=lfs -text
src/kxos-user/busybox/busybox filter=lfs diff=lfs merge=lfs -text

View File

@ -211,6 +211,12 @@ impl From<core::ffi::FromBytesWithNulError> for Error {
}
}
impl From<alloc::ffi::NulError> for Error {
fn from(_: alloc::ffi::NulError) -> Self {
Error::with_message(Errno::E2BIG, "Cannot find null in cstring")
}
}
#[macro_export]
macro_rules! return_errno {
($errno: expr) => {

View File

@ -0,0 +1,13 @@
use crate::prelude::*;
bitflags! {
pub struct IoEvents: u32 {
const POLLIN = 0x0001;
const POLLPRI = 0x0002;
const POLLOUT = 0x0004;
const POLLERR = 0x0008;
const POLLHUP = 0x0010;
const POLLNVAL = 0x0020;
const POLLRDHUP = 0x2000;
}
}

View File

@ -0,0 +1,36 @@
use crate::prelude::*;
use crate::define_fcntl_cmd;
define_fcntl_cmd! {
F_DUPFD = 0,
F_GETFD = 1,
F_SETFD = 2,
F_DUPFD_CLOEXEC = 1030
}
#[macro_export]
macro_rules! define_fcntl_cmd {
($($name: ident = $value: expr),*) => {
#[repr(i32)]
#[derive(Debug, Clone, Copy)]
#[allow(non_camel_case_types)]
pub enum FcntlCmd {
$($name = $value,)*
}
$(
pub const $name: i32 = $value;
)*
impl TryFrom<i32> for FcntlCmd {
type Error = Error;
fn try_from(value: i32) -> Result<Self> {
match value {
$($name => Ok(FcntlCmd::$name),)*
_ => return_errno!(Errno::EINVAL),
}
}
}
}
}

View File

@ -0,0 +1,26 @@
use crate::prelude::*;
use core::{any::Any, fmt::Debug};
use super::events::IoEvents;
use super::ioctl::IoctlCmd;
pub type FileDescripter = i32;
/// The basic operations defined on a file
pub trait File: Send + Sync + Debug + Any {
fn read(&self, buf: &mut [u8]) -> Result<usize> {
panic!("read unsupported");
}
fn write(&self, buf: &[u8]) -> Result<usize> {
panic!("write unsupported");
}
fn ioctl(&self, cmd: &mut IoctlCmd) -> Result<i32> {
panic!("ioctl unsupported");
}
fn poll(&self) -> IoEvents {
IoEvents::empty()
}
}

View File

@ -0,0 +1,53 @@
use crate::prelude::*;
use super::{
file::{File, FileDescripter},
stdio::{Stderr, Stdin, Stdout, FD_STDERR, FD_STDIN, FD_STDOUT},
};
#[derive(Debug, Clone)]
pub struct FileTable {
table: BTreeMap<FileDescripter, Arc<dyn File>>,
}
impl FileTable {
pub fn new() -> Self {
Self {
table: BTreeMap::new(),
}
}
pub fn new_with_stdio() -> Self {
let mut table = BTreeMap::new();
table.insert(FD_STDIN, Arc::new(Stdin) as Arc<dyn File>);
table.insert(FD_STDOUT, Arc::new(Stdout) as Arc<dyn File>);
table.insert(FD_STDERR, Arc::new(Stderr) as Arc<dyn File>);
Self { table }
}
pub fn dup(&mut self, fd: FileDescripter, new_fd: Option<FileDescripter>) -> Result<()> {
let file = self.table.get(&fd).map_or_else(
|| return_errno_with_message!(Errno::ENOENT, "No such file"),
|f| Ok(f.clone()),
)?;
let new_fd = if let Some(new_fd) = new_fd {
new_fd
} else {
self.max_fd() + 1
};
if self.table.contains_key(&new_fd) {
return_errno_with_message!(Errno::EBADF, "Fd exists");
}
self.table.insert(new_fd, file);
Ok(())
}
fn max_fd(&self) -> FileDescripter {
self.table.iter().map(|(fd, _)| fd.clone()).max().unwrap()
}
pub fn get_file(&self, fd: FileDescripter) -> Option<&Arc<dyn File>> {
self.table.get(&fd)
}
}

View File

@ -0,0 +1,42 @@
pub mod termio;
use crate::define_ioctl_cmd;
use crate::prelude::*;
define_ioctl_cmd! {
// Get terminal attributes
TCGETS = 0x5401,
TCSETS = 0x5402,
// Get the process group ID of the foreground process group on this terminal
TIOCGPGRP = 0x540f,
// Set the foreground process group ID of this terminal.
TIOCSPGRP = 0x5410,
// Set window size
TIOCGWINSZ = 0x5413,
TIOCSWINSZ = 0x5414
}
#[macro_export]
macro_rules! define_ioctl_cmd {
($($name: ident = $value: expr),*) => {
#[repr(u32)]
#[derive(Debug, Clone, Copy)]
pub enum IoctlCmd {
$($name = $value,)*
}
$(
pub const $name: u32 = $value;
)*
impl TryFrom<u32> for IoctlCmd {
type Error = Error;
fn try_from(value: u32) -> Result<Self> {
match value {
$($name => Ok(IoctlCmd::$name),)*
_ => return_errno!(Errno::EINVAL),
}
}
}
}
}

View File

@ -0,0 +1,45 @@
//! This definition is from occlum
const KERNEL_NCCS: usize = 19;
type TcflagT = u32;
type CcT = u8;
type SpeedT = u32;
#[derive(Debug, Clone, Copy, Pod)]
#[repr(C)]
pub struct KernelTermios {
pub c_iflags: TcflagT,
pub c_oflags: TcflagT,
pub c_cflags: TcflagT,
pub c_lflags: TcflagT,
pub c_line: CcT,
pub c_cc: [CcT; KERNEL_NCCS],
}
impl KernelTermios {
/// TODO: This fake result is from whitley
pub fn fake_kernel_termios() -> Self {
let mut termios = KernelTermios::new();
termios.c_iflags = 0x6d02;
termios.c_oflags = 0x5;
termios.c_cflags = 0x4bf;
termios.c_lflags = 0x8acb;
termios.c_line = 0;
termios.c_cc = [
0x03, 0x1c, 0x7f, 0x15, 0x04, 0x00, 0x01, 0x00, 0x11, 0x13, 0x1a, 0xff, 0x12, 0x0f,
0x17, 0x16, 0xff, 0x00, 0x00,
];
termios
}
fn new() -> Self {
KernelTermios {
c_iflags: 0,
c_oflags: 0,
c_cflags: 0,
c_lflags: 0,
c_line: 0,
c_cc: [0; KERNEL_NCCS],
}
}
}

View File

@ -1 +1,8 @@
pub mod events;
pub mod fcntl;
pub mod file;
pub mod file_table;
pub mod ioctl;
pub mod poll;
pub mod stat;
pub mod stdio;

View File

@ -0,0 +1,45 @@
#![allow(non_camel_case_types)]
use super::events::IoEvents;
use super::file::FileDescripter;
pub type c_nfds = u64;
// https://github.com/torvalds/linux/blob/master/include/uapi/asm-generic/poll.h
#[derive(Debug, Clone, Copy, Pod)]
#[repr(C)]
pub struct c_pollfd {
fd: FileDescripter,
events: i16,
revents: i16,
}
#[derive(Debug, Clone, Copy)]
pub struct PollFd {
pub fd: FileDescripter,
pub events: IoEvents,
pub revents: IoEvents,
}
impl From<c_pollfd> for PollFd {
fn from(raw: c_pollfd) -> Self {
let events = IoEvents::from_bits_truncate(raw.events as _);
let revents = IoEvents::from_bits_truncate(raw.revents as _);
Self {
fd: raw.fd,
events,
revents,
}
}
}
impl From<PollFd> for c_pollfd {
fn from(raw: PollFd) -> Self {
let events = raw.events.bits() as i16;
let revents = raw.revents.bits() as i16;
Self {
fd: raw.fd,
events,
revents,
}
}
}

View File

@ -58,4 +58,13 @@ impl Stat {
stat.st_blksize = 1024;
stat
}
/// Fake stat for a dir
pub fn fake_dir_stat() -> Self {
let mut stat = Stat::default();
stat.st_mode = S_IFDIR | 0o755;
stat.st_nlink = 20;
stat.st_blksize = 4096;
stat
}
}

View File

@ -0,0 +1,18 @@
use super::file::{File, FileDescripter};
pub const FD_STDIN: FileDescripter = 0;
pub const FD_STDOUT: FileDescripter = 1;
pub const FD_STDERR: FileDescripter = 2;
#[derive(Debug)]
pub struct Stdin;
#[derive(Debug)]
pub struct Stdout;
#[derive(Debug)]
pub struct Stderr;
impl File for Stdin {}
impl File for Stdout {}
impl File for Stderr {}

View File

@ -10,7 +10,7 @@
#![feature(btree_drain_filter)]
#![feature(const_option)]
use crate::prelude::*;
use crate::{prelude::*, user_apps::UserApp};
use kxos_frame::{info, println};
use process::Process;
@ -59,16 +59,15 @@ pub fn init_process() {
process.pid()
);
for app in get_all_apps() {
let app_name = app.app_name();
info!("[kxos-std/lib.rs] spwan {:?} process", app.app_name());
let argv = vec![app_name.clone()];
let process = Process::spawn_user_process(app_name, app.app_content(), argv, Vec::new());
info!(
"[kxos-std/lib.rs] {:?} process exits, pid = {}",
app.app_name(),
process.pid()
);
for app in get_all_apps().into_iter().last() {
let UserApp {
app_name,
app_content,
argv,
envp,
} = app;
info!("[kxos-std/lib.rs] spwan {:?} process", app_name);
Process::spawn_user_process(app_name.clone(), app_content, argv, Vec::new());
}
loop {

View File

@ -127,6 +127,8 @@ pub fn clone_child(parent_context: CpuContext, clone_args: CloneArgs) -> Result<
debug!("child process pid: {}", child_pid);
debug!("rip = 0x{:x}", child_cpu_context.gp_regs.rip);
let child_file_table = current.file_table.lock().clone();
// inherit parent's sig disposition
let child_sig_dispositions = current.sig_dispositions().lock().clone();
// sig queue is set empty
@ -144,6 +146,7 @@ pub fn clone_child(parent_context: CpuContext, clone_args: CloneArgs) -> Result<
child_user_vm,
Some(child_user_space),
None,
child_file_table,
child_sig_dispositions,
child_sig_queues,
child_sig_mask,

View File

@ -12,6 +12,7 @@ use self::signal::sig_queues::SigQueues;
use self::signal::signals::kernel::KernelSignal;
use self::status::ProcessStatus;
use self::task::create_user_task_from_elf;
use crate::fs::file_table::FileTable;
use crate::prelude::*;
use kxos_frame::sync::WaitQueue;
use kxos_frame::{task::Task, user::UserSpace, vm::VmSpace};
@ -30,10 +31,10 @@ pub mod table;
pub mod task;
pub mod wait;
static PID_ALLOCATOR: AtomicUsize = AtomicUsize::new(0);
static PID_ALLOCATOR: AtomicI32 = AtomicI32::new(0);
pub type Pid = usize;
pub type Pgid = usize;
pub type Pid = i32;
pub type Pgid = i32;
pub type ExitCode = i32;
/// Process stands for a set of tasks that shares the same userspace.
@ -45,7 +46,10 @@ pub struct Process {
filename: Option<CString>,
user_space: Option<Arc<UserSpace>>,
user_vm: Option<UserVm>,
/// wait for child status changed
waiting_children: WaitQueue,
/// wait for io events
poll_queue: WaitQueue,
// Mutable Part
/// The exit code
@ -55,11 +59,13 @@ pub struct Process {
/// Parent process
parent: Mutex<Option<Weak<Process>>>,
/// Children processes
children: Mutex<BTreeMap<usize, Arc<Process>>>,
children: Mutex<BTreeMap<Pid, Arc<Process>>>,
/// Process group
process_group: Mutex<Option<Weak<ProcessGroup>>>,
/// Process name
process_name: Mutex<Option<ProcessName>>,
/// File table
file_table: Mutex<FileTable>,
// Signal
sig_dispositions: Mutex<SigDispositions>,
@ -91,6 +97,7 @@ impl Process {
user_vm: Option<UserVm>,
user_space: Option<Arc<UserSpace>>,
process_group: Option<Weak<ProcessGroup>>,
file_table: FileTable,
sig_dispositions: SigDispositions,
sig_queues: SigQueues,
sig_mask: SigMask,
@ -105,6 +112,7 @@ impl Process {
};
let children = BTreeMap::new();
let waiting_children = WaitQueue::new();
let poll_queue = WaitQueue::new();
let process_name = exec_filename.as_ref().map(|filename| {
let mut process_name = ProcessName::new();
process_name.set_name(filename).unwrap();
@ -117,12 +125,14 @@ impl Process {
user_space,
user_vm,
waiting_children,
poll_queue,
exit_code: AtomicI32::new(0),
status: Mutex::new(ProcessStatus::Runnable),
parent: Mutex::new(parent),
children: Mutex::new(children),
process_group: Mutex::new(process_group),
process_name: Mutex::new(process_name),
file_table: Mutex::new(file_table),
sig_dispositions: Mutex::new(sig_dispositions),
sig_queues: Mutex::new(sig_queues),
sig_mask: Mutex::new(sig_mask),
@ -134,6 +144,10 @@ impl Process {
&self.waiting_children
}
pub fn poll_queue(&self) -> &WaitQueue {
&self.poll_queue
}
/// init a user process and send the process to scheduler
pub fn spawn_user_process(
filename: CString,
@ -175,6 +189,7 @@ impl Process {
create_user_task_from_elf(filename, elf_file_content, weak_process, argv, envp);
let user_space = task.user_space().map(|user_space| user_space.clone());
let user_vm = UserVm::new();
let file_table = FileTable::new_with_stdio();
let sig_dispositions = SigDispositions::new();
let sig_queues = SigQueues::new();
let sig_mask = SigMask::new_empty();
@ -185,6 +200,7 @@ impl Process {
Some(user_vm),
user_space,
None,
file_table,
sig_dispositions,
sig_queues,
sig_mask,
@ -208,6 +224,7 @@ impl Process {
let kernel_process = Arc::new_cyclic(|weak_process_ref| {
let weak_process = weak_process_ref.clone();
let task = Task::new(task_fn, weak_process, None).expect("spawn kernel task failed");
let file_table = FileTable::new();
let sig_dispositions = SigDispositions::new();
let sig_queues = SigQueues::new();
let sig_mask = SigMask::new_empty();
@ -218,6 +235,7 @@ impl Process {
None,
None,
None,
file_table,
sig_dispositions,
sig_queues,
sig_mask,
@ -283,6 +301,10 @@ impl Process {
let _ = self.process_group.lock().insert(process_group);
}
pub fn file_table(&self) -> &Mutex<FileTable> {
&self.file_table
}
/// create a new process group for the process and add it to globle table.
/// Then set the process group for current process.
fn create_and_set_process_group(self: &Arc<Self>) {
@ -388,7 +410,7 @@ impl Process {
child_process.exit_code()
}
pub fn children(&self) -> &Mutex<BTreeMap<usize, Arc<Process>>> {
pub fn children(&self) -> &Mutex<BTreeMap<Pid, Arc<Process>>> {
&self.children
}

View File

@ -0,0 +1,27 @@
use super::{SyscallReturn, SYS_FCNTL};
use crate::fs::fcntl::FcntlCmd;
use crate::{fs::file::FileDescripter, prelude::*};
pub fn sys_fcntl(fd: FileDescripter, cmd: i32, arg: u64) -> Result<SyscallReturn> {
debug!("[syscall][id={}][SYS_FCNTL]", SYS_FCNTL);
let fcntl_cmd = FcntlCmd::try_from(cmd)?;
debug!("fd = {}, cmd = {:?}, arg = {}", fd, fcntl_cmd, arg);
match fcntl_cmd {
FcntlCmd::F_DUPFD_CLOEXEC => {
// FIXME: deal with the cloexec flag
let current = current!();
let mut file_table = current.file_table().lock();
let new_fd = arg as FileDescripter;
file_table.dup(fd, Some(new_fd))?;
return Ok(SyscallReturn::Return(new_fd as _));
}
FcntlCmd::F_SETFD => {
if arg != 1 {
panic!("Unknown setfd argument");
}
// TODO: Set cloexec
return Ok(SyscallReturn::Return(0));
}
_ => todo!(),
}
}

View File

@ -0,0 +1,15 @@
use crate::memory::write_bytes_to_user;
use crate::prelude::*;
use super::SyscallReturn;
use super::SYS_GETCWD;
pub fn sys_getcwd(buf: Vaddr, len: usize) -> Result<SyscallReturn> {
debug!("[syscall][id={}][SYS_GETCWD]", SYS_GETCWD);
// TODO: getcwd only return a fake result now
let fake_cwd = CString::new("/")?;
let bytes = fake_cwd.as_bytes_with_nul();
let write_len = len.min(bytes.len());
write_bytes_to_user(buf, &bytes[..write_len])?;
Ok(SyscallReturn::Return(write_len as _))
}

View File

@ -0,0 +1,54 @@
use crate::fs::file::FileDescripter;
use crate::fs::ioctl::termio::KernelTermios;
use crate::fs::ioctl::IoctlCmd;
use crate::memory::read_val_from_user;
use crate::memory::write_val_to_user;
use crate::prelude::*;
use super::SyscallReturn;
use super::SYS_IOCTL;
pub fn sys_ioctl(fd: FileDescripter, cmd: u32, arg: Vaddr) -> Result<SyscallReturn> {
debug!("[syscall][id={}][SYS_IOCTL]", SYS_IOCTL);
let ioctl_cmd = IoctlCmd::try_from(cmd)?;
debug!(
"fd = {}, ioctl_cmd = {:?}, arg = 0x{:x}",
fd, ioctl_cmd, arg
);
match ioctl_cmd {
IoctlCmd::TCGETS => {
if fd == 0 || fd == 1 {
let termio = KernelTermios::fake_kernel_termios();
write_val_to_user(arg, &termio)?;
} else {
todo!()
}
}
IoctlCmd::TIOCGPGRP => {
// FIXME: Get the process group ID of the foreground process group on this terminal.
// We currently only return the pgid of current process
let current = current!();
let pgid = current.pgid();
write_val_to_user(arg, &pgid)?;
}
IoctlCmd::TIOCSPGRP => {
let pgid = read_val_from_user::<i32>(arg)?;
debug!("set foreground process group id: {}", pgid);
// TODO: Set the foreground process group
}
IoctlCmd::TCSETS => {
if fd == 0 || fd == 1 {
let termio = read_val_from_user::<KernelTermios>(arg)?;
debug!("termio = {:x?}", termio);
// TODO: Set termios
} else {
todo!()
}
}
IoctlCmd::TIOCGWINSZ => {
// TODO:get window size
}
_ => todo!(),
}
Ok(SyscallReturn::Return(0))
}

View File

@ -0,0 +1,24 @@
use crate::fs::stat::Stat;
use crate::memory::read_cstring_from_user;
use crate::memory::write_val_to_user;
use crate::prelude::*;
use crate::syscall::constants::MAX_FILENAME_LEN;
use super::SyscallReturn;
use super::SYS_LSTAT;
pub fn sys_lstat(filename_ptr: Vaddr, stat_buf_ptr: Vaddr) -> Result<SyscallReturn> {
debug!("[syscall][id={}][SYS_LSTAT]", SYS_LSTAT);
let filename = read_cstring_from_user(filename_ptr, MAX_FILENAME_LEN)?;
debug!(
"filename = {:?}, stat_buf_ptr = 0x{:x}",
filename, stat_buf_ptr
);
// TODO: only return a fake result here
if filename == CString::new(".")? || filename == CString::new("/")? {
let stat = Stat::fake_dir_stat();
write_val_to_user(stat_buf_ptr, &stat)?;
return Ok(SyscallReturn::Return(0));
}
todo!()
}

View File

@ -8,9 +8,11 @@ use crate::syscall::clone::sys_clone;
use crate::syscall::execve::sys_execve;
use crate::syscall::exit::sys_exit;
use crate::syscall::exit_group::sys_exit_group;
use crate::syscall::fcntl::sys_fcntl;
use crate::syscall::fork::sys_fork;
use crate::syscall::fstat::sys_fstat;
use crate::syscall::futex::sys_futex;
use crate::syscall::getcwd::sys_getcwd;
use crate::syscall::getegid::sys_getegid;
use crate::syscall::geteuid::sys_geteuid;
use crate::syscall::getgid::sys_getgid;
@ -19,9 +21,13 @@ use crate::syscall::getpid::sys_getpid;
use crate::syscall::getppid::sys_getppid;
use crate::syscall::gettid::sys_gettid;
use crate::syscall::getuid::sys_getuid;
use crate::syscall::ioctl::sys_ioctl;
use crate::syscall::kill::sys_kill;
use crate::syscall::lstat::sys_lstat;
use crate::syscall::mmap::sys_mmap;
use crate::syscall::mprotect::sys_mprotect;
use crate::syscall::openat::sys_openat;
use crate::syscall::poll::sys_poll;
use crate::syscall::prctl::sys_prctl;
use crate::syscall::readlink::sys_readlink;
use crate::syscall::rt_sigaction::sys_rt_sigaction;
@ -46,9 +52,11 @@ mod constants;
mod execve;
mod exit;
mod exit_group;
mod fcntl;
mod fork;
mod fstat;
mod futex;
mod getcwd;
mod getegid;
mod geteuid;
mod getgid;
@ -57,9 +65,13 @@ mod getpid;
mod getppid;
mod gettid;
mod getuid;
mod ioctl;
mod kill;
mod lstat;
mod mmap;
mod mprotect;
mod openat;
mod poll;
mod prctl;
mod readlink;
mod rt_sigaction;
@ -77,16 +89,18 @@ mod writev;
define_syscall_nums!(
SYS_WRITE = 1,
SYS_FSTAT = 5,
SYS_LSTAT = 6,
SYS_POLL = 7,
SYS_MMAP = 9,
SYS_MPROTECT = 10,
SYS_BRK = 12,
SYS_RT_SIGACTION = 13,
SYS_RT_SIGPROCMASK = 14,
SYS_RT_SIGRETRUN = 15,
SYS_IOCTL = 16,
SYS_WRITEV = 20,
SYS_ACCESS = 21,
SYS_SCHED_YIELD = 24,
SYS_IOCTL = 29,
SYS_GETPID = 39,
SYS_CLONE = 56,
SYS_FORK = 57,
@ -96,6 +110,7 @@ define_syscall_nums!(
SYS_KILL = 62,
SYS_UNAME = 63,
SYS_FCNTL = 72,
SYS_GETCWD = 79,
SYS_READLINK = 89,
SYS_GETUID = 102,
SYS_GETGID = 104,
@ -106,12 +121,12 @@ define_syscall_nums!(
SYS_GETPGRP = 111,
SYS_PRCTL = 157,
SYS_ARCH_PRCTL = 158,
SYS_GETCWD = 183,
SYS_GETTID = 186,
SYS_FUTEX = 202,
SYS_EXIT_GROUP = 231,
SYS_TGKILL = 234,
SYS_WAITID = 247
SYS_WAITID = 247,
SYS_OPENAT = 257
);
pub struct SyscallArgument {
@ -170,16 +185,18 @@ pub fn syscall_dispatch(
match syscall_number {
SYS_WRITE => syscall_handler!(3, sys_write, args),
SYS_FSTAT => syscall_handler!(2, sys_fstat, args),
SYS_LSTAT => syscall_handler!(2, sys_lstat, args),
SYS_POLL => syscall_handler!(3, sys_poll, args),
SYS_MMAP => syscall_handler!(6, sys_mmap, args),
SYS_MPROTECT => syscall_handler!(3, sys_mprotect, args),
SYS_BRK => syscall_handler!(1, sys_brk, args),
SYS_RT_SIGACTION => syscall_handler!(4, sys_rt_sigaction, args),
SYS_RT_SIGPROCMASK => syscall_handler!(4, sys_rt_sigprocmask, args),
SYS_RT_SIGRETRUN => syscall_handler!(0, sys_rt_sigreturn, context),
SYS_IOCTL => syscall_handler!(3, sys_ioctl, args),
SYS_WRITEV => syscall_handler!(3, sys_writev, args),
SYS_ACCESS => syscall_handler!(2, sys_access, args),
SYS_SCHED_YIELD => syscall_handler!(0, sys_sched_yield),
SYS_IOCTL => todo!(),
SYS_GETPID => syscall_handler!(0, sys_getpid),
SYS_CLONE => syscall_handler!(5, sys_clone, args, context.clone()),
SYS_FORK => syscall_handler!(0, sys_fork, context.clone()),
@ -188,7 +205,8 @@ pub fn syscall_dispatch(
SYS_WAIT4 => syscall_handler!(3, sys_wait4, args),
SYS_KILL => syscall_handler!(2, sys_kill, args),
SYS_UNAME => syscall_handler!(1, sys_uname, args),
SYS_FCNTL => todo!(),
SYS_FCNTL => syscall_handler!(3, sys_fcntl, args),
SYS_GETCWD => syscall_handler!(2, sys_getcwd, args),
SYS_READLINK => syscall_handler!(3, sys_readlink, args),
SYS_GETUID => syscall_handler!(0, sys_getuid),
SYS_GETGID => syscall_handler!(0, sys_getgid),
@ -199,12 +217,12 @@ pub fn syscall_dispatch(
SYS_GETPGRP => syscall_handler!(0, sys_getpgrp),
SYS_PRCTL => syscall_handler!(5, sys_prctl, args),
SYS_ARCH_PRCTL => syscall_handler!(2, sys_arch_prctl, args, context),
SYS_GETCWD => todo!(),
SYS_GETTID => syscall_handler!(0, sys_gettid),
SYS_FUTEX => syscall_handler!(6, sys_futex, args),
SYS_EXIT_GROUP => syscall_handler!(1, sys_exit_group, args),
SYS_TGKILL => syscall_handler!(3, sys_tgkill, args),
SYS_WAITID => syscall_handler!(5, sys_waitid, args),
SYS_OPENAT => syscall_handler!(4, sys_openat, args),
_ => panic!("Unsupported syscall number: {}", syscall_number),
}
}

View File

@ -0,0 +1,29 @@
use crate::fs::file::FileDescripter;
use crate::memory::read_cstring_from_user;
use crate::prelude::*;
use crate::syscall::constants::MAX_FILENAME_LEN;
use super::SyscallReturn;
use super::SYS_OPENAT;
const AT_FDCWD: FileDescripter = -100;
pub fn sys_openat(
dirfd: FileDescripter,
pathname_addr: Vaddr,
flags: i32,
mode: u16,
) -> Result<SyscallReturn> {
debug!("[syscall][id={}][SYS_OPENAT]", SYS_OPENAT);
let pathname = read_cstring_from_user(pathname_addr, MAX_FILENAME_LEN)?;
debug!(
"dirfd = {}, pathname = {:?}, flags = {}, mode = {}",
dirfd, pathname, flags, mode
);
// TODO: do real openat
if dirfd == AT_FDCWD && pathname == CString::new("/etc/passwd")? {
return_errno!(Errno::ENOENT);
}
todo!()
}

View File

@ -0,0 +1,64 @@
use core::time::Duration;
use crate::fs::poll::{c_pollfd, PollFd};
use crate::memory::{read_val_from_user, write_val_to_user};
use crate::{fs::poll::c_nfds, prelude::*};
use super::SyscallReturn;
use super::SYS_POLL;
pub fn sys_poll(fds: Vaddr, nfds: c_nfds, timeout: i32) -> Result<SyscallReturn> {
debug!("[syscall][id={}][SYS_POLL]", SYS_POLL);
let mut read_addr = fds;
let mut pollfds = Vec::with_capacity(nfds as _);
for _ in 0..nfds {
let c_poll_fd = read_val_from_user::<c_pollfd>(read_addr)?;
let poll_fd = PollFd::from(c_poll_fd);
pollfds.push(poll_fd);
// FIXME: do we need to respect align of c_pollfd here?
read_addr += core::mem::size_of::<c_pollfd>();
}
let timeout = if timeout == 0 {
None
} else {
Some(Duration::from_millis(timeout as _))
};
debug!(
"poll_fds = {:?}, nfds = {}, timeout = {:?}",
pollfds, nfds, timeout
);
let current = current!();
// FIXME: respect timeout parameter
let ready_files = current.poll_queue().wait_until(|| {
let mut ready_files = 0;
for pollfd in &mut pollfds {
let file_table = current.file_table().lock();
let file = file_table.get_file(pollfd.fd);
match file {
None => return Some(Err(Error::new(Errno::EBADF))),
Some(file) => {
let file_events = file.poll();
let polled_events = pollfd.events.intersection(file_events);
if !polled_events.is_empty() {
ready_files += 1;
pollfd.revents |= polled_events;
}
}
}
}
if ready_files > 0 {
return Some(Ok(ready_files));
} else {
return None;
}
})?;
let mut write_addr = fds;
for pollfd in pollfds {
let c_poll_fd = c_pollfd::from(pollfd);
write_val_to_user(write_addr, &c_poll_fd)?;
// FIXME: do we need to respect align of c_pollfd here?
write_addr += core::mem::size_of::<c_pollfd>();
}
Ok(SyscallReturn::Return(ready_files))
}

View File

@ -25,9 +25,7 @@ pub fn sys_rt_sigaction(
let current = current!();
let mut sig_dispositions = current.sig_dispositions().lock();
let old_action = sig_dispositions.get(sig_num);
debug!("old_action = {:x?}", old_action);
let old_action_c = old_action.to_c();
debug!("old_action_c = {:x?}", old_action_c);
sig_dispositions.set(sig_num, sig_action);
if old_sig_action_ptr != 0 {
write_val_to_user(old_sig_action_ptr, &old_action_c)?;

View File

@ -1,8 +1,10 @@
use crate::prelude::*;
pub struct UserApp {
app_name: CString,
app_content: &'static [u8],
pub app_name: CString,
pub app_content: &'static [u8],
pub argv: Vec<CString>,
pub envp: Vec<CString>,
}
impl UserApp {
@ -11,15 +13,17 @@ impl UserApp {
UserApp {
app_name,
app_content,
argv: Vec::new(),
envp: Vec::new(),
}
}
pub fn app_name(&self) -> CString {
self.app_name.clone()
pub fn set_argv(&mut self, argv: Vec<CString>) {
self.argv = argv;
}
pub fn app_content(&self) -> &'static [u8] {
self.app_content
pub fn set_envp(&mut self, envp: Vec<CString>) {
self.envp = envp;
}
}
@ -52,6 +56,16 @@ pub fn get_all_apps() -> Vec<UserApp> {
let signal_test = UserApp::new("/signal_test", read_signal_test_content());
res.push(signal_test);
// busybox
let mut busybox = UserApp::new("/busybox", read_busybox_content());
let argv = ["./busybox", "sh"];
let envp = ["SHELL=/bin/bash", "COLORTERM=truecolor", "TERM_PROGRAM_VERSION=1.73.0", "LC_ADDRESS=zh_CN.UTF-8", "LC_NAME=zh_CN.UTF-8", "LC_MONETARY=zh_CN.UTF-8", "PWD=/", "LOGNAME=jiangjf", "XDG_SESSION_TYPE=tty", "VSCODE_GIT_ASKPASS_NODE=/home/jiangjf/.vscode-server/bin/8fa188b2b301d36553cbc9ce1b0a146ccb93351f/node", "MOTD_SHOWN=pam", "HOME=/home/jiangjf", "LC_PAPER=zh_CN.UTF-8", "LANG=en_US.UTF-8", "LS_COLORS=rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:mi=00:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arc=01;31:*.arj=01;31:*.taz=01;31:*.lha=01;31:*.lz4=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.tzo=01;31:*.t7z=01;31:*.zip=01;31:*.z=01;31:*.dz=01;31:*.gz=01;31:*.lrz=01;31:*.lz=01;31:*.lzo=01;31:*.xz=01;31:*.zst=01;31:*.tzst=01;31:*.bz2=01;31:*.bz=01;31:*.tbz=01;31:*.tbz2=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.war=01;31:*.ear=01;31:*.sar=01;31:*.rar=01;31:*.alz=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.cab=01;31:*.wim=01;31:*.swm=01;31:*.dwm=01;31:*.esd=01;31:*.jpg=01;35:*.jpeg=01;35:*.mjpg=01;35:*.mjpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.webm=01;35", "GIT_ASKPASS=/home/jiangjf/.vscode-server/bin/8fa188b2b301d36553cbc9ce1b0a146ccb93351f/extensions/git/dist/askpass.sh", "SSH_CONNECTION=30.177.3.156 54687 30.77.178.76 22", "VSCODE_GIT_ASKPASS_EXTRA_ARGS=", "LESSCLOSE=/usr/bin/lesspipe %s %s", "XDG_SESSION_CLASS=user", "TERM=xterm-256color", "LC_IDENTIFICATION=zh_CN.UTF-8", "LESSOPEN=| /usr/bin/lesspipe %s", "USER=jiangjf", "VSCODE_GIT_IPC_HANDLE=/run/user/1015/vscode-git-623b69fb06.sock", "SHLVL=2", "LC_TELEPHONE=zh_CN.UTF-8", "LC_MEASUREMENT=zh_CN.UTF-8", "XDG_SESSION_ID=8884", "XDG_RUNTIME_DIR=/run/user/1015", "SSH_CLIENT=30.177.3.156 54687 22", "LC_TIME=zh_CN.UTF-8", "VSCODE_GIT_ASKPASS_MAIN=/home/jiangjf/.vscode-server/bin/8fa188b2b301d36553cbc9ce1b0a146ccb93351f/extensions/git/dist/askpass-main.js", "XDG_DATA_DIRS=/usr/local/share:/usr/share:/var/lib/snapd/desktop", "BROWSER=/home/jiangjf/.vscode-server/bin/8fa188b2b301d36553cbc9ce1b0a146ccb93351f/bin/helpers/browser.sh", "PATH=/home/jiangjf/.vscode-server/bin/8fa188b2b301d36553cbc9ce1b0a146ccb93351f/bin/remote-cli:/home/jiangjf/.cargo/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin", "DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1015/bus", "LC_NUMERIC=zh_CN.UTF-8", "TERM_PROGRAM=vscode", "VSCODE_IPC_HOOK_CLI=/run/user/1015/vscode-ipc-ed06ed64-441d-4b59-a8fe-90ce2cf29a8a.sock", "OLDPWD=/"];
let argv = to_vec_cstring(&argv).unwrap();
let envp = to_vec_cstring(&envp).unwrap();
busybox.set_argv(argv);
busybox.set_envp(envp);
res.push(busybox);
res
}
@ -82,3 +96,16 @@ fn read_fork_c_content() -> &'static [u8] {
fn read_signal_test_content() -> &'static [u8] {
include_bytes!("../../kxos-user/signal_c/signal_test")
}
fn read_busybox_content() -> &'static [u8] {
include_bytes!("../../kxos-user/busybox/busybox")
}
fn to_vec_cstring(raw_strs: &[&str]) -> Result<Vec<CString>> {
let mut res = Vec::new();
for raw_str in raw_strs {
let cstring = CString::new(*raw_str)?;
res.push(cstring);
}
Ok(res)
}

3
src/kxos-user/busybox/busybox Executable file
View File

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:c3019f1ee7431b4a7cbcbace4c114679430a6c1277081bed11a290aeb0bc9d6e
size 2644416