mirror of
https://github.com/rcore-os/rCore-Tutorial-v3.git
synced 2024-11-22 17:36:25 +04:00
Add signal user lib
This commit is contained in:
parent
1d7b8141f0
commit
7a97faee6c
@ -35,7 +35,7 @@ pub fn syscall(syscall_id: usize, args: [usize; 3]) -> isize {
|
||||
SYSCALL_EXIT => sys_exit(args[0] as i32),
|
||||
SYSCALL_YIELD => sys_yield(),
|
||||
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_SIGRETURN => sys_sigretrun(),
|
||||
SYSCALL_GET_TIME => sys_get_time(),
|
||||
|
@ -2,7 +2,7 @@ use crate::fs::{open_file, OpenFlags};
|
||||
use crate::mm::{translated_ref, translated_refmut, translated_str};
|
||||
use crate::task::{
|
||||
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 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();
|
||||
if let Some(task) = current_task() {
|
||||
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) {
|
||||
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() {
|
||||
*translated_refmut(token, old_action) = old_kernel_action;
|
||||
} 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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
158
user/src/bin/sig_tests.rs
Normal file
158
user/src/bin/sig_tests.rs
Normal 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
|
||||
}
|
||||
}
|
@ -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! {
|
||||
pub struct SignalFlags: i32 {
|
||||
const SIGINT = 1 << 2;
|
||||
const SIGILL = 1 << 4;
|
||||
const SIGABRT = 1 << 6;
|
||||
const SIGFPE = 1 << 8;
|
||||
const SIGSEGV = 1 << 11;
|
||||
const SIGDEF = 1; // Default signal handling
|
||||
const SIGHUP = 1 << 1;
|
||||
const SIGINT = 1 << 2;
|
||||
const SIGQUIT = 1 << 3;
|
||||
const SIGILL = 1 << 4;
|
||||
const SIGTRAP = 1 << 5;
|
||||
const SIGABRT = 1 << 6;
|
||||
const SIGBUS = 1 << 7;
|
||||
const SIGFPE = 1 << 8;
|
||||
const SIGKILL = 1 << 9;
|
||||
const SIGUSR1 = 1 << 10;
|
||||
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 {
|
||||
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)
|
||||
}
|
||||
|
@ -1,5 +1,7 @@
|
||||
use core::arch::asm;
|
||||
|
||||
use crate::SignalAction;
|
||||
|
||||
const SYSCALL_DUP: usize = 24;
|
||||
const SYSCALL_OPEN: usize = 56;
|
||||
const SYSCALL_CLOSE: usize = 57;
|
||||
@ -9,6 +11,8 @@ const SYSCALL_WRITE: usize = 64;
|
||||
const SYSCALL_EXIT: usize = 93;
|
||||
const SYSCALL_YIELD: usize = 124;
|
||||
const SYSCALL_KILL: usize = 129;
|
||||
const SYSCALL_SIGACTION: usize = 134;
|
||||
const SYSCALL_SIGPROCMASK: usize = 135;
|
||||
const SYSCALL_GET_TIME: usize = 169;
|
||||
const SYSCALL_GETPID: usize = 172;
|
||||
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 {
|
||||
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])
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user