signal的处理(kill命令)以及一些其他的改进 (#100)

* 将entry.S中冗余的ret_from_syscall代码删除,改为jmp Restore_all

* new: 增加判断pt_regs是否来自用户态的函数

* new: rust的cli和sti封装

* 将原有的判断pt_regs是否来自用户态的代码,统一改为调用user_mode函数

* ffz函数:获取u64中的第一个值为0的bit

* spinlock增加 spinlock irq spin_unlock_irq

* 临时解决显示刷新线程迟迟不运行的问题

* 更改ffi_convert的生命周期标签

* new: 测试signal用的app

* 解决由于编译器优化导致local_irq_restore无法获取到正确的rflags的值的问题

* new: exec命令增加"&"后台运行选项

* procfs->status增加显示preempt和虚拟运行时间

* 更改引用计数的FFIBind2Rust trait中的生命周期标签

* new: signal处理(kill)

* 更正在review中发现的一些细节问题
This commit is contained in:
login 2022-12-08 22:59:51 +08:00 committed by GitHub
parent f8b55f6d3f
commit 1a2eaa402f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
30 changed files with 1002 additions and 192 deletions

View File

@ -0,0 +1,11 @@
use core::arch::x86_64::_popcnt64;
/// @brief ffz - 寻找u64中的第一个0所在的位从第0位开始寻找
/// 请注意如果x中没有0,那么结果将是未定义的。请确保传入的x至少存在1个0
///
/// @param x 目标u64
/// @return i32 bit-number(0..63) of the first (least significant) zero bit.
#[inline]
pub fn ffz(x: u64) -> i32 {
return unsafe { _popcnt64((x & ((!x) - 1)).try_into().unwrap()) };
}

View File

@ -1,21 +1,15 @@
use core::arch::asm;
use core::{arch::asm, ptr::read_volatile};
#[inline]
pub fn local_irq_save(flags: &mut u64) {
unsafe {
asm!(
"pushfq",
"pop rax",
"mov rax, {0}",
"cli",
out(reg)(*flags),
);
asm!("pushfq", "pop rax", "mov rax, {0}", "cli", out(reg)(*flags),);
}
}
#[inline]
pub fn local_irq_restore(flags: &u64) {
let x = *flags;
let x = unsafe { read_volatile(flags) };
unsafe {
asm!("push r15",

View File

@ -1,3 +1,5 @@
pub mod irqflags;
#[macro_use]
pub mod current;
pub mod current;
pub mod ptrace;
pub mod bitops;

View File

@ -0,0 +1,12 @@
#![allow(dead_code)]
use crate::include::bindings::bindings::pt_regs;
/// @brief 判断给定的栈帧是否来自用户态
/// 判断方法为根据代码段选择子是否具有ring3的访问权限低2bit均为1
pub fn user_mode(regs: *const pt_regs)->bool{
if (unsafe{(*regs).cs} & 0x3) != 0{
return true;
}else {
return false;
}
}

View File

@ -0,0 +1,18 @@
#![allow(dead_code)]
use core::arch::asm;
/// @brief 关闭中断
#[inline]
pub fn cli(){
unsafe{
asm!("cli");
}
}
/// @brief 开启中断
#[inline]
pub fn sti(){
unsafe{
asm!("sti");
}
}

View File

@ -1,3 +1,4 @@
#[macro_use]
pub mod asm;
pub mod cpu;
pub mod cpu;
pub mod interrupt;

View File

@ -66,6 +66,7 @@ int video_refresh_daemon(void *unused)
memcpy((void *)video_frame_buffer_info.vaddr, (void *)video_refresh_target->vaddr,
video_refresh_target->size);
spin_unlock(&daemon_refresh_lock);
video_daemon_pcb->virtual_runtime = 0xfffff0000000; // 临时解决由于显示刷新进程的虚拟运行时间过大/过小,导致其不运行,或者一直运行的问题。将来应使用实时调度解决它
}
video_refresh_expire_jiffies = cal_next_n_ms_jiffies(REFRESH_INTERVAL << 1);
}
@ -83,8 +84,11 @@ void video_refresh_framebuffer(void *data)
{
if (unlikely(video_daemon_pcb == NULL))
return;
process_wakeup(video_daemon_pcb);
if (clock() >= video_refresh_expire_jiffies)
{
video_daemon_pcb->virtual_runtime = 0;
process_wakeup(video_daemon_pcb);
}
}
/**

View File

@ -60,6 +60,14 @@ ret_from_exception:
// === ===
ENTRY(ret_from_intr)
//
cli
// do_signal
movq %rsp, %rdi
callq do_signal
//
jmp Restore_all

View File

@ -24,8 +24,8 @@ void do_debug(struct pt_regs *regs, unsigned long error_code)
{
printk("[ ");
printk_color(RED, BLACK, "ERROR / TRAP");
printk(" ] do_debug(1),\tError Code:%#18lx,\tRSP:%#18lx,\tRIP:%#18lx\t CPU:%d\n", error_code, regs->rsp, regs->rip,
proc_current_cpu_id);
printk(" ] do_debug(1),\tError Code:%#18lx,\tRSP:%#18lx,\tRIP:%#18lx\t CPU:%d, pid:%d\n", error_code, regs->rsp, regs->rip,
proc_current_cpu_id, current_pcb->pid);
while (1)
hlt();

View File

@ -359,7 +359,7 @@ uint64_t sys_mkdir(struct pt_regs *regs)
// kdebug("path = %s", path);
mode_t mode = (mode_t)regs->r9;
if (regs->cs & USER_CS)
if (user_mode(regs))
return vfs_mkdir(path, mode, true);
else
return vfs_mkdir(path, mode, false);

View File

@ -124,18 +124,23 @@ static long procfs_open(struct vfs_index_node_t *inode, struct vfs_file_t *file_
switch (mode)
{
case 1:
data_puts(fdata, "Name:");
data_puts(fdata, "Name:\t");
data_puts(fdata, pcb_t->name);
data_puts(fdata, "\nstate:");
data_puts(fdata, "\nstate:\t");
data_puts(fdata, ltoa(pcb_t->state));
data_puts(fdata, "\npid:");
data_puts(fdata, "\npid:\t");
data_puts(fdata, ltoa(pcb_t->pid));
data_puts(fdata, "\nPpid:");
data_puts(fdata, "\nPpid:\t");
data_puts(fdata, ltoa(pcb_t->parent_pcb->pid));
data_puts(fdata, "\ncpu_id:");
data_puts(fdata, "\ncpu_id:\t");
data_puts(fdata, ltoa(pcb_t->cpu_id));
data_puts(fdata, "\npriority:");
data_puts(fdata, "\npriority:\t");
data_puts(fdata, ltoa(pcb_t->priority));
data_puts(fdata, "\npreempt:\t");
data_puts(fdata, ltoa(pcb_t->preempt_count));
data_puts(fdata, "\nvrtime:\t");
data_puts(fdata, ltoa(pcb_t->virtual_runtime));
// data_puts(fdata,"\n");
uint64_t hiwater_vm, text, data;

View File

@ -1,3 +1,12 @@
/**
* @file signal.h
* @author longjin (longjin@RinGoTek.cn)
* @brief signal相关类型在C语言中的导出rust版本为准
* @version 0.1
*
* @copyright Copyright (c) 2022
*
*/
#pragma once
#include <DragonOS/refcount.h>
#include <common/atomic.h>
@ -8,6 +17,8 @@
// 系统最大支持的信号数量
#define MAX_SIG_NUM 64
// sigset所占用的u64的数量
#define _NSIG_U64_CNT (MAX_SIG_NUM / 64)
typedef void __signalfn_t(int);
typedef __signalfn_t *__sighandler_t;
@ -97,6 +108,11 @@ struct sigaction
void (*sa_restorer)(void); // 暂时未实现
};
// ============ sigaction结构体中的的sa_flags的可选值 ===========
#define SA_FLAG_IGN (1UL << 0) // 当前sigaction表示忽略信号的动作
#define SA_FLAG_DFL (1UL << 1) // 当前sigaction表示系统默认的动作
#define SA_FLAG_RESTORER (1UL << 2) // 当前sigaction具有用户指定的restorer
/**
* signal_struct总是和sighand_struct一起使用sighand加锁
* signal_struct不用加锁
@ -124,4 +140,5 @@ struct sighand_struct
struct sigpending
{
sigset_t signal;
void *sigqueue; // 信号队列(在rust中实现)
};

View File

@ -1,17 +1,23 @@
use core::ptr::read_volatile;
use core::{ffi::c_void, intrinsics::size_of, ptr::read_volatile, sync::atomic::compiler_fence};
use crate::{
include::{
bindings::bindings::{
pid_t, process_control_block, process_find_pcb_by_pid, pt_regs, spinlock_t, EINVAL,
ENOTSUP, ESRCH, PF_EXITING, PF_KTHREAD, PF_WAKEKILL, PROC_INTERRUPTIBLE,
},
arch::x86_64::{
asm::{bitops::ffz, current::current_pcb, ptrace::user_mode},
interrupt::sti,
},
kBUG, kdebug, kwarn,
include::bindings::bindings::{
pid_t, process_control_block, process_do_exit, process_find_pcb_by_pid, pt_regs,
spinlock_t, verify_area, EINVAL, ENOTSUP, EPERM, ESRCH, PF_EXITING, PF_KTHREAD,
PF_SIGNALED, PF_WAKEKILL, PROC_INTERRUPTIBLE, USER_CS, USER_DS, USER_MAX_LINEAR_ADDR,
},
ipc::signal_types::sigset_add,
kBUG, kdebug, kerror, kwarn,
libs::{
ffi_convert::FFIBind2Rust,
spinlock::{spin_is_locked, spin_lock_irqsave, spin_unlock_irqrestore},
spinlock::{
spin_is_locked, spin_lock_irq, spin_lock_irqsave, spin_unlock_irq,
spin_unlock_irqrestore,
},
},
println,
process::{
@ -21,18 +27,26 @@ use crate::{
};
use super::signal_types::{
si_code_val, sigaction, sigaction__union_u, sighand_struct, siginfo, signal_struct,
sigpending, sigset_t, SignalNumber, MAX_SIG_NUM,
si_code_val, sigaction, sigaction__union_u, sigcontext, sigframe, sighand_struct, siginfo,
signal_struct, sigpending, sigset_clear, sigset_del, sigset_t, SignalNumber, MAX_SIG_NUM,
SA_FLAG_DFL, SA_FLAG_IGN, SA_FLAG_RESTORER, STACK_ALIGN, _NSIG_U64_CNT,
};
use super::signal_types::{__siginfo_union, __siginfo_union_data};
/// 默认信号处理程序占位符用于在sighand结构体中的action数组中占位
pub static DEFAULT_SIGACTION: sigaction = sigaction {
_u: sigaction__union_u { _sa_handler: None },
sa_flags: 0,
sa_flags: SA_FLAG_DFL,
sa_mask: 0,
sa_restorer: None,
};
/// 默认的“忽略信号”的sigaction
#[allow(dead_code)]
pub static DEFAULT_SIGACTION_IGNORE: sigaction = sigaction {
_u: sigaction__union_u { _sa_handler: None },
sa_flags: SA_FLAG_IGN,
sa_mask: 0,
sa_restorer: None,
};
@ -50,8 +64,8 @@ pub extern "C" fn sys_kill(regs: &pt_regs) -> u64 {
);
let pid: pid_t = regs.r8 as pid_t;
let sig: Option<SignalNumber> = SignalNumber::from_i32(regs.r9 as i32);
if sig.is_none() {
let sig: SignalNumber = SignalNumber::from(regs.r9 as i32);
if sig == SignalNumber::INVALID {
// 传入的signal数值不合法
kwarn!("Not a valid signal number");
return (-(EINVAL as i64)) as u64;
@ -61,7 +75,7 @@ pub extern "C" fn sys_kill(regs: &pt_regs) -> u64 {
let mut info = siginfo {
_sinfo: __siginfo_union {
data: __siginfo_union_data {
si_signo: sig.unwrap() as i32,
si_signo: sig as i32,
si_code: si_code_val::SI_USER as i32,
si_errno: 0,
reserved: 0,
@ -71,8 +85,12 @@ pub extern "C" fn sys_kill(regs: &pt_regs) -> u64 {
},
},
};
compiler_fence(core::sync::atomic::Ordering::SeqCst);
return signal_kill_something_info(sig.unwrap(), Some(&mut info), pid) as u64;
let retval = signal_kill_something_info(sig, Some(&mut info), pid) as u64;
compiler_fence(core::sync::atomic::Ordering::SeqCst);
return retval;
}
/// 通过kill的方式向目标进程发送信号
@ -103,10 +121,11 @@ fn signal_kill_proc_info(sig: SignalNumber, info: Option<&mut siginfo>, pid: pid
return retval;
}
println!("Target pcb = {:?}", pcb.as_ref().unwrap());
// println!("Target pcb = {:?}", pcb.as_ref().unwrap());
compiler_fence(core::sync::atomic::Ordering::SeqCst);
// step3: 调用signal_send_sig_info函数发送信息
retval = signal_send_sig_info(sig, info, pcb.unwrap());
compiler_fence(core::sync::atomic::Ordering::SeqCst);
// step4: 解锁
return retval;
}
@ -130,7 +149,7 @@ fn signal_send_sig_info(
info: Option<&mut siginfo>,
target_pcb: &mut process_control_block,
) -> i32 {
kdebug!("signal_send_sig_info");
// kdebug!("signal_send_sig_info");
// 检查sig是否符合要求如果不符合要求则退出。
if !verify_signal(sig) {
return -(EINVAL as i32);
@ -142,12 +161,13 @@ fn signal_send_sig_info(
let mut flags: u64 = 0;
// 如果上锁成功,则发送信号
if !lock_process_sighand(target_pcb, &mut flags).is_none() {
compiler_fence(core::sync::atomic::Ordering::SeqCst);
// 发送信号
retval = send_signal_locked(sig, info, target_pcb, PidType::PID);
kdebug!("flags=0x{:016x}", flags);
compiler_fence(core::sync::atomic::Ordering::SeqCst);
// kdebug!("flags=0x{:016x}", flags);
// 对sighand放锁
unlock_process_sighand(target_pcb, &flags);
unlock_process_sighand(target_pcb, flags);
}
return retval;
}
@ -160,22 +180,18 @@ fn lock_process_sighand<'a>(
pcb: &'a mut process_control_block,
flags: &mut u64,
) -> Option<&'a mut sighand_struct> {
kdebug!("lock_process_sighand");
// kdebug!("lock_process_sighand");
let sighand_ptr = sighand_struct::convert_mut(unsafe { &mut *pcb.sighand });
// kdebug!("sighand_ptr={:?}", &sighand_ptr);
if !sighand_ptr.is_some() {
kBUG!("Sighand ptr of process {pid} is NULL!", pid = pcb.pid);
return None;
} else {
kdebug!("7777");
}
let lock = { &mut sighand_ptr.unwrap().siglock };
kdebug!("123");
kdebug!("lock={}", unsafe { *(lock as *mut spinlock_t as *mut i8) });
spin_lock_irqsave(lock, flags);
kdebug!("lock={}", unsafe { *(lock as *mut spinlock_t as *mut i8) });
kdebug!("locked");
let ret = unsafe { ((*pcb).sighand as *mut sighand_struct).as_mut() };
return ret;
@ -184,13 +200,10 @@ fn lock_process_sighand<'a>(
/// @brief 对pcb的sighand结构体中的siglock进行放锁并恢复之前存储的rflags
/// @param pcb 目标pcb
/// @param flags 用来保存rflags的变量将这个值恢复到rflags寄存器中
fn unlock_process_sighand(pcb: &mut process_control_block, flags: &u64) {
kdebug!("unlock_process_sighand");
fn unlock_process_sighand(pcb: &mut process_control_block, flags: u64) {
let lock = unsafe { &mut (*pcb.sighand).siglock };
kdebug!("lock={:?}", lock);
spin_unlock_irqrestore(lock, flags);
kdebug!("lock={}", unsafe { *(lock as *mut spinlock_t as *mut i8) });
kdebug!("123443");
spin_unlock_irqrestore(lock, &flags);
}
/// @brief 判断是否需要强制发送信号,然后发送信号
@ -203,18 +216,17 @@ fn send_signal_locked(
pcb: &mut process_control_block,
pt: PidType,
) -> i32 {
kdebug!("send_signal_locked");
// 是否强制发送信号
let mut force_send = false;
// signal的信息为空
if info.is_none() {
// todo: 判断signal是否来自于一个祖先进程的namespace如果是则强制发送信号
} else {
force_send = unsafe { info.as_ref().unwrap()._sinfo.data }.si_code
force_send = unsafe { info.as_ref().unwrap()._sinfo.data.si_code }
== (si_code_val::SI_KERNEL as i32);
}
kdebug!("force send={}", force_send);
// kdebug!("force send={}", force_send);
return __send_signal_locked(sig, info, pcb, pt, force_send);
}
@ -234,18 +246,14 @@ fn __send_signal_locked(
pt: PidType,
_force_send: bool,
) -> i32 {
kdebug!("__send_signal_locked");
// kdebug!("__send_signal_locked");
let mut retval = 0;
// 判断该进入该函数时,是否已经持有了锁
println!(
"locked={}",
spin_is_locked(unsafe { &(*pcb.sighand).siglock })
);
kdebug!("1234");
let _pending: Option<&mut sigpending> = sigpending::convert_mut(&mut pcb.sig_pending);
kdebug!("567");
assert!(spin_is_locked(unsafe { &(*pcb.sighand).siglock }));
let _pending: Option<&mut sigpending> = sigpending::convert_mut(&mut pcb.sig_pending);
compiler_fence(core::sync::atomic::Ordering::SeqCst);
// 如果是kill或者目标pcb是内核线程则无需获取sigqueue直接发送信号即可
if sig == SignalNumber::SIGKILL || (pcb.flags & (PF_KTHREAD as u64)) != 0 {
complete_signal(sig, pcb, pt);
@ -253,7 +261,7 @@ fn __send_signal_locked(
// todo: 如果是其他信号则加入到sigqueue内然后complete_signal
retval = -(ENOTSUP as i32);
}
kdebug!("12342");
compiler_fence(core::sync::atomic::Ordering::SeqCst);
return retval;
}
@ -263,14 +271,15 @@ fn __send_signal_locked(
/// @param pcb 目标pcb
/// @param pt siginfo结构体中pid字段代表的含义
fn complete_signal(sig: SignalNumber, pcb: &mut process_control_block, pt: PidType) {
// kdebug!("complete_signal");
// todo: 将信号产生的消息通知到正在监听这个信号的进程引入signalfd之后在这里调用signalfd_notify)
kdebug!("complete_signal");
// 将这个信号加到目标进程的sig_pending中
sigset_add(
sigset_t::convert_mut(&mut pcb.sig_pending.signal).unwrap(),
sig,
);
compiler_fence(core::sync::atomic::Ordering::SeqCst);
// ===== 寻找需要wakeup的目标进程 =====
// 备注由于当前没有进程组的概念每个进程只有1个对应的线程因此不需要通知进程组内的每个进程。
// todo: 当引入进程组的概念后,需要完善这里,使得它能寻找一个目标进程来唤醒,接着执行信号处理的操作。
@ -298,7 +307,7 @@ fn complete_signal(sig: SignalNumber, pcb: &mut process_control_block, pt: PidTy
// todo:引入进程组后,在这里挑选一个进程来唤醒,让它执行相应的操作。
// todo!();
compiler_fence(core::sync::atomic::Ordering::SeqCst);
// todo: 到这里信号已经被放置在共享的pending队列中我们在这里把目标进程唤醒。
if _target.is_some() {
signal_wake_up(pcb, sig == SignalNumber::SIGKILL);
@ -346,12 +355,6 @@ fn sig_is_member(set: &sigset_t, _sig: SignalNumber) -> bool {
};
}
/// @brief 将指定的信号在sigset中的对应bit进行置位
#[inline]
fn sigset_add(set: &mut sigset_t, _sig: SignalNumber) {
*set |= 1 << ((_sig as u32) - 1);
}
/// @brief 判断signal的处理是否可能使得整个进程组退出
/// @return true 可能会导致退出(不一定)
#[allow(dead_code)]
@ -386,6 +389,7 @@ fn has_sig_pending(pcb: &process_control_block) -> bool {
#[inline]
fn signal_wake_up(pcb: &mut process_control_block, fatal: bool) {
// kdebug!("signal_wake_up");
let mut state: u64 = 0;
if fatal {
state = PF_WAKEKILL as u64;
@ -394,11 +398,364 @@ fn signal_wake_up(pcb: &mut process_control_block, fatal: bool) {
}
fn signal_wake_up_state(pcb: &mut process_control_block, state: u64) {
assert!(spin_is_locked(&unsafe { *pcb.sighand }.siglock));
assert!(spin_is_locked(&unsafe { (*pcb.sighand).siglock }));
// todo: 设置线程结构体的标志位为TIF_SIGPENDING
compiler_fence(core::sync::atomic::Ordering::SeqCst);
// 如果目标进程已经在运行则发起一个ipi使得它陷入内核
if !process_wake_up_state(pcb, state | (PROC_INTERRUPTIBLE as u64)) {
process_kick(pcb);
}
compiler_fence(core::sync::atomic::Ordering::SeqCst);
}
/// @brief 信号处理函数。该函数在进程退出内核态的时候会被调用,且调用前会关闭中断。
#[no_mangle]
pub extern "C" fn do_signal(regs: &mut pt_regs) {
// 检查sigpending是否为0
if current_pcb().sig_pending.signal == 0 || (!user_mode(regs)) {
// 若没有正在等待处理的信号,或者将要返回到的是内核态,则启用中断,然后返回
sti();
return;
}
// 做完上面的检查后,开中断
sti();
// return;
// kdebug!("do_signal");
let oldset = current_pcb().sig_blocked;
loop {
let (sig_number, info, ka) = get_signal_to_deliver(regs.clone());
// 所有的信号都处理完了
if sig_number == SignalNumber::INVALID {
return;
}
kdebug!(
"To handle signal [{}] for pid:{}",
sig_number as i32,
current_pcb().pid
);
let res = handle_signal(sig_number, ka.unwrap(), &info.unwrap(), &oldset, regs);
if res.is_err() {
kerror!(
"Error occurred when handling signal: {}, pid={}, errcode={}",
sig_number as i32,
current_pcb().pid,
res.unwrap_err()
);
}
}
}
/// @brief 获取要被发送的信号的signumber, siginfo, 以及对应的sigaction结构体
fn get_signal_to_deliver(
_regs: pt_regs,
) -> (
SignalNumber,
Option<siginfo>,
Option<&'static mut sigaction>,
) {
let mut info: Option<siginfo>;
let ka: Option<&mut sigaction>;
let mut sig_number;
let sighand: &mut sighand_struct;
{
let _tmp = sighand_struct::convert_mut(current_pcb().sighand);
if let Some(i) = _tmp {
sighand = i;
} else {
panic!("Sighand is NULL! pid={}", current_pcb().pid);
}
}
spin_lock_irq(&mut sighand.siglock);
loop {
(sig_number, info) =
dequeue_signal(sigset_t::convert_mut(&mut current_pcb().sig_blocked).unwrap());
// 如果信号非法,则直接返回
if sig_number == SignalNumber::INVALID {
spin_unlock_irq(unsafe { (&mut (*current_pcb().sighand).siglock) as *mut spinlock_t });
return (sig_number, None, None);
}
// 获取指向sigaction结构体的引用
let hand = sighand_struct::convert_mut(current_pcb().sighand).unwrap();
// kdebug!("hand=0x{:018x}", hand as *const sighand_struct as usize);
let tmp_ka = &mut hand.action[sig_number as usize - 1];
// 如果当前动作是忽略这个信号,则不管它了。
if (tmp_ka.sa_flags & SA_FLAG_IGN) != 0 {
continue;
} else if (tmp_ka.sa_flags & SA_FLAG_DFL) == 0 {
// 当前不采用默认的信号处理函数
ka = Some(tmp_ka);
break;
}
kdebug!(
"Use default handler to handle signal [{}] for pid {}",
sig_number as i32,
current_pcb().pid
);
// ===== 经过上面的判断,如果能走到这一步,就意味着我们采用默认的信号处理函数来处理这个信号 =====
spin_unlock_irq(&mut sighand.siglock);
// 标记当前进程由于信号而退出
current_pcb().flags |= PF_SIGNALED as u64;
// 执行进程的退出动作
unsafe { process_do_exit(info.unwrap()._sinfo.data.si_signo as u64) };
/* NOT REACHED 这部分代码将不会到达 */
}
spin_unlock_irq(&mut sighand.siglock);
return (sig_number, info, ka);
}
/// @brief 从当前进程的sigpending中取出下一个待处理的signal并返回给调用者。调用者应当处理这个信号
/// 请注意进入本函数前当前进程应当持有current_pcb().sighand.siglock
fn dequeue_signal(sig_mask: &mut sigset_t) -> (SignalNumber, Option<siginfo>) {
// kdebug!("dequeue signal");
// 获取下一个要处理的信号的编号
let sig = next_signal(
sigpending::convert_ref(&(current_pcb().sig_pending)).unwrap(),
sig_mask,
);
let info: Option<siginfo>;
if sig != SignalNumber::INVALID {
// 如果下一个要处理的信号是合法的则收集其siginfo
info = Some(collect_signal(
sig,
sigpending::convert_mut(&mut current_pcb().sig_pending).unwrap(),
));
} else {
info = None;
}
// 当一个进程具有多个线程之后在这里需要重新计算线程的flag中的TIF_SIGPENDING位
recalc_sigpending();
return (sig, info);
}
/// @brief 获取下一个要处理的信号sig number越小的信号优先级越高
///
/// @param pending 等待处理的信号
/// @param sig_mask 屏蔽了的信号
/// @return i32 下一个要处理的信号的number. 如果为0,则无效
fn next_signal(pending: &sigpending, sig_mask: &sigset_t) -> SignalNumber {
let mut sig = SignalNumber::INVALID;
let s = pending.signal;
let m = *sig_mask;
// 获取第一个待处理的信号的号码
let x = s & (!m);
if x != 0 {
sig = SignalNumber::from(ffz(!x) + 1);
return sig;
}
// 暂时只支持64种信号信号
assert_eq!(_NSIG_U64_CNT, 1);
return sig;
}
/// @brief 当一个进程具有多个线程之后在这里需要重新计算线程的flag中的TIF_SIGPENDING位
fn recalc_sigpending() {
// todo:
}
/// @brief 收集信号的信息
///
/// @param sig 要收集的信号的信息
/// @param pending 信号的排队等待标志
/// @return siginfo 信号的信息
fn collect_signal(sig: SignalNumber, pending: &mut sigpending) -> siginfo {
let (info, still_pending) = unsafe { pending.queue.as_mut() }
.unwrap()
.find_and_delete(sig);
// 如果没有仍在等待的信号则清除pending位
if !still_pending {
sigset_del(&mut pending.signal, sig);
}
if info.is_some() {
return info.unwrap();
} else {
// 信号不在sigqueue中这意味着当前信号是来自快速路径因此直接把siginfo设置为0即可。
let mut ret = siginfo::new(sig, 0, si_code_val::SI_USER);
ret._sinfo.data._sifields._kill._pid = 0;
return ret;
}
}
/// @brief 真正发送signal执行自定义的处理函数
///
/// @param sig 信号number
/// @param ka 信号响应动作
/// @param info 信号信息
/// @param oldset
/// @param regs 之前的系统调用将要返回的时候,要弹出的栈帧的拷贝
///
/// @return Result<0,i32> 若Error, 则返回错误码,否则返回Ok(0)
fn handle_signal(
sig: SignalNumber,
ka: &mut sigaction,
info: &siginfo,
oldset: &sigset_t,
regs: &mut pt_regs,
) -> Result<i32, i32> {
// 设置栈帧
let retval = setup_frame(sig, ka, info, oldset, regs);
if retval.is_err() {
return retval;
}
return Ok(0);
}
/// @brief 在用户栈上开辟一块空间,并且把内核栈的栈帧以及需要在用户态执行的代码给保存进去。
///
/// @param regs 进入信号处理流程前Restore all要弹出的内核栈栈帧
fn setup_frame(
sig: SignalNumber,
ka: &mut sigaction,
info: &siginfo,
oldset: &sigset_t,
regs: &mut pt_regs,
) -> Result<i32, i32> {
let mut err = 0;
let frame: *mut sigframe = get_stack(ka, &regs, size_of::<sigframe>());
// 要求这个frame的地址位于用户空间因此进行校验
let access_check_ok = unsafe { verify_area(frame as u64, size_of::<sigframe>() as u64) };
if !access_check_ok {
// 如果地址区域位于内核空间,则直接报错
// todo: 生成一个sigsegv
kerror!("In setup frame: access check failed");
return Err(-(EPERM as i32));
}
unsafe {
(*frame).arg0 = sig as u64;
(*frame).arg1 = &((*frame).info) as *const siginfo as usize;
(*frame).arg2 = &((*frame).context) as *const sigcontext as usize;
(*frame).handler = ka._u._sa_handler.unwrap() as *mut core::ffi::c_void;
}
// 将siginfo拷贝到用户栈
err |= copy_siginfo_to_user(unsafe { &mut (*frame).info }, info).unwrap_or(1);
// todo: 拷贝处理程序备用栈的地址、大小、ss_flags
err |= setup_sigcontext(unsafe { &mut (*frame).context }, oldset, &regs).unwrap_or(1);
// 为了与Linux的兼容性64位程序必须由用户自行指定restorer
if ka.sa_flags & SA_FLAG_RESTORER != 0 {
unsafe {
(*frame).ret_code_ptr =
(&mut ka.sa_restorer.unwrap()) as *mut unsafe extern "C" fn() as *mut c_void;
}
} else {
kerror!(
"pid-{} forgot to set SA_FLAG_RESTORER for signal {}",
current_pcb().pid,
sig as i32
);
err = 1;
}
if err != 0 {
// todo: 在这里生成一个sigsegv,然后core dump
return Err(1);
}
regs.rdi = sig as u64;
regs.rsi = unsafe { &(*frame).info as *const siginfo as u64 };
regs.rsp = frame as u64;
regs.rip = unsafe { ka._u._sa_handler.unwrap() as *const unsafe extern "C" fn() as u64 };
// 如果handler位于内核空间
if regs.rip >= USER_MAX_LINEAR_ADDR {
// 如果当前是SIGSEGV,则采用默认函数处理
if sig == SignalNumber::SIGSEGV {
ka.sa_flags |= SA_FLAG_DFL;
}
// 将rip设置为0
regs.rip = 0;
}
// 设置cs和ds寄存器
regs.cs = (USER_CS | 0x3) as u64;
regs.ds = (USER_DS | 0x3) as u64;
return if err == 0 { Ok(0) } else { Err(1) };
}
#[inline(always)]
fn get_stack(_ka: &sigaction, regs: &pt_regs, size: usize) -> *mut sigframe {
// 默认使用 用户栈的栈顶指针-128字节的红区-sigframe的大小
let mut rsp: usize = (regs.rsp as usize) - 128 - size;
// 按照要求进行对齐
rsp &= (-(STACK_ALIGN as i64)) as usize;
return rsp as *mut sigframe;
}
/// @brief 将siginfo结构体拷贝到用户栈
fn copy_siginfo_to_user(to: *mut siginfo, from: &siginfo) -> Result<i32, i32> {
// 验证目标地址是否为用户空间
if unsafe { !verify_area(to as u64, size_of::<siginfo>() as u64) } {
// 如果目标地址空间不为用户空间,则直接返回错误码 -EPERM
return Err(-(EPERM as i32));
}
let retval: Result<i32, i32> = Ok(0);
// todo: 将这里按照si_code的类型来分别拷贝不同的信息。
// 这里参考linux-2.6.39 网址: http://opengrok.ringotek.cn/xref/linux-2.6.39/arch/ia64/kernel/signal.c#137
unsafe {
(*to)._sinfo.data._sifields._kill._pid = from._sinfo.data._sifields._kill._pid;
}
return retval;
}
/// @brief 设置目标的sigcontext
///
/// @param context 要被设置的目标sigcontext
/// @param mask 要被暂存的信号mask标志位
/// @param regs 进入信号处理流程前Restore all要弹出的内核栈栈帧
fn setup_sigcontext(context: &mut sigcontext, mask: &sigset_t, regs: &pt_regs) -> Result<i32, i32> {
let current_thread = current_pcb().thread;
context.oldmask = *mask;
context.regs = regs.clone();
context.trap_num = unsafe { (*current_thread).trap_num };
context.err_code = unsafe { (*current_thread).err_code };
context.cr2 = unsafe { (*current_thread).cr2 };
return Ok(0);
}
/// @brief 刷新指定进程的sighand的sigaction将满足条件的sigaction恢复为Default
/// 除非某个信号被设置为ignore且force_default为false否则都不会将其恢复
///
/// @param pcb 要被刷新的pcb
/// @param force_default 是否强制将sigaction恢复成默认状态
pub fn flush_signal_handlers(pcb: *mut process_control_block, force_default: bool) {
compiler_fence(core::sync::atomic::Ordering::SeqCst);
let action = unsafe { &mut (*(*pcb).sighand).action };
for ka in action.iter_mut() {
if force_default || (ka.sa_flags != SA_FLAG_IGN) {
ka.sa_flags = SA_FLAG_DFL;
ka._u._sa_handler = None;
}
// 清除flags中除了DFL和IGN以外的所有标志
ka.sa_flags &= SA_FLAG_DFL | SA_FLAG_IGN;
ka.sa_restorer = None;
sigset_clear(&mut ka.sa_mask);
compiler_fence(core::sync::atomic::Ordering::SeqCst);
}
compiler_fence(core::sync::atomic::Ordering::SeqCst);
}

