Add signal user lib

This commit is contained in:
liusm18 2022-04-22 14:31:28 +08:00
parent 1d7b8141f0
commit 7a97faee6c
5 changed files with 236 additions and 11 deletions

View File

@ -35,7 +35,7 @@ pub fn syscall(syscall_id: usize, args: [usize; 3]) -> isize {
SYSCALL_EXIT => sys_exit(args[0] as i32), SYSCALL_EXIT => sys_exit(args[0] as i32),
SYSCALL_YIELD => sys_yield(), SYSCALL_YIELD => sys_yield(),
SYSCALL_KILL => sys_kill(args[0], args[1] as u32), SYSCALL_KILL => sys_kill(args[0], args[1] as u32),
SYSCALL_SIGACTION => sys_sigaction(args[0] as u32, args[1] as *const SignalAction, args[2] as *mut SignalAction), SYSCALL_SIGACTION => sys_sigaction(args[0], args[1] as *const SignalAction, args[2] as *mut SignalAction),
SYSCALL_SIGPROCMASK => sys_sigprocmask(args[0] as u32), SYSCALL_SIGPROCMASK => sys_sigprocmask(args[0] as u32),
SYSCALL_SIGRETURN => sys_sigretrun(), SYSCALL_SIGRETURN => sys_sigretrun(),
SYSCALL_GET_TIME => sys_get_time(), SYSCALL_GET_TIME => sys_get_time(),

View File

@ -2,7 +2,7 @@ use crate::fs::{open_file, OpenFlags};
use crate::mm::{translated_ref, translated_refmut, translated_str}; use crate::mm::{translated_ref, translated_refmut, translated_str};
use crate::task::{ use crate::task::{
add_task, current_task, current_user_token, exit_current_and_run_next, pid2task, add_task, current_task, current_user_token, exit_current_and_run_next, pid2task,
suspend_current_and_run_next, SignalFlags, SignalAction, suspend_current_and_run_next, SignalFlags, SignalAction, MAX_SIG,
}; };
use crate::timer::get_time_ms; use crate::timer::get_time_ms;
use alloc::string::String; use alloc::string::String;
@ -159,15 +159,18 @@ fn check_sigaction_error(signal: SignalFlags, action: usize, old_action: usize)
} }
} }
pub fn sys_sigaction(signal: u32, action: *const SignalAction, old_action: *mut SignalAction) -> isize { pub fn sys_sigaction(signum: usize, action: *const SignalAction, old_action: *mut SignalAction) -> isize {
let token = current_user_token(); let token = current_user_token();
if let Some(task) = current_task() { if let Some(task) = current_task() {
let mut inner = task.inner_exclusive_access(); let mut inner = task.inner_exclusive_access();
if let Some(flag) = SignalFlags::from_bits(signal) { if signum as usize > MAX_SIG {
return -1;
}
if let Some(flag) = SignalFlags::from_bits(1 << signum) {
if check_sigaction_error(flag, action as usize, old_action as usize) { if check_sigaction_error(flag, action as usize, old_action as usize) {
return -1; return -1;
} }
let old_kernel_action = inner.signal_actions.table[signal as usize]; let old_kernel_action = inner.signal_actions.table[signum];
if old_kernel_action.mask != SignalFlags::from_bits(40).unwrap() { if old_kernel_action.mask != SignalFlags::from_bits(40).unwrap() {
*translated_refmut(token, old_action) = old_kernel_action; *translated_refmut(token, old_action) = old_kernel_action;
} else { } else {
@ -175,7 +178,7 @@ pub fn sys_sigaction(signal: u32, action: *const SignalAction, old_action: *mut
ref_old_action.handler = old_kernel_action.handler; ref_old_action.handler = old_kernel_action.handler;
} }
let ref_action = translated_ref(token, action); let ref_action = translated_ref(token, action);
inner.signal_actions.table[signal as usize] = *ref_action; inner.signal_actions.table[signum] = *ref_action;
return 0; return 0;
} }
} }

158
user/src/bin/sig_tests.rs Normal file
View File

@ -0,0 +1,158 @@
#![no_std]
#![no_main]
#[macro_use]
extern crate user_lib;
use user_lib::{sigaction, sigprocmask, SignalAction, SignalFlags, fork, exit, wait, kill, getpid, sleep};
fn func() {
println!("user_sig_test succsess");
}
fn user_sig_test_failsignum() {
let mut new = SignalAction::default();
let old = SignalAction::default();
new.handler = func as usize;
if sigaction(50, &new, &old) >= 0 {
panic!("Wrong sigaction but success!");
}
}
fn user_sig_test_kill() {
let mut new = SignalAction::default();
let old = SignalAction::default();
new.handler = func as usize;
if sigaction(10, &new, &old) < 0 {
panic!("Sigaction failed!");
}
if kill(getpid() as usize, 1 << 10) < 0 {
println!("Kill failed!");
exit(1);
}
}
fn user_sig_test_multiprocsignals() {
let pid= fork();
if pid == 0{
let mut new = SignalAction::default();
let old = SignalAction::default();
new.handler = func as usize;
if sigaction(10, &new, &old) < 0 {
panic!("Sigaction failed!");
}
} else {
if kill(pid as usize, 1 << 10) < 0 {
println!("Kill failed!");
exit(1);
}
let mut exit_code = 0;
wait(&mut exit_code);
}
}
fn user_sig_test_restore() {
let mut new = SignalAction::default();
let old = SignalAction::default();
let old2 = SignalAction::default();
new.handler = func as usize;
if sigaction(10, &new, &old) < 0 {
panic!("Sigaction failed!");
}
if sigaction(10, &old, &old2) < 0 {
panic!("Sigaction failed!");
}
if old2.handler != new.handler {
println!("Restore failed!");
exit(-1);
}
}
fn kernel_sig_test_ignore() {
sigprocmask(SignalFlags::SIGSTOP.bits() as u32);
if kill(getpid() as usize, SignalFlags::SIGSTOP.bits()) < 0{
println!("kill faild\n");
exit(-1);
}
}
fn kernel_sig_test_stop_cont() {
let pid= fork();
if pid == 0 {
kill(getpid() as usize, SignalFlags::SIGSTOP.bits());
sleep(1000);
exit(-1);
} else {
sleep(5000);
kill(pid as usize, SignalFlags::SIGCONT.bits());
let mut exit_code = 0;
wait(&mut exit_code);
}
}
fn kernel_sig_test_failignorekill() {
let mut new = SignalAction::default();
let old = SignalAction::default();
new.handler = func as usize;
if sigaction(9, &new, &old) >= 0 {
panic!("Should not set sigaction to kill!");
}
if sigaction(9, &new, 0 as *const SignalAction) >= 0 {
panic!("Should not set sigaction to kill!");
}
if sigaction(9, 0 as *const SignalAction, &old) >= 0 {
panic!("Should not set sigaction to kill!");
}
}
fn run(f: fn()) -> bool {
let pid = fork();
if pid == 0 {
f();
exit(0);
} else {
let mut exit_code: i32 = 0;
wait(&mut exit_code);
if exit_code != 0 {
println!("FAILED!");
} else {
println!("OK!");
}
exit_code == 0
}
}
#[no_mangle]
pub fn main() -> i32 {
let tests: [(fn(), &str); 7] = [
(user_sig_test_failsignum, "user_sig_test_failsignum"),
(user_sig_test_kill, "user_sig_test_kill"),
(user_sig_test_multiprocsignals, "user_sig_test_multiprocsignals"),
(user_sig_test_restore, "user_sig_test_restore"),
(kernel_sig_test_ignore, "kernel_sig_test_ignore"),
(kernel_sig_test_stop_cont, "kernel_sig_test_stop_cont"),
(kernel_sig_test_failignorekill, "kernel_sig_test_failignorekill")
];
let mut fail_num = 0;
for test in tests {
println!("Testing {}", test.1);
if !run(test.0) {
fail_num += 1;
}
}
if fail_num == 0 {
println!("ALL TESTS PASSED");
0
} else {
println!("SOME TESTS FAILED");
-1
}
}

View File

@ -139,16 +139,68 @@ pub fn sleep(period_ms: usize) {
} }
} }
/// Action for a signal
#[repr(C)]
#[derive(Debug, Clone, Copy)]
pub struct SignalAction {
pub handler: usize,
pub mask: SignalFlags
}
impl Default for SignalAction {
fn default() -> Self {
Self {
handler: 0,
mask: SignalFlags::empty()
}
}
}
bitflags! { bitflags! {
pub struct SignalFlags: i32 { pub struct SignalFlags: i32 {
const SIGDEF = 1; // Default signal handling
const SIGHUP = 1 << 1;
const SIGINT = 1 << 2; const SIGINT = 1 << 2;
const SIGQUIT = 1 << 3;
const SIGILL = 1 << 4; const SIGILL = 1 << 4;
const SIGTRAP = 1 << 5;
const SIGABRT = 1 << 6; const SIGABRT = 1 << 6;
const SIGBUS = 1 << 7;
const SIGFPE = 1 << 8; const SIGFPE = 1 << 8;
const SIGKILL = 1 << 9;
const SIGUSR1 = 1 << 10;
const SIGSEGV = 1 << 11; const SIGSEGV = 1 << 11;
const SIGUSR2 = 1 << 12;
const SIGPIPE = 1 << 13;
const SIGALRM = 1 << 14;
const SIGTERM = 1 << 15;
const SIGSTKFLT = 1 << 16;
const SIGCHLD = 1 << 17;
const SIGCONT = 1 << 18;
const SIGSTOP = 1 << 19;
const SIGTSTP = 1 << 20;
const SIGTTIN = 1 << 21;
const SIGTTOU = 1 << 22;
const SIGURG = 1 << 23;
const SIGXCPU = 1 << 24;
const SIGXFSZ = 1 << 25;
const SIGVTALRM = 1 << 26;
const SIGPROF = 1 << 27;
const SIGWINCH = 1 << 28;
const SIGIO = 1 << 29;
const SIGPWR = 1 << 30;
const SIGSYS = 1 << 31;
} }
} }
pub fn kill(pid: usize, signal: i32) -> isize { pub fn kill(pid: usize, signal: i32) -> isize {
sys_kill(pid, signal) sys_kill(pid, signal)
} }
pub fn sigaction(signum: usize, action: *const SignalAction, old_action: *const SignalAction) -> isize {
sys_sigaction(signum, action, old_action)
}
pub fn sigprocmask(mask: u32) -> isize {
sys_sigprocmask(mask)
}

