mirror of
https://github.com/DragonOS-Community/DragonOS.git
synced 2025-06-08 14:16:47 +00:00
feat(wait): 调整内核wait4函数参数类型 (#1175)
* feat:补充wait4的逻辑,添加对进程组的判断 * fix: 修复进程退出码的返回,将正常退出的进程的退出码移动至高8位 * fix: 移除session和processgroup的debug trait Signed-off-by: sparkzky <sparkhhhhhhhhhh@outlook.com> * fix: 删除shell.service文件中对于backspace的单独设置 Signed-off-by: sparkzky <sparkhhhhhhhhhh@outlook.com> * fix: 更新exit函数文档,明确状态码移位规则 Signed-off-by: sparkzky <sparkhhhhhhhhhh@outlook.com> --------- Signed-off-by: sparkzky <sparkhhhhhhhhhh@outlook.com>
This commit is contained in:
parent
ae987c6f9a
commit
aa394c1f6f
@ -1,26 +1,23 @@
|
|||||||
use core::intrinsics::likely;
|
|
||||||
|
|
||||||
use alloc::sync::Arc;
|
use alloc::sync::Arc;
|
||||||
use log::warn;
|
use core::intrinsics::likely;
|
||||||
use system_error::SystemError;
|
use system_error::SystemError;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
arch::ipc::signal::{SigChildCode, Signal},
|
arch::ipc::signal::{SigChildCode, Signal},
|
||||||
|
ipc::syscall::PidConverter,
|
||||||
sched::{schedule, SchedMode},
|
sched::{schedule, SchedMode},
|
||||||
syscall::user_access::UserBufferWriter,
|
syscall::user_access::UserBufferWriter,
|
||||||
time::{sleep::nanosleep, Duration},
|
time::{sleep::nanosleep, Duration},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
abi::WaitOption, pid::PidType, resource::RUsage, Pid, ProcessControlBlock, ProcessManager,
|
abi::WaitOption, resource::RUsage, Pid, ProcessControlBlock, ProcessManager, ProcessState,
|
||||||
ProcessState,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/// 内核wait4时的参数
|
/// 内核wait4时的参数
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct KernelWaitOption<'a> {
|
pub struct KernelWaitOption<'a> {
|
||||||
pub pid_type: PidType,
|
pub pid_converter: PidConverter,
|
||||||
pub pid: Pid,
|
|
||||||
pub options: WaitOption,
|
pub options: WaitOption,
|
||||||
pub ret_status: i32,
|
pub ret_status: i32,
|
||||||
pub ret_info: Option<WaitIdInfo>,
|
pub ret_info: Option<WaitIdInfo>,
|
||||||
@ -37,10 +34,9 @@ pub struct WaitIdInfo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl KernelWaitOption<'_> {
|
impl KernelWaitOption<'_> {
|
||||||
pub fn new(pid_type: PidType, pid: Pid, options: WaitOption) -> Self {
|
pub fn new(pid_converter: PidConverter, options: WaitOption) -> Self {
|
||||||
Self {
|
Self {
|
||||||
pid_type,
|
pid_converter,
|
||||||
pid,
|
|
||||||
options,
|
options,
|
||||||
ret_status: 0,
|
ret_status: 0,
|
||||||
ret_info: None,
|
ret_info: None,
|
||||||
@ -51,36 +47,15 @@ impl KernelWaitOption<'_> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn kernel_wait4(
|
pub fn kernel_wait4(
|
||||||
mut pid: i64,
|
pid: i32,
|
||||||
wstatus_buf: Option<UserBufferWriter<'_>>,
|
wstatus_buf: Option<UserBufferWriter<'_>>,
|
||||||
options: WaitOption,
|
options: WaitOption,
|
||||||
rusage_buf: Option<&mut RUsage>,
|
rusage_buf: Option<&mut RUsage>,
|
||||||
) -> Result<usize, SystemError> {
|
) -> Result<usize, SystemError> {
|
||||||
// i64::MIN is not defined
|
let converter = PidConverter::from_id(pid);
|
||||||
if pid == i64::MIN {
|
|
||||||
return Err(SystemError::ESRCH);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 判断pid类型
|
|
||||||
let pidtype: PidType;
|
|
||||||
if pid == -1 {
|
|
||||||
pidtype = PidType::MAX;
|
|
||||||
} else if pid < 0 {
|
|
||||||
pidtype = PidType::PGID;
|
|
||||||
warn!("kernel_wait4: currently not support pgid, default to wait for pid\n");
|
|
||||||
pid = -pid;
|
|
||||||
} else if pid == 0 {
|
|
||||||
pidtype = PidType::PGID;
|
|
||||||
warn!("kernel_wait4: currently not support pgid, default to wait for pid\n");
|
|
||||||
pid = ProcessManager::current_pcb().pid().data() as i64;
|
|
||||||
} else {
|
|
||||||
pidtype = PidType::PID;
|
|
||||||
}
|
|
||||||
|
|
||||||
let pid = Pid(pid as usize);
|
|
||||||
|
|
||||||
// 构造参数
|
// 构造参数
|
||||||
let mut kwo = KernelWaitOption::new(pidtype, pid, options);
|
let mut kwo = KernelWaitOption::new(converter, options);
|
||||||
|
|
||||||
kwo.options.insert(WaitOption::WEXITED);
|
kwo.options.insert(WaitOption::WEXITED);
|
||||||
kwo.ret_rusage = rusage_buf;
|
kwo.ret_rusage = rusage_buf;
|
||||||
@ -131,59 +106,78 @@ fn do_wait(kwo: &mut KernelWaitOption) -> Result<usize, SystemError> {
|
|||||||
|
|
||||||
'outer: loop {
|
'outer: loop {
|
||||||
kwo.no_task_error = Some(SystemError::ECHILD);
|
kwo.no_task_error = Some(SystemError::ECHILD);
|
||||||
let child_pcb = ProcessManager::find(kwo.pid).ok_or(SystemError::ECHILD);
|
match kwo.pid_converter {
|
||||||
|
PidConverter::Pid(pid) => {
|
||||||
if kwo.pid_type != PidType::MAX && child_pcb.is_err() {
|
let child_pcb = ProcessManager::find(pid)
|
||||||
notask!('outer);
|
.ok_or(SystemError::ECHILD)
|
||||||
}
|
.unwrap();
|
||||||
|
// 获取weak引用,以便于在do_waitpid中能正常drop pcb
|
||||||
if kwo.pid_type == PidType::PID {
|
let child_weak = Arc::downgrade(&child_pcb);
|
||||||
let child_pcb = child_pcb.unwrap();
|
let r: Option<Result<usize, SystemError>> = do_waitpid(child_pcb, kwo);
|
||||||
// 获取weak引用,以便于在do_waitpid中能正常drop pcb
|
if let Some(r) = r {
|
||||||
let child_weak = Arc::downgrade(&child_pcb);
|
retval = r;
|
||||||
let r = do_waitpid(child_pcb, kwo);
|
break 'outer;
|
||||||
if let Some(r) = r {
|
} else if let Err(SystemError::ESRCH) =
|
||||||
retval = r;
|
child_weak.upgrade().unwrap().wait_queue.sleep()
|
||||||
break 'outer;
|
{
|
||||||
} else if let Err(SystemError::ESRCH) = child_weak.upgrade().unwrap().wait_queue.sleep()
|
// log::debug!("do_wait: child_pcb sleep failed");
|
||||||
{
|
continue;
|
||||||
// log::debug!("do_wait: child_pcb sleep failed");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
} else if kwo.pid_type == PidType::MAX {
|
|
||||||
// 等待任意子进程
|
|
||||||
// todo: 这里有问题!应当让当前进程sleep到自身的child_wait等待队列上,这样才高效。(还没实现)
|
|
||||||
let current_pcb = ProcessManager::current_pcb();
|
|
||||||
loop {
|
|
||||||
let rd_childen = current_pcb.children.read();
|
|
||||||
if rd_childen.is_empty() {
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
for pid in rd_childen.iter() {
|
}
|
||||||
let pcb = ProcessManager::find(*pid).ok_or(SystemError::ECHILD)?;
|
PidConverter::All => {
|
||||||
let sched_guard = pcb.sched_info().inner_lock_read_irqsave();
|
// 等待任意子进程
|
||||||
let state = sched_guard.state();
|
// todo: 这里有问题!应当让当前进程sleep到自身的child_wait等待队列上,这样才高效。(还没实现)
|
||||||
if state.is_exited() {
|
let current_pcb = ProcessManager::current_pcb();
|
||||||
kwo.ret_status = state.exit_code().unwrap() as i32;
|
loop {
|
||||||
kwo.no_task_error = None;
|
let rd_childen = current_pcb.children.read();
|
||||||
// 由于pcb的drop方法里面要获取父进程的children字段的写锁,所以这里不能直接drop pcb,
|
if rd_childen.is_empty() {
|
||||||
// 而是要先break到外层循环,以便释放父进程的children字段的锁,才能drop pcb。
|
break;
|
||||||
// 否则会死锁。
|
|
||||||
tmp_child_pcb = Some(pcb.clone());
|
|
||||||
unsafe { ProcessManager::release(*pid) };
|
|
||||||
retval = Ok((*pid).into());
|
|
||||||
break 'outer;
|
|
||||||
}
|
}
|
||||||
|
for pid in rd_childen.iter() {
|
||||||
|
let pcb = ProcessManager::find(*pid).ok_or(SystemError::ECHILD)?;
|
||||||
|
let sched_guard = pcb.sched_info().inner_lock_read_irqsave();
|
||||||
|
let state = sched_guard.state();
|
||||||
|
if state.is_exited() {
|
||||||
|
kwo.ret_status = state.exit_code().unwrap() as i32;
|
||||||
|
kwo.no_task_error = None;
|
||||||
|
// 由于pcb的drop方法里面要获取父进程的children字段的写锁,所以这里不能直接drop pcb,
|
||||||
|
// 而是要先break到外层循环,以便释放父进程的children字段的锁,才能drop pcb。
|
||||||
|
// 否则会死锁。
|
||||||
|
tmp_child_pcb = Some(pcb.clone());
|
||||||
|
unsafe { ProcessManager::release(*pid) };
|
||||||
|
retval = Ok((*pid).into());
|
||||||
|
break 'outer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
drop(rd_childen);
|
||||||
|
nanosleep(Duration::from_millis(100).into())?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
PidConverter::Pgid(pgid) => {
|
||||||
|
let pg = ProcessManager::find_process_group(pgid).ok_or(SystemError::ESRCH)?;
|
||||||
|
loop {
|
||||||
|
let inner = pg.process_group_inner.lock();
|
||||||
|
for (_, pcb) in inner.processes.iter() {
|
||||||
|
let sched_guard = pcb.sched_info().inner_lock_read_irqsave();
|
||||||
|
let state = sched_guard.state();
|
||||||
|
if state.is_exited() {
|
||||||
|
kwo.ret_status = state.exit_code().unwrap() as i32;
|
||||||
|
kwo.no_task_error = None;
|
||||||
|
// 由于pcb的drop方法里面要获取父进程的children字段的写锁,所以这里不能直接drop pcb,
|
||||||
|
// 而是要先break到外层循环,以便释放父进程的children字段的锁,才能drop pcb。
|
||||||
|
// 否则会死锁。
|
||||||
|
tmp_child_pcb = Some(pcb.clone());
|
||||||
|
let pid = pcb.pid();
|
||||||
|
unsafe { ProcessManager::release(pid) };
|
||||||
|
retval = Ok((pid).into());
|
||||||
|
break 'outer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
drop(inner);
|
||||||
|
nanosleep(Duration::from_millis(100).into())?;
|
||||||
}
|
}
|
||||||
drop(rd_childen);
|
|
||||||
nanosleep(Duration::from_millis(100).into())?;
|
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
// todo: 对于pgid的处理
|
|
||||||
warn!("kernel_wait4: currently not support {:?}", kwo.pid_type);
|
|
||||||
return Err(SystemError::EINVAL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
notask!('outer);
|
notask!('outer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -404,6 +404,11 @@ impl ProcessManager {
|
|||||||
/// ## 参数
|
/// ## 参数
|
||||||
///
|
///
|
||||||
/// - `exit_code` : 进程的退出码
|
/// - `exit_code` : 进程的退出码
|
||||||
|
///
|
||||||
|
/// ## 注意
|
||||||
|
/// 对于正常退出的进程,状态码应该先左移八位,以便用户态读取的时候正常返回退出码;而对于被信号终止的进程,状态码则是最低七位,无需进行移位操作。
|
||||||
|
///
|
||||||
|
/// 因此注意,传入的`exit_code`应该是已经完成了移位操作的
|
||||||
pub fn exit(exit_code: usize) -> ! {
|
pub fn exit(exit_code: usize) -> ! {
|
||||||
// 关中断
|
// 关中断
|
||||||
let _irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() };
|
let _irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() };
|
||||||
|
@ -17,14 +17,12 @@ pub type Pgid = Pid;
|
|||||||
pub static ALL_PROCESS_GROUP: SpinLock<Option<HashMap<Pgid, Arc<ProcessGroup>>>> =
|
pub static ALL_PROCESS_GROUP: SpinLock<Option<HashMap<Pgid, Arc<ProcessGroup>>>> =
|
||||||
SpinLock::new(None);
|
SpinLock::new(None);
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct ProcessGroup {
|
pub struct ProcessGroup {
|
||||||
/// 进程组pgid
|
/// 进程组pgid
|
||||||
pub pgid: Pgid,
|
pub pgid: Pgid,
|
||||||
pub process_group_inner: SpinLock<PGInner>,
|
pub process_group_inner: SpinLock<PGInner>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct PGInner {
|
pub struct PGInner {
|
||||||
pub processes: BTreeMap<Pid, Arc<ProcessControlBlock>>,
|
pub processes: BTreeMap<Pid, Arc<ProcessControlBlock>>,
|
||||||
pub leader: Option<Arc<ProcessControlBlock>>,
|
pub leader: Option<Arc<ProcessControlBlock>>,
|
||||||
|
@ -16,13 +16,11 @@ pub type Sid = Pid;
|
|||||||
/// 系统中所有会话
|
/// 系统中所有会话
|
||||||
pub static ALL_SESSION: SpinLock<Option<HashMap<Sid, Arc<Session>>>> = SpinLock::new(None);
|
pub static ALL_SESSION: SpinLock<Option<HashMap<Sid, Arc<Session>>>> = SpinLock::new(None);
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct Session {
|
pub struct Session {
|
||||||
pub sid: Sid,
|
pub sid: Sid,
|
||||||
pub session_inner: SpinLock<SessionInner>,
|
pub session_inner: SpinLock<SessionInner>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct SessionInner {
|
pub struct SessionInner {
|
||||||
pub process_groups: BTreeMap<Pgid, Arc<ProcessGroup>>,
|
pub process_groups: BTreeMap<Pgid, Arc<ProcessGroup>>,
|
||||||
pub leader: Option<Arc<ProcessControlBlock>>,
|
pub leader: Option<Arc<ProcessControlBlock>>,
|
||||||
|
@ -206,7 +206,7 @@ impl Syscall {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn wait4(
|
pub fn wait4(
|
||||||
pid: i64,
|
pid: i32,
|
||||||
wstatus: *mut i32,
|
wstatus: *mut i32,
|
||||||
options: i32,
|
options: i32,
|
||||||
rusage: *mut c_void,
|
rusage: *mut c_void,
|
||||||
@ -248,7 +248,7 @@ impl Syscall {
|
|||||||
///
|
///
|
||||||
/// - status: 退出状态
|
/// - status: 退出状态
|
||||||
pub fn exit(status: usize) -> ! {
|
pub fn exit(status: usize) -> ! {
|
||||||
ProcessManager::exit(status);
|
ProcessManager::exit((status & 0xff) << 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief 获取当前进程的pid
|
/// @brief 获取当前进程的pid
|
||||||
|
@ -295,7 +295,7 @@ impl Syscall {
|
|||||||
let rusage = args[3] as *mut c_void;
|
let rusage = args[3] as *mut c_void;
|
||||||
// 权限校验
|
// 权限校验
|
||||||
// todo: 引入rusage之后,更正以下权限校验代码中,rusage的大小
|
// todo: 引入rusage之后,更正以下权限校验代码中,rusage的大小
|
||||||
Self::wait4(pid.into(), wstatus, options, rusage)
|
Self::wait4(pid, wstatus, options, rusage)
|
||||||
}
|
}
|
||||||
|
|
||||||
SYS_EXIT => {
|
SYS_EXIT => {
|
||||||
|
@ -6,6 +6,5 @@ Type=simple
|
|||||||
ExecStart=/bin/NovaShell
|
ExecStart=/bin/NovaShell
|
||||||
Restart=always
|
Restart=always
|
||||||
ExecStartPre=-/bin/about.elf
|
ExecStartPre=-/bin/about.elf
|
||||||
ExecStartPre=/bin/busybox stty erase 127
|
|
||||||
Environment=PATH=/bin:/usr/bin:/usr/local/bin
|
Environment=PATH=/bin:/usr/bin:/usr/local/bin
|
||||||
Environment=LD_LIBRARY_PATH=/usr/lib:/usr/lib64:/usr/local/lib
|
Environment=LD_LIBRARY_PATH=/usr/lib:/usr/lib64:/usr/local/lib
|
||||||
|
Loading…
x
Reference in New Issue
Block a user