View File

@ -1,9 +1,16 @@
#![allow(non_camel_case_types)]
// 这是signal暴露给其他模块的公有的接口文件
use core::ffi::c_void;
use core::fmt::Debug;
use alloc::vec::Vec;
// todo: 将这里更换为手动编写的ffi绑定
use crate::include::bindings::bindings::atomic_t;
use crate::include::bindings::bindings::pt_regs;
use crate::include::bindings::bindings::spinlock_t;
use crate::kerror;
use crate::libs::ffi_convert::FFIBind2Rust;
use crate::libs::ffi_convert::__convert_mut;
use crate::libs::ffi_convert::__convert_ref;
@ -14,8 +21,12 @@ pub type sigset_t = u64;
pub type __signalfn_t = ::core::option::Option<unsafe extern "C" fn(arg1: ::core::ffi::c_int)>;
pub type __sighandler_t = __signalfn_t;
// 最大的信号数量改动这个值的时候请同步到signal.h)
/// 最大的信号数量改动这个值的时候请同步到signal.h)
pub const MAX_SIG_NUM: i32 = 64;
/// sigset所占用的u64的数量改动这个值的时候请同步到signal.h)
pub const _NSIG_U64_CNT: i32 = MAX_SIG_NUM / 64;
/// 信号处理的栈的栈指针的最小对齐数量
pub const STACK_ALIGN: u64 = 16;
/// 由于signal_struct总是和sighand_struct一起使用并且信号处理的过程中必定会对sighand加锁
/// 因此signal_struct不用加锁
@ -26,9 +37,11 @@ pub struct signal_struct {
pub sig_cnt: atomic_t,
}
impl Default for signal_struct{
impl Default for signal_struct {
fn default() -> Self {
Self { sig_cnt: Default::default() }
Self {
sig_cnt: Default::default(),
}
}
}
@ -49,19 +62,23 @@ pub union sigaction__union_u {
>,
}
impl core::fmt::Debug for sigaction__union_u{
impl core::fmt::Debug for sigaction__union_u {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.write_str("sigaction__union_u")
}
}
impl Default for sigaction__union_u {
fn default() -> Self {
Self{_sa_handler:None}
Self { _sa_handler: None }
}
}
// ============ sigaction结构体中的的sa_flags的可选值 ===========
pub const SA_FLAG_IGN: u64 = 1u64 << 0; // 当前sigaction表示忽略信号的动作
pub const SA_FLAG_DFL: u64 = 1u64 << 1; // 当前sigaction表示系统默认的动作
pub const SA_FLAG_RESTORER: u64 = 1u64 << 2; // 当前sigaction具有用户指定的restorer
/**
* @brief
*/
@ -71,17 +88,21 @@ pub struct sigaction {
pub _u: sigaction__union_u,
pub sa_flags: u64,
pub sa_mask: sigset_t,
pub sa_restorer: ::core::option::Option<unsafe extern "C" fn()>, // 暂时未实现该函数
/// 信号处理函数执行结束后将会跳转到这个函数内进行执行然后执行sigreturn系统调用
pub sa_restorer: ::core::option::Option<unsafe extern "C" fn()>,
}
impl Default for sigaction{
impl Default for sigaction {
fn default() -> Self {
Self { _u: Default::default(), sa_flags: Default::default(), sa_mask: Default::default(), sa_restorer: Default::default() }
Self {
_u: Default::default(),
sa_flags: Default::default(),
sa_mask: Default::default(),
sa_restorer: Default::default(),
}
}
}
/**
* sigaction结构体中指向的处理函数
*/
@ -126,6 +147,38 @@ pub struct __sifields__kill {
pub _pid: i64, /* 发起kill的进程的pid */
}
impl siginfo {
pub fn new(sig: SignalNumber, _si_errno: i32, _si_code: si_code_val) -> Self {
siginfo {
_sinfo: __siginfo_union {
data: __siginfo_union_data {
si_signo: sig as i32,
si_code: _si_code as i32,
si_errno: _si_errno,
reserved: 0,
_sifields: super::signal_types::__sifields {
_kill: super::signal_types::__sifields__kill { _pid: 0 },
},
},
},
}
}
}
impl Debug for siginfo {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
unsafe {
f.write_fmt(format_args!(
"si_signo:{}, si_code:{}, si_errno:{}, _pid:{}",
self._sinfo.data.si_signo,
self._sinfo.data.si_code,
self._sinfo.data.si_errno,
self._sinfo.data._sifields._kill._pid
))
}
}
}
/**
* @brief pcb之中
*/
@ -137,9 +190,13 @@ pub struct sighand_struct {
pub action: [sigaction; MAX_SIG_NUM as usize],
}
impl Default for sighand_struct{
impl Default for sighand_struct {
fn default() -> Self {
Self { siglock: Default::default(), count: Default::default(), action: [Default::default();MAX_SIG_NUM as usize] }
Self {
siglock: Default::default(),
count: Default::default(),
action: [Default::default(); MAX_SIG_NUM as usize],
}
}
}
@ -150,8 +207,12 @@ impl Default for sighand_struct{
#[derive(Debug, Copy, Clone)]
pub struct sigpending {
pub signal: sigset_t,
/// 信号队列
pub queue: *mut SigQueue,
}
/// siginfo中的si_code的可选值
/// 请注意当这个值小于0时表示siginfo来自用户态否则来自内核态
#[allow(dead_code)]
#[repr(i32)]
pub enum si_code_val {
@ -192,6 +253,7 @@ impl si_code_val {
#[derive(Debug, Clone, Copy)]
#[repr(i32)]
pub enum SignalNumber {
INVALID = 0,
SIGHUP = 1,
SIGINT,
SIGQUIT,
@ -237,18 +299,18 @@ impl PartialEq for SignalNumber {
}
}
impl SignalNumber {
/// @brief 从i32转换为SignalNumber枚举类型如果传入的x不符合要求则返回None
#[allow(dead_code)]
pub fn from_i32(x: i32) -> Option<SignalNumber> {
if Self::valid_signal_number(x) {
let ret: SignalNumber = unsafe { core::mem::transmute(x) };
return Some(ret);
impl From<i32> for SignalNumber {
fn from(value: i32) -> Self {
if Self::valid_signal_number(value) {
let ret: SignalNumber = unsafe { core::mem::transmute(value) };
return ret;
} else {
kerror!("Try to convert an invalid number to SignalNumber");
return SignalNumber::INVALID;
}
return None;
}
}
impl SignalNumber {
/// 判断一个数字是否为可用的信号
fn valid_signal_number(x: i32) -> bool {
if x > 0 && x < MAX_SIG_NUM {
@ -268,14 +330,14 @@ pub const SIGRTMAX: i32 = MAX_SIG_NUM;
///
/// 这么做的主要原因在于由于PCB是通过bindgen生成的FFI因此pcb中的结构体类型都是bindgen自动生成的
impl FFIBind2Rust<crate::include::bindings::bindings::signal_struct> for signal_struct {
fn convert_mut<'a>(
fn convert_mut(
src: *mut crate::include::bindings::bindings::signal_struct,
) -> Option<&'a mut Self> {
) -> Option<&'static mut Self> {
return __convert_mut(src);
}
fn convert_ref<'a>(
fn convert_ref(
src: *const crate::include::bindings::bindings::signal_struct,
) -> Option<&'a Self> {
) -> Option<&'static Self> {
return __convert_ref(src);
}
}
@ -284,32 +346,31 @@ impl FFIBind2Rust<crate::include::bindings::bindings::signal_struct> for signal_
///
/// 这么做的主要原因在于由于PCB是通过bindgen生成的FFI因此pcb中的结构体类型都是bindgen自动生成的
impl FFIBind2Rust<crate::include::bindings::bindings::siginfo> for siginfo {
fn convert_mut<'a>(
fn convert_mut(
src: *mut crate::include::bindings::bindings::siginfo,
) -> Option<&'a mut Self> {
) -> Option<&'static mut Self> {
return __convert_mut(src);
}
fn convert_ref<'a>(
fn convert_ref(
src: *const crate::include::bindings::bindings::siginfo,
) -> Option<&'a Self> {
return __convert_ref(src)
) -> Option<&'static Self> {
return __convert_ref(src);
}
}
/// @brief 将给定的sigset_t解析为Rust的signal.rs中定义的sigset_t的引用
///
/// 这么做的主要原因在于由于PCB是通过bindgen生成的FFI因此pcb中的结构体类型都是bindgen自动生成的
impl FFIBind2Rust<crate::include::bindings::bindings::sigset_t> for sigset_t {
fn convert_mut<'a>(
fn convert_mut(
src: *mut crate::include::bindings::bindings::sigset_t,
) -> Option<&'a mut Self> {
) -> Option<&'static mut Self> {
return __convert_mut(src);
}
fn convert_ref<'a>(
fn convert_ref(
src: *const crate::include::bindings::bindings::sigset_t,
) -> Option<&'a Self> {
return __convert_ref(src)
) -> Option<&'static Self> {
return __convert_ref(src);
}
}
@ -317,44 +378,184 @@ impl FFIBind2Rust<crate::include::bindings::bindings::sigset_t> for sigset_t {
///
/// 这么做的主要原因在于由于PCB是通过bindgen生成的FFI因此pcb中的结构体类型都是bindgen自动生成的
impl FFIBind2Rust<crate::include::bindings::bindings::sigpending> for sigpending {
fn convert_mut<'a>(
fn convert_mut(
src: *mut crate::include::bindings::bindings::sigpending,
) -> Option<&'a mut Self> {
) -> Option<&'static mut Self> {
return __convert_mut(src);
}
fn convert_ref<'a>(
fn convert_ref(
src: *const crate::include::bindings::bindings::sigpending,
) -> Option<&'a Self> {
return __convert_ref(src)
) -> Option<&'static Self> {
return __convert_ref(src);
}
}
/// @brief 将给定的来自bindgen的sighand_struct解析为Rust的signal.rs中定义的sighand_struct的引用
///
/// 这么做的主要原因在于由于PCB是通过bindgen生成的FFI因此pcb中的结构体类型都是bindgen自动生成的会导致无法自定义功能的问题。
impl FFIBind2Rust<crate::include::bindings::bindings::sighand_struct> for sighand_struct{
fn convert_mut<'a>(
impl FFIBind2Rust<crate::include::bindings::bindings::sighand_struct> for sighand_struct {
fn convert_mut(
src: *mut crate::include::bindings::bindings::sighand_struct,
) -> Option<&'a mut Self> {
) -> Option<&'static mut Self> {
return __convert_mut(src);
}
fn convert_ref<'a>(
fn convert_ref(
src: *const crate::include::bindings::bindings::sighand_struct,
) -> Option<&'a Self> {
return __convert_ref(src)
) -> Option<&'static Self> {
return __convert_ref(src);
}
}
/// @brief 将给定的来自bindgen的sigaction解析为Rust的signal.rs中定义的sigaction的引用
impl FFIBind2Rust<crate::include::bindings::bindings::sigaction> for sigaction{
fn convert_mut<'a>(
impl FFIBind2Rust<crate::include::bindings::bindings::sigaction> for sigaction {
fn convert_mut(
src: *mut crate::include::bindings::bindings::sigaction,
) -> Option<&'a mut Self> {
) -> Option<&'static mut Self> {
return __convert_mut(src);
}
fn convert_ref<'a>(
fn convert_ref(
src: *const crate::include::bindings::bindings::sigaction,
) -> Option<&'a Self> {
return __convert_ref(src)
) -> Option<&'static Self> {
return __convert_ref(src);
}
}
}
/// @brief 进程接收到的信号的队列
pub struct SigQueue {
pub q: Vec<siginfo>,
}
#[allow(dead_code)]
impl SigQueue {
/// @brief 初始化一个新的信号队列
pub fn new(capacity: usize) -> Self {
SigQueue {
q: Vec::with_capacity(capacity),
}
}
/// @brief 在信号队列中寻找第一个满足要求的siginfo, 并返回它的引用
///
/// @return (第一个满足要求的siginfo的引用; 是否有多个满足条件的siginfo)
pub fn find(&self, sig: SignalNumber) -> (Option<&siginfo>, bool) {
// 是否存在多个满足条件的siginfo
let mut still_pending = false;
let mut info: Option<&siginfo> = None;
for x in self.q.iter() {
if unsafe { x._sinfo.data.si_signo } == sig as i32 {
if info.is_some() {
still_pending = true;
break;
} else {
info = Some(x);
}
}
}
return (info, still_pending);
}
/// @brief 在信号队列中寻找第一个满足要求的siginfo, 并将其从队列中删除然后返回这个siginfo
///
/// @return (第一个满足要求的siginfo; 从队列中删除前是否有多个满足条件的siginfo)
pub fn find_and_delete(&mut self, sig: SignalNumber) -> (Option<siginfo>, bool) {
// 是否存在多个满足条件的siginfo
let mut still_pending = false;
let mut first = true; // 标记变量,记录当前是否已经筛选出了一个元素
let filter = |x: &mut siginfo| {
if unsafe { x._sinfo.data.si_signo } == sig as i32 {
if !first {
// 如果之前已经筛选出了一个元素,则不把当前元素删除
still_pending = true;
return false;
} else {
// 当前是第一个被筛选出来的元素
first = false;
return true;
}
} else {
return false;
}
};
// 从sigqueue中过滤出结果
let mut filter_result: Vec<siginfo> = self.q.drain_filter(filter).collect();
// 筛选出的结果不能大于1个
assert!(filter_result.len() <= 1);
return (filter_result.pop(), still_pending);
}
}
impl Default for SigQueue {
fn default() -> Self {
Self {
q: Default::default(),
}
}
}
/// @brief 清除sigset中某个信号对应的标志位
#[inline]
pub fn sigset_del(set: &mut sigset_t, sig: SignalNumber) {
let sig = sig as i32 - 1;
if _NSIG_U64_CNT == 1 {
*set &= !(1 << sig);
} else {
// 暂时不支持超过64个信号
panic!("Unsupported signal number: {:?}", sig);
}
}
/// @brief 将指定的信号在sigset中的对应bit进行置位
#[inline]
pub fn sigset_add(set: &mut sigset_t, _sig: SignalNumber) {
*set |= 1 << ((_sig as u32) - 1);
}
/// @brief 将sigset清零
#[inline]
pub fn sigset_clear(set: &mut sigset_t) {
*set = 0;
}
#[repr(C)]
#[derive(Debug, Clone, Copy)]
pub struct sigframe {
/// 指向restorer的地址的指针。该变量必须放在sigframe的第一位因为这样才能在handler返回的时候跳转到对应的代码执行sigreturn)
pub ret_code_ptr: *mut core::ffi::c_void,
/// signum
pub arg0: u64,
/// siginfo pointer
pub arg1: usize,
/// sigcontext pointer
pub arg2: usize,
pub handler: *mut c_void,
pub info: siginfo,
pub context: sigcontext,
}
#[derive(Debug, Clone, Copy)]
pub struct sigcontext {
/// sigcontext的标志位
pub sc_flags: u64,
pub sc_stack: signal_stack, // 信号处理程序备用栈信息
pub regs: pt_regs, // 暂存的系统调用/中断返回时,原本要弹出的内核栈帧
pub trap_num: u64, // 用来保存线程结构体中的trap_num字段
pub oldmask: u64, // 暂存的执行信号处理函数之前的sigmask
pub cr2: u64, // 用来保存线程结构体中的cr2字段
pub err_code: u64, // 用来保存线程结构体中的err_code字段
// todo: 支持x87浮点处理器后在这里增加浮点处理器的状态结构体指针
pub reserved_for_x87_state: u64,
pub reserved: [u64; 8],
}
/// @brief 信号处理备用栈的信息
#[derive(Debug, Clone, Copy)]
pub struct signal_stack {
pub sp: *mut c_void,
pub flags: u32,
pub size: u32,
}