View File

@ -1,5 +1,7 @@
use core::arch::asm; use core::arch::asm;
use crate::SignalAction;
const SYSCALL_DUP: usize = 24; const SYSCALL_DUP: usize = 24;
const SYSCALL_OPEN: usize = 56; const SYSCALL_OPEN: usize = 56;
const SYSCALL_CLOSE: usize = 57; const SYSCALL_CLOSE: usize = 57;
@ -9,6 +11,8 @@ const SYSCALL_WRITE: usize = 64;
const SYSCALL_EXIT: usize = 93; const SYSCALL_EXIT: usize = 93;
const SYSCALL_YIELD: usize = 124; const SYSCALL_YIELD: usize = 124;
const SYSCALL_KILL: usize = 129; const SYSCALL_KILL: usize = 129;
const SYSCALL_SIGACTION: usize = 134;
const SYSCALL_SIGPROCMASK: usize = 135;
const SYSCALL_GET_TIME: usize = 169; const SYSCALL_GET_TIME: usize = 169;
const SYSCALL_GETPID: usize = 172; const SYSCALL_GETPID: usize = 172;
const SYSCALL_FORK: usize = 220; const SYSCALL_FORK: usize = 220;
@ -91,3 +95,11 @@ pub fn sys_exec(path: &str, args: &[*const u8]) -> isize {
pub fn sys_waitpid(pid: isize, exit_code: *mut i32) -> isize { pub fn sys_waitpid(pid: isize, exit_code: *mut i32) -> isize {
syscall(SYSCALL_WAITPID, [pid as usize, exit_code as usize, 0]) syscall(SYSCALL_WAITPID, [pid as usize, exit_code as usize, 0])
} }
pub fn sys_sigaction(signum: usize, action: *const SignalAction, old_action: *const SignalAction) -> isize {
syscall(SYSCALL_SIGACTION, [signum, action as usize, old_action as usize])
}
pub fn sys_sigprocmask(mask: u32) -> isize {
syscall(SYSCALL_SIGPROCMASK, [mask as usize, 0, 0])
}