Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions kernel/src/filesystem/vfs/syscall.rs
Original file line number Diff line number Diff line change
Expand Up @@ -294,7 +294,7 @@ impl Syscall {
if path.len() > 0 {
let cwd = match path.as_bytes()[0] {
b'/' => String::from("/"),
_ => proc.basic().path(),
_ => proc.basic().cwd(),
};
let mut cwd_vec: Vec<_> = cwd.split("/").filter(|&x| x != "").collect();
let path_split = path.split("/").filter(|&x| x != "");
Expand Down Expand Up @@ -325,7 +325,7 @@ impl Syscall {
};
let metadata = inode.metadata()?;
if metadata.file_type == FileType::Dir {
proc.basic_mut().set_path(String::from(new_path));
proc.basic_mut().set_cwd(String::from(new_path));
return Ok(0);
} else {
return Err(SystemError::ENOTDIR);
Expand All @@ -341,7 +341,7 @@ impl Syscall {
/// @return 错误,没有足够的空间
pub fn getcwd(buf: &mut [u8]) -> Result<VirtAddr, SystemError> {
let proc = ProcessManager::current_pcb();
let cwd = proc.basic().path();
let cwd = proc.basic().cwd();

let cwd_bytes = cwd.as_bytes();
let cwd_len = cwd_bytes.len();
Expand Down
74 changes: 66 additions & 8 deletions kernel/src/process/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use core::{
use alloc::{
boxed::Box,
string::{String, ToString},
sync::Arc,
sync::{Arc, Weak},
};
use hashbrown::HashMap;

Expand Down Expand Up @@ -354,6 +354,12 @@ pub struct ProcessControlBlock {
sched_info: RwLock<ProcessSchedulerInfo>,
/// 与处理器架构相关的信息
arch_info: SpinLock<ArchPCBInfo>,

/// 父进程指针
parent_pcb: RwLock<Weak<ProcessControlBlock>>,

/// 子进程链表
children: RwLock<HashMap<Pid, Arc<ProcessControlBlock>>>,
}

impl ProcessControlBlock {
Expand All @@ -380,19 +386,27 @@ impl ProcessControlBlock {
}

fn do_create_pcb(name: String, kstack: KernelStack, is_idle: bool) -> Arc<Self> {
let pid = if is_idle {
Pid(0)
let (pid, ppid, cwd) = if is_idle {
(Pid(0), Pid(0), "/".to_string())
} else {
Self::generate_pid()
(
Self::generate_pid(),
ProcessManager::current_pcb().basic().pid(),
ProcessManager::current_pcb().basic().cwd(),
)
};

let basic_info = ProcessBasicInfo::new(pid, Pid(0), Pid(0), name, "/".to_string(), None);
let basic_info = ProcessBasicInfo::new(pid, Pid(0), ppid, name, cwd, None);
let preempt_count = AtomicUsize::new(0);
let flags = SpinLock::new(ProcessFlags::empty());

let sched_info = ProcessSchedulerInfo::new(None);
let arch_info = SpinLock::new(ArchPCBInfo::new(Some(&kstack)));

let ppcb: Weak<ProcessControlBlock> = ProcessManager::find(ppid)
.map(|p| Arc::downgrade(&p))
.unwrap_or_else(|| Weak::new());

let pcb = Self {
basic: basic_info,
preempt_count,
Expand All @@ -401,12 +415,25 @@ impl ProcessControlBlock {
worker_private: SpinLock::new(None),
sched_info,
arch_info,
parent_pcb: RwLock::new(ppcb),
children: RwLock::new(HashMap::new()),
};

let pcb = Arc::new(pcb);

// 设置进程的arc指针到内核栈的最低地址处
unsafe { pcb.kernel_stack.write().set_pcb(Arc::clone(&pcb)).unwrap() };

// 将当前pcb加入父进程的子进程哈希表中
if pcb.basic().pid() != Pid(0) {
if let Some(ppcb_arc) = pcb.parent_pcb.read().upgrade() {
let mut children = ppcb_arc.children.write();
children.insert(pcb.basic().pid(), pcb.clone());
} else {
panic!("parent pcb is None");
}
}

return pcb;
}

Expand Down Expand Up @@ -505,14 +532,45 @@ impl ProcessControlBlock {
.expect("Not a socket inode");
return Some(socket);
}

/// 退出进程时,让初始进程收养所有子进程
///
/// ## 参数
///
/// -`pcb` : 要退出的进程
fn adopt_childen(&self) -> Result<(), SystemError> {
match ProcessManager::find(Pid(1)) {
Some(init_pcb) => {
let mut childen_guard = self.children.write();
let mut init_childen_guard = init_pcb.children.write();

childen_guard.drain().for_each(|(pid, child)| {
init_childen_guard.insert(pid, child);
});

return Ok(());
}
// FIXME 没有找到1号进程返回什么错误码
_ => Err(SystemError::ECHILD),
}
}
}

impl Drop for ProcessControlBlock {
fn drop(&mut self) {
// 在ProcFS中,解除进程的注册
procfs_unregister_pid(self.basic().pid())
.unwrap_or_else(|e| panic!("procfs_unregister_pid failed: error: {e:?}"));
// 释放资源
// 让INIT进程收养所有子进程
if self.basic().pid() != Pid(1) {
self.adopt_childen()
.unwrap_or_else(|e| panic!("adopte_childen failed: error: {e:?}"));
}
if let Some(ppcb) = self.parent_pcb.read().upgrade() {
ppcb.children.write().remove(&self.basic().pid());
}

unsafe { ProcessManager::release(self.basic().pid()) };
}
}
/// 进程的基本信息
Expand Down Expand Up @@ -580,10 +638,10 @@ impl ProcessBasicInfo {
self.name = name;
}

pub fn path(&self) -> String {
pub fn cwd(&self) -> String {
return self.cwd.clone();
}
pub fn set_path(&mut self, path: String) {
pub fn set_cwd(&mut self, path: String) {
return self.cwd = path;
}

Expand Down
1 change: 1 addition & 0 deletions kernel/src/process/syscall.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ impl Syscall {
options: c_int,
rusage: *mut c_void,
) -> Result<usize, SystemError> {
// TODO 将c_sys_wait4使用rust实现
let ret = unsafe { c_sys_wait4(pid, wstatus, options, rusage) };
if (ret as isize) < 0 {
return Err(
Expand Down