View File

@ -3,6 +3,7 @@
#![feature(core_intrinsics)] // <2>
#![feature(alloc_error_handler)]
#![feature(panic_info_message)]
#![feature(drain_filter)]// 允许Vec的drain_filter特性
#[allow(non_upper_case_globals)]
#[allow(non_camel_case_types)]

View File

@ -1,9 +1,9 @@
/// @brief 由bindgen生成的结构体转换成rust原生定义的结构体的特性
pub trait FFIBind2Rust<T> {
/// 转换为不可变引用
fn convert_ref<'a>(src: *const T) -> Option<&'a Self>;
fn convert_ref(src: *const T) -> Option<&'static Self>;
/// 转换为可变引用
fn convert_mut<'a>(src: *mut T) -> Option<&'a mut Self>;
fn convert_mut(src: *mut T) -> Option<&'static mut Self>;
}

View File

@ -15,14 +15,14 @@ impl Default for RefCount{
/// @brief 将给定的来自bindgen的refcount_t解析为Rust的RefCount的引用
impl FFIBind2Rust<crate::include::bindings::bindings::refcount_struct> for RefCount{
fn convert_mut<'a>(
fn convert_mut(
src: *mut crate::include::bindings::bindings::refcount_struct,
) -> Option<&'a mut Self> {
) -> Option<&'static mut Self> {
return __convert_mut(src);
}
fn convert_ref<'a>(
fn convert_ref(
src: *const crate::include::bindings::bindings::refcount_struct,
) -> Option<&'a Self> {
) -> Option<&'static Self> {
return __convert_ref(src)
}
}

View File

@ -2,9 +2,11 @@
use core::ptr::read_volatile;
use crate::arch::x86_64::asm::irqflags::{local_irq_restore, local_irq_save};
use crate::arch::x86_64::interrupt::{cli, sti};
use crate::include::bindings::bindings::{spin_lock, spin_unlock, spinlock_t};
/// @brief 保存中断状态到flags中关闭中断并对自旋锁加锁
#[inline]
pub fn spin_lock_irqsave(lock: *mut spinlock_t, flags: &mut u64) {
local_irq_save(flags);
unsafe {
@ -13,7 +15,7 @@ pub fn spin_lock_irqsave(lock: *mut spinlock_t, flags: &mut u64) {
}
/// @brief 恢复rflags以及中断状态并解锁自旋锁
#[no_mangle]
#[inline]
pub fn spin_unlock_irqrestore(lock: *mut spinlock_t, flags: &u64) {
unsafe {
spin_unlock(lock);
@ -23,6 +25,7 @@ pub fn spin_unlock_irqrestore(lock: *mut spinlock_t, flags: &u64) {
}
/// 判断一个自旋锁是否已经被加锁
#[inline]
pub fn spin_is_locked(lock: &spinlock_t) -> bool {
let val = unsafe { read_volatile(&lock.lock as *const i8) };
@ -33,4 +36,16 @@ impl Default for spinlock_t {
fn default() -> Self {
Self { lock: 1 }
}
}
/// @brief 关闭中断并加锁
pub fn spin_lock_irq(lock: *mut spinlock_t){
cli();
unsafe{spin_lock(lock);}
}
/// @brief 解锁并开中断
pub fn spin_unlock_irq(lock: *mut spinlock_t){
unsafe{spin_unlock(lock);}
sti();
}

View File

@ -1,4 +1,4 @@
use core::ptr::null_mut;
use core::{ffi::c_void, ptr::null_mut, sync::atomic::compiler_fence};
use alloc::boxed::Box;
@ -8,10 +8,9 @@ use crate::{
process_control_block, CLONE_CLEAR_SIGHAND, CLONE_SIGHAND, CLONE_THREAD, ENOMEM,
},
ipc::{
signal::DEFAULT_SIGACTION,
signal_types::{sigaction, sighand_struct, signal_struct},
signal::{flush_signal_handlers, DEFAULT_SIGACTION},
signal_types::{sigaction, sighand_struct, signal_struct, SigQueue},
},
kdebug,
libs::{
atomic::atomic_set,
ffi_convert::FFIBind2Rust,
@ -22,29 +21,38 @@ use crate::{
#[no_mangle]
pub extern "C" fn process_copy_sighand(clone_flags: u64, pcb: *mut process_control_block) -> i32 {
kdebug!("process_copy_sighand");
// kdebug!("process_copy_sighand");
if (clone_flags & (CLONE_SIGHAND as u64)) != 0 {
let r = RefCount::convert_mut(unsafe { &mut (*(current_pcb().sighand)).count }).unwrap();
refcount_inc(r);
}
// 在这里使用Box::leak将动态申请的内存的生命周期转换为static的
let mut sig: &mut sighand_struct = Box::leak(Box::new(sighand_struct::default()));
if (sig as *mut sighand_struct) == null_mut() {
return -(ENOMEM as i32);
}
// 将新的sighand赋值给pcb
unsafe {
(*pcb).sighand = sig as *mut sighand_struct as usize
as *mut crate::include::bindings::bindings::sighand_struct;
}
// kdebug!("DEFAULT_SIGACTION.sa_flags={}", DEFAULT_SIGACTION.sa_flags);
// 拷贝sigaction
let mut flags: u64 = 0;
spin_lock_irqsave(unsafe { &mut (*current_pcb().sighand).siglock }, &mut flags);
compiler_fence(core::sync::atomic::Ordering::SeqCst);
for (index, x) in unsafe { (*current_pcb().sighand).action }
.iter()
.enumerate()
{
compiler_fence(core::sync::atomic::Ordering::SeqCst);
if !(x as *const crate::include::bindings::bindings::sigaction).is_null() {
sig.action[index] =
*sigaction::convert_ref(x as *const crate::include::bindings::bindings::sigaction)
@ -53,20 +61,26 @@ pub extern "C" fn process_copy_sighand(clone_flags: u64, pcb: *mut process_contr
sig.action[index] = DEFAULT_SIGACTION;
}
}
compiler_fence(core::sync::atomic::Ordering::SeqCst);
spin_unlock_irqrestore(unsafe { &mut (*current_pcb().sighand).siglock }, &flags);
compiler_fence(core::sync::atomic::Ordering::SeqCst);
// 将所有屏蔽的信号的处理函数设置为default
// 将信号的处理函数设置为default(除了那些被手动屏蔽的)
if (clone_flags & (CLONE_CLEAR_SIGHAND as u64)) != 0 {
todo!();
compiler_fence(core::sync::atomic::Ordering::SeqCst);
flush_signal_handlers(pcb, false);
compiler_fence(core::sync::atomic::Ordering::SeqCst);
}
compiler_fence(core::sync::atomic::Ordering::SeqCst);
return 0;
}
#[no_mangle]
pub extern "C" fn process_copy_signal(clone_flags: u64, pcb: *mut process_control_block) -> i32 {
kdebug!("process_copy_signal");
// kdebug!("process_copy_signal");
// 如果克隆的是线程,则不拷贝信号(同一进程的各个线程之间共享信号)
if (clone_flags & (CLONE_THREAD as u64)) != 0 {
return 0;
@ -81,6 +95,13 @@ pub extern "C" fn process_copy_signal(clone_flags: u64, pcb: *mut process_contro
(*pcb).signal = sig as *mut signal_struct as usize
as *mut crate::include::bindings::bindings::signal_struct;
}
// 创建新的sig_pending->sigqueue
unsafe {
(*pcb).sig_pending.signal = 0;
(*pcb).sig_pending.sigqueue =
Box::leak(Box::new(SigQueue::default())) as *mut SigQueue as *mut c_void;
}
return 0;
}
@ -88,9 +109,15 @@ pub extern "C" fn process_copy_signal(clone_flags: u64, pcb: *mut process_contro
pub extern "C" fn process_exit_signal(pcb: *mut process_control_block) {
// 回收进程的信号结构体
unsafe {
// 回收sighand
let sighand = Box::from_raw((*pcb).sighand as *mut sighand_struct);
drop(sighand);
(*pcb).sighand = 0 as *mut crate::include::bindings::bindings::sighand_struct;
// 回收sigqueue
let queue = Box::from_raw((*pcb).sig_pending.sigqueue as *mut SigQueue);
drop(queue);
}
}

View File

@ -1,13 +1,17 @@
use core::ffi::c_void;
use alloc::boxed::Box;
use crate::{
include::bindings::bindings::{atomic_t, spinlock_t},
ipc::signal::DEFAULT_SIGACTION,
include::bindings::bindings::{atomic_t, process_control_block, spinlock_t},
ipc::{signal::DEFAULT_SIGACTION, signal_types::SigQueue},
};
use crate::ipc::signal_types::{sighand_struct, signal_struct, MAX_SIG_NUM};
/// @brief 初始进程的signal结构体
#[no_mangle]
pub static INITIAL_SIGNALS: signal_struct = signal_struct {
pub static mut INITIAL_SIGNALS: signal_struct = signal_struct {
sig_cnt: atomic_t { value: 0 },
};
@ -18,3 +22,25 @@ pub static mut INITIAL_SIGHAND: sighand_struct = sighand_struct {
siglock: spinlock_t { lock: 1 },
action: [DEFAULT_SIGACTION; MAX_SIG_NUM as usize],
};
/// @brief 初始化pid=0的进程的信号相关的信息
#[no_mangle]
pub extern "C" fn initial_proc_init_signal(pcb: *mut process_control_block) {
// 所设置的pcb的pid一定为0
assert_eq!(unsafe { (*pcb).pid }, 0);
// 设置init进程的sighand和signal
unsafe {
(*pcb).sighand = &mut INITIAL_SIGHAND as *mut sighand_struct as usize
as *mut crate::include::bindings::bindings::sighand_struct;
(*pcb).signal = &mut INITIAL_SIGNALS as *mut signal_struct as usize
as *mut crate::include::bindings::bindings::signal_struct;
}
// 创建新的sig_pending->sigqueue
unsafe {
(*pcb).sig_pending.signal = 0;
(*pcb).sig_pending.sigqueue =
Box::leak(Box::new(SigQueue::default())) as *mut SigQueue as *mut c_void;
}
}

View File

@ -67,6 +67,7 @@ struct thread_struct
#define PF_NOFREEZE (1UL << 4) // 当前进程不能被冻结
#define PF_EXITING (1UL << 5) // 进程正在退出
#define PF_WAKEKILL (1UL << 6) // 进程由于接收到终止信号唤醒
#define PF_SIGNALED (1UL << 7) // 进程由于接收到信号而退出
/**
* @brief
*

View File

@ -49,6 +49,7 @@ extern struct sighand_struct INITIAL_SIGHAND;
extern void process_exit_sighand(struct process_control_block *pcb);
extern void process_exit_signal(struct process_control_block *pcb);
extern void initial_proc_init_signal(struct process_control_block *pcb);
// 设置初始进程的PCB
#define INITIAL_PROC(proc) \
@ -439,7 +440,7 @@ ul do_execve(struct pt_regs *regs, char *path, char *argv[], char *envp[])
regs->rsi = (uint64_t)dst_argv;
}
// kdebug("execve ok");
// 设置进程的段选择子为用户态可访问
regs->cs = USER_CS | 3;
regs->ds = USER_DS | 3;
regs->ss = USER_DS | 0x3;
@ -464,7 +465,7 @@ exec_failed:;
#pragma GCC optimize("O0")
ul initial_kernel_thread(ul arg)
{
kinfo("initial proc running...\targ:%#018lx", arg);
kinfo("initial proc running...\targ:%#018lx, vruntime=%d", arg, current_pcb->virtual_runtime);
scm_enable_double_buffer();
@ -624,6 +625,8 @@ void process_init()
list_init(&initial_proc_union.pcb.list);
wait_queue_init(&initial_proc_union.pcb.wait_child_proc_exit, NULL);
// 初始化init进程的signal相关的信息
initial_proc_init_signal(current_pcb);
// 临时设置IDLE进程的的虚拟运行时间为0防止下面的这些内核线程的虚拟运行时间出错
current_pcb->virtual_runtime = 0;
barrier();

View File

@ -8,30 +8,41 @@
struct pt_regs
{
unsigned long r15;
unsigned long r14;
unsigned long r13;
unsigned long r12;
unsigned long r11;
unsigned long r10;
unsigned long r9;
unsigned long r8;
unsigned long rbx;
unsigned long rcx;
unsigned long rdx;
unsigned long rsi;
unsigned long rdi;
unsigned long rbp;
unsigned long ds;
unsigned long es;
unsigned long rax;
unsigned long func;
unsigned long errcode;
unsigned long rip;
unsigned long cs;
unsigned long rflags;
unsigned long rsp;
unsigned long ss;
unsigned long r15;
unsigned long r14;
unsigned long r13;
unsigned long r12;
unsigned long r11;
unsigned long r10;
unsigned long r9;
unsigned long r8;
unsigned long rbx;
unsigned long rcx;
unsigned long rdx;
unsigned long rsi;
unsigned long rdi;
unsigned long rbp;
unsigned long ds;
unsigned long es;
unsigned long rax;
unsigned long func;
unsigned long errcode;
unsigned long rip;
unsigned long cs;
unsigned long rflags;
unsigned long rsp;
unsigned long ss;
};
/**
* @brief pt_regs是否来自用户态
*
* @param regs
* @return __always_inline
*/
static inline int user_mode(struct pt_regs *regs)
{
return !!(regs->cs & 3);
}
#endif

View File

@ -372,7 +372,7 @@ uint64_t sys_chdir(struct pt_regs *regs)
// 计算输入的路径长度
int dest_path_len;
if (regs->cs & USER_CS)
if (user_mode(regs))
{
dest_path_len = strnlen_user(dest_path, PAGE_4K_SIZE);
}

View File

@ -17,7 +17,7 @@ extern void ret_from_system_call(void); // 导出从系统调用返回的函数
extern system_call_t system_call_table[MAX_SYSTEM_CALL_NUM];
// 判断系统调用是否来自用户态
#define SYSCALL_FROM_USER(regs) ((regs)->cs & USER_CS)
#define SYSCALL_FROM_USER(regs) (user_mode(regs))
// 判断系统调用是否来自内核态
#define SYSCALL_FROM_KERNEL(regs) (!SYSCALL_FROM_USER(regs))

View File

@ -1,5 +1,5 @@
user_apps_sub_dirs=shell about
user_apps_sub_dirs=shell about test_signal
ECHO:
@echo "$@"

View File

@ -467,7 +467,7 @@ int shell_cmd_exec(int argc, char **argv)
if (pid == 0)
{
// printf("child proc\n");
// 子进程
int path_len = 0;
char *file_path = get_target_filepath(argv[1], &path_len);
@ -480,10 +480,13 @@ int shell_cmd_exec(int argc, char **argv)
}
else
{
// printf("parent process wait for pid:[ %d ]\n", pid);
waitpid(pid, &retval, 0);
// printf("parent process wait pid [ %d ], exit code=%d\n", pid, retval);
// 如果不指定后台运行,则等待退出
if (strcmp(argv[argc - 1], "&") != 0)
waitpid(pid, &retval, 0);
else{
// 输出子进程的pid
printf("[1] %d\n", pid);
}
free(argv);
}
}
@ -513,8 +516,6 @@ int shell_cmd_kill(int argc, char **argv)
retval = -EINVAL;
goto out;
}
printf("argc = %d, argv[1]=%s\n", argc, argv[1]);
printf("atoi(argv[1])=%d\n", atoi(argv[1]));
retval = syscall_invoke(SYS_KILL, atoi(argv[1]), SIGKILL, 0, 0, 0, 0, 0, 0);
out:;
free(argv);

View File

@ -0,0 +1,7 @@
all: main.o
ld -b elf64-x86-64 -z muldefs -o $(tmp_output_dir)/test_signal $(shell find . -name "*.o") $(shell find $(sys_libs_dir) -name "*.o") -T link.lds
objcopy -I elf64-x86-64 -R ".eh_frame" -R ".comment" -O elf64-x86-64 $(tmp_output_dir)/test_signal $(output_dir)/test_signal.elf
main.o: main.c
$(CC) $(CFLAGS) -c main.c -o main.o

View File

@ -0,0 +1,50 @@
OUTPUT_FORMAT("elf64-x86-64","elf64-x86-64","elf64-x86-64")
OUTPUT_ARCH(i386:x86-64)
ENTRY(_start)
SECTIONS
{
. = 0x800000;
.text :
{
_text = .;
*(.text)
_etext = .;
}
. = ALIGN(8);
.data :
{
_data = .;
*(.data)
_edata = .;
}
rodata_start_pa = .;
.rodata :
{
_rodata = .;
*(.rodata)
_erodata = .;
}
.bss :
{
_bss = .;
*(.bss)
_ebss = .;
}
_end = .;
}

View File

@ -0,0 +1,38 @@
/**
* @file main.c
* @author longjin (longjin@RinGoTek.cn)
* @brief signal用的程序
* @version 0.1
* @date 2022-12-06
*
* @copyright Copyright (c) 2022
*
*/
/**
* signal的kill命令的方法:
* 1.DragonOS的控制台输入 exec bin/test_signal.elf &
* , '&',
* 2.kill对应的进程的pid (,:"[1] 生成的pid")
*
*/
#include <libc/math.h>
#include <libc/stdio.h>
#include <libc/stdlib.h>
#include <libc/time.h>
#include <libc/unistd.h>
int main()
{
printf("Test signal running...\n");
clock_t last = clock();
while (1)
{
if ((clock()-last)/CLOCKS_PER_SEC >= 1){
// printf("Test signal running\n");
last = clock();
}
}
return 0;
}