mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-20 13:06:33 +00:00
Move functions related to spawning the init process to a seperate module
This commit is contained in:
@ -15,7 +15,7 @@ use crate::{
|
||||
prelude::*,
|
||||
process::{
|
||||
signal::{signals::kernel::KernelSignal, PollHandle, Pollable},
|
||||
JobControl, Process, Terminal,
|
||||
JobControl, Terminal,
|
||||
},
|
||||
};
|
||||
|
||||
@ -211,21 +211,3 @@ pub fn new_job_control_and_ldisc() -> (Arc<JobControl>, Arc<LineDiscipline>) {
|
||||
pub fn get_n_tty() -> &'static Arc<Tty> {
|
||||
N_TTY.get().unwrap()
|
||||
}
|
||||
|
||||
/// Open `N_TTY` as the controlling terminal for the process. This method should
|
||||
/// only be called when creating the init process.
|
||||
pub fn open_ntty_as_controlling_terminal(process: &Process) -> Result<()> {
|
||||
let tty = get_n_tty();
|
||||
|
||||
let session = &process.session().unwrap();
|
||||
let process_group = process.process_group().unwrap();
|
||||
|
||||
session.set_terminal(|| {
|
||||
tty.job_control.set_session(session);
|
||||
Ok(tty.clone())
|
||||
})?;
|
||||
|
||||
tty.job_control.set_foreground(Some(&process_group))?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@ -35,7 +35,7 @@ use ostd::{
|
||||
boot::boot_info,
|
||||
cpu::{CpuId, CpuSet, PinCurrentCpu},
|
||||
};
|
||||
use process::Process;
|
||||
use process::{spawn_init_process, Process};
|
||||
use sched::SchedPolicy;
|
||||
|
||||
use crate::{prelude::*, thread::kernel_thread::ThreadOptions};
|
||||
@ -151,7 +151,7 @@ fn init_thread() {
|
||||
|
||||
let karg: KCmdlineArg = boot_info().kernel_cmdline.as_str().into();
|
||||
|
||||
let initproc = Process::spawn_user_process(
|
||||
let initproc = spawn_init_process(
|
||||
karg.get_initproc_path().unwrap(),
|
||||
karg.get_initproc_argv().to_vec(),
|
||||
karg.get_initproc_envp().to_vec(),
|
||||
|
@ -8,8 +8,9 @@ use super::{
|
||||
posix_thread::{AsPosixThread, PosixThreadBuilder, ThreadName},
|
||||
process_table,
|
||||
process_vm::ProcessVm,
|
||||
rlimit::ResourceLimits,
|
||||
signal::{constants::SIGCHLD, sig_disposition::SigDispositions, sig_num::SigNum},
|
||||
Credentials, Process, ProcessBuilder,
|
||||
Credentials, Pid, Process,
|
||||
};
|
||||
use crate::{
|
||||
cpu::LinuxAbi,
|
||||
@ -17,6 +18,7 @@ use crate::{
|
||||
fs::{file_table::FileTable, thread_info::ThreadFsInfo},
|
||||
prelude::*,
|
||||
process::posix_thread::allocate_posix_tid,
|
||||
sched::Nice,
|
||||
thread::{AsThread, Tid},
|
||||
};
|
||||
|
||||
@ -299,13 +301,13 @@ fn clone_child_process(
|
||||
|
||||
let clone_flags = clone_args.flags;
|
||||
|
||||
// clone vm
|
||||
// Clone the virtual memory space
|
||||
let child_process_vm = {
|
||||
let parent_process_vm = process.vm();
|
||||
clone_vm(parent_process_vm, clone_flags)?
|
||||
};
|
||||
|
||||
// clone user space
|
||||
// Clone the user context
|
||||
let child_user_ctx = Arc::new(clone_user_ctx(
|
||||
parent_context,
|
||||
clone_args.stack,
|
||||
@ -314,22 +316,25 @@ fn clone_child_process(
|
||||
clone_flags,
|
||||
));
|
||||
|
||||
// clone file table
|
||||
// Clone the file table
|
||||
let child_file_table = clone_files(thread_local.borrow_file_table().unwrap(), clone_flags);
|
||||
|
||||
// clone fs
|
||||
// Clone the filesystem information
|
||||
let child_fs = clone_fs(posix_thread.fs(), clone_flags);
|
||||
|
||||
// clone sig dispositions
|
||||
// Clone signal dispositions
|
||||
let child_sig_dispositions = clone_sighand(process.sig_dispositions(), clone_flags);
|
||||
|
||||
// clone system V semaphore
|
||||
// Clone System V semaphore
|
||||
clone_sysvsem(clone_flags)?;
|
||||
|
||||
// inherit parent's sig mask
|
||||
// Inherit the parent's signal mask
|
||||
let child_sig_mask = posix_thread.sig_mask().load(Ordering::Relaxed).into();
|
||||
|
||||
// inherit parent's nice value
|
||||
// Inherit the parent's resource limits
|
||||
let child_resource_limits = process.resource_limits().clone();
|
||||
|
||||
// Inherit the parent's nice value
|
||||
let child_nice = process.nice().load(Ordering::Relaxed);
|
||||
|
||||
let child_tid = allocate_posix_tid();
|
||||
@ -358,16 +363,16 @@ fn clone_child_process(
|
||||
child_thread_builder =
|
||||
clone_child_settid(child_thread_builder, clone_args.child_tid, clone_flags);
|
||||
|
||||
let mut process_builder =
|
||||
ProcessBuilder::new(child_tid, &child_elf_path, posix_thread.weak_process());
|
||||
|
||||
process_builder
|
||||
.main_thread_builder(child_thread_builder)
|
||||
.process_vm(child_process_vm)
|
||||
.sig_dispositions(child_sig_dispositions)
|
||||
.nice(child_nice);
|
||||
|
||||
process_builder.build()?
|
||||
create_child_process(
|
||||
child_tid,
|
||||
posix_thread.weak_process(),
|
||||
&child_elf_path,
|
||||
child_process_vm,
|
||||
child_resource_limits,
|
||||
child_nice,
|
||||
child_sig_dispositions,
|
||||
child_thread_builder,
|
||||
)
|
||||
};
|
||||
|
||||
if let Some(sig) = clone_args.exit_signal {
|
||||
@ -510,6 +515,32 @@ fn clone_sysvsem(clone_flags: CloneFlags) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn create_child_process(
|
||||
pid: Pid,
|
||||
parent: Weak<Process>,
|
||||
executable_path: &str,
|
||||
process_vm: ProcessVm,
|
||||
resource_limits: ResourceLimits,
|
||||
nice: Nice,
|
||||
sig_dispositions: Arc<Mutex<SigDispositions>>,
|
||||
thread_builder: PosixThreadBuilder,
|
||||
) -> Arc<Process> {
|
||||
let child_proc = Process::new(
|
||||
pid,
|
||||
parent,
|
||||
executable_path.to_string(),
|
||||
process_vm,
|
||||
resource_limits,
|
||||
nice,
|
||||
sig_dispositions,
|
||||
);
|
||||
|
||||
let child_task = thread_builder.process(Arc::downgrade(&child_proc)).build();
|
||||
child_proc.tasks().lock().insert(child_task).unwrap();
|
||||
|
||||
child_proc
|
||||
}
|
||||
|
||||
fn set_parent_and_group(parent: &Process, child: &Arc<Process>) {
|
||||
// Lock order: process table -> children -> group of process
|
||||
// -> group inner -> session inner
|
||||
|
@ -23,7 +23,8 @@ pub use clone::{clone_child, CloneArgs, CloneFlags};
|
||||
pub use credentials::{Credentials, Gid, Uid};
|
||||
pub use kill::{kill, kill_all, kill_group, tgkill};
|
||||
pub use process::{
|
||||
ExitCode, JobControl, Pgid, Pid, Process, ProcessBuilder, ProcessGroup, Session, Sid, Terminal,
|
||||
spawn_init_process, ExitCode, JobControl, Pgid, Pid, Process, ProcessGroup, Session, Sid,
|
||||
Terminal,
|
||||
};
|
||||
pub use process_filter::ProcessFilter;
|
||||
pub use process_vm::{
|
||||
|
@ -1,7 +1,5 @@
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
#![expect(dead_code)]
|
||||
|
||||
use ostd::{
|
||||
cpu::{context::UserContext, CpuSet},
|
||||
sync::RwArc,
|
||||
@ -94,11 +92,6 @@ impl PosixThreadBuilder {
|
||||
self
|
||||
}
|
||||
|
||||
pub fn sched_policy(mut self, sched_policy: SchedPolicy) -> Self {
|
||||
self.sched_policy = sched_policy;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn build(self) -> Arc<Task> {
|
||||
let Self {
|
||||
tid,
|
||||
|
@ -38,7 +38,7 @@ pub mod thread_table;
|
||||
pub use builder::PosixThreadBuilder;
|
||||
pub use exit::{do_exit, do_exit_group};
|
||||
pub use name::{ThreadName, MAX_THREAD_NAME_LEN};
|
||||
pub use posix_thread_ext::{create_posix_task_from_executable, AsPosixThread};
|
||||
pub use posix_thread_ext::AsPosixThread;
|
||||
pub use robust_list::RobustListHead;
|
||||
pub use thread_local::{AsThreadLocal, FileTableRefMut, ThreadLocal};
|
||||
|
||||
|
@ -1,17 +1,9 @@
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
use ostd::{cpu::context::UserContext, task::Task, user::UserContextApi};
|
||||
use ostd::task::Task;
|
||||
|
||||
use super::{builder::PosixThreadBuilder, name::ThreadName, PosixThread};
|
||||
use crate::{
|
||||
fs::{
|
||||
fs_resolver::{FsPath, AT_FDCWD},
|
||||
thread_info::ThreadFsInfo,
|
||||
},
|
||||
prelude::*,
|
||||
process::{process_vm::ProcessVm, program_loader::ProgramToLoad, Credentials, Process},
|
||||
thread::{AsThread, Thread, Tid},
|
||||
};
|
||||
use super::PosixThread;
|
||||
use crate::thread::{AsThread, Thread};
|
||||
|
||||
/// A trait to provide the `as_posix_thread` method for tasks and threads.
|
||||
pub trait AsPosixThread {
|
||||
@ -30,37 +22,3 @@ impl AsPosixThread for Task {
|
||||
self.as_thread()?.as_posix_thread()
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a task for running an executable file.
|
||||
///
|
||||
/// This function should _only_ be used to create the init user task.
|
||||
pub fn create_posix_task_from_executable(
|
||||
tid: Tid,
|
||||
credentials: Credentials,
|
||||
process_vm: &ProcessVm,
|
||||
executable_path: &str,
|
||||
process: Weak<Process>,
|
||||
argv: Vec<CString>,
|
||||
envp: Vec<CString>,
|
||||
) -> Result<Arc<Task>> {
|
||||
let fs = ThreadFsInfo::default();
|
||||
let (_, elf_load_info) = {
|
||||
let fs_resolver = fs.resolver().read();
|
||||
let fs_path = FsPath::new(AT_FDCWD, executable_path)?;
|
||||
let elf_file = fs.resolver().read().lookup(&fs_path)?;
|
||||
let program_to_load =
|
||||
ProgramToLoad::build_from_file(elf_file, &fs_resolver, argv, envp, 1)?;
|
||||
process_vm.clear_and_map();
|
||||
program_to_load.load_to_vm(process_vm, &fs_resolver)?
|
||||
};
|
||||
|
||||
let mut user_ctx = UserContext::default();
|
||||
user_ctx.set_instruction_pointer(elf_load_info.entry_point() as _);
|
||||
user_ctx.set_stack_pointer(elf_load_info.user_stack_top() as _);
|
||||
let thread_name = Some(ThreadName::new_from_executable_path(executable_path)?);
|
||||
let thread_builder = PosixThreadBuilder::new(tid, Arc::new(user_ctx), credentials)
|
||||
.thread_name(thread_name)
|
||||
.process(process)
|
||||
.fs(Arc::new(fs));
|
||||
Ok(thread_builder.build())
|
||||
}
|
||||
|
@ -1,167 +0,0 @@
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
#![expect(dead_code)]
|
||||
|
||||
use super::{Pid, Process};
|
||||
use crate::{
|
||||
prelude::*,
|
||||
process::{
|
||||
posix_thread::{create_posix_task_from_executable, PosixThreadBuilder},
|
||||
process_vm::ProcessVm,
|
||||
rlimit::ResourceLimits,
|
||||
signal::sig_disposition::SigDispositions,
|
||||
Credentials,
|
||||
},
|
||||
sched::Nice,
|
||||
};
|
||||
|
||||
pub struct ProcessBuilder<'a> {
|
||||
// Essential parts
|
||||
pid: Pid,
|
||||
executable_path: &'a str,
|
||||
parent: Weak<Process>,
|
||||
|
||||
// Optional parts
|
||||
main_thread_builder: Option<PosixThreadBuilder>,
|
||||
argv: Option<Vec<CString>>,
|
||||
envp: Option<Vec<CString>>,
|
||||
process_vm: Option<ProcessVm>,
|
||||
resource_limits: Option<ResourceLimits>,
|
||||
sig_dispositions: Option<Arc<Mutex<SigDispositions>>>,
|
||||
credentials: Option<Credentials>,
|
||||
nice: Option<Nice>,
|
||||
}
|
||||
|
||||
impl<'a> ProcessBuilder<'a> {
|
||||
pub fn new(pid: Pid, executable_path: &'a str, parent: Weak<Process>) -> Self {
|
||||
ProcessBuilder {
|
||||
pid,
|
||||
executable_path,
|
||||
parent,
|
||||
main_thread_builder: None,
|
||||
argv: None,
|
||||
envp: None,
|
||||
process_vm: None,
|
||||
resource_limits: None,
|
||||
sig_dispositions: None,
|
||||
credentials: None,
|
||||
nice: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn main_thread_builder(&mut self, builder: PosixThreadBuilder) -> &mut Self {
|
||||
self.main_thread_builder = Some(builder);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn process_vm(&mut self, process_vm: ProcessVm) -> &mut Self {
|
||||
self.process_vm = Some(process_vm);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn resource_limits(&mut self, resource_limits: ResourceLimits) -> &mut Self {
|
||||
self.resource_limits = Some(resource_limits);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn sig_dispositions(&mut self, sig_dispositions: Arc<Mutex<SigDispositions>>) -> &mut Self {
|
||||
self.sig_dispositions = Some(sig_dispositions);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn argv(&mut self, argv: Vec<CString>) -> &mut Self {
|
||||
self.argv = Some(argv);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn envp(&mut self, envp: Vec<CString>) -> &mut Self {
|
||||
self.envp = Some(envp);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn credentials(&mut self, credentials: Credentials) -> &mut Self {
|
||||
self.credentials = Some(credentials);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn nice(&mut self, nice: Nice) -> &mut Self {
|
||||
self.nice = Some(nice);
|
||||
self
|
||||
}
|
||||
|
||||
fn check_build(&self) -> Result<()> {
|
||||
if self.main_thread_builder.is_some() {
|
||||
debug_assert!(self.parent.upgrade().is_some());
|
||||
debug_assert!(self.argv.is_none());
|
||||
debug_assert!(self.envp.is_none());
|
||||
debug_assert!(self.credentials.is_none());
|
||||
}
|
||||
|
||||
if self.main_thread_builder.is_none() {
|
||||
debug_assert!(self.parent.upgrade().is_none());
|
||||
debug_assert!(self.argv.is_some());
|
||||
debug_assert!(self.envp.is_some());
|
||||
debug_assert!(self.credentials.is_some());
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn build(self) -> Result<Arc<Process>> {
|
||||
self.check_build()?;
|
||||
let Self {
|
||||
pid,
|
||||
executable_path,
|
||||
parent,
|
||||
main_thread_builder,
|
||||
argv,
|
||||
envp,
|
||||
process_vm,
|
||||
resource_limits,
|
||||
sig_dispositions,
|
||||
credentials,
|
||||
nice,
|
||||
} = self;
|
||||
|
||||
let process_vm = process_vm.or_else(|| Some(ProcessVm::alloc())).unwrap();
|
||||
|
||||
let resource_limits = resource_limits
|
||||
.or_else(|| Some(ResourceLimits::default()))
|
||||
.unwrap();
|
||||
|
||||
let sig_dispositions = sig_dispositions
|
||||
.or_else(|| Some(Arc::new(Mutex::new(SigDispositions::new()))))
|
||||
.unwrap();
|
||||
|
||||
let nice = nice.or_else(|| Some(Nice::default())).unwrap();
|
||||
|
||||
let process = Process::new(
|
||||
pid,
|
||||
parent,
|
||||
executable_path.to_string(),
|
||||
process_vm,
|
||||
resource_limits,
|
||||
nice,
|
||||
sig_dispositions,
|
||||
);
|
||||
|
||||
let task = if let Some(thread_builder) = main_thread_builder {
|
||||
let builder = thread_builder.process(Arc::downgrade(&process));
|
||||
builder.build()
|
||||
} else {
|
||||
create_posix_task_from_executable(
|
||||
pid,
|
||||
credentials.unwrap(),
|
||||
process.vm(),
|
||||
executable_path,
|
||||
Arc::downgrade(&process),
|
||||
argv.unwrap(),
|
||||
envp.unwrap(),
|
||||
)?
|
||||
};
|
||||
|
||||
process.tasks().lock().insert(task).unwrap();
|
||||
|
||||
Ok(process)
|
||||
}
|
||||
}
|
146
kernel/src/process/process/init_proc.rs
Normal file
146
kernel/src/process/process/init_proc.rs
Normal file
@ -0,0 +1,146 @@
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
//! This module defines functions related to spawning the init process.
|
||||
|
||||
use ostd::{cpu::context::UserContext, task::Task, user::UserContextApi};
|
||||
|
||||
use super::{Process, Terminal};
|
||||
use crate::{
|
||||
device::tty::get_n_tty,
|
||||
fs::{
|
||||
fs_resolver::{FsPath, AT_FDCWD},
|
||||
thread_info::ThreadFsInfo,
|
||||
},
|
||||
prelude::*,
|
||||
process::{
|
||||
posix_thread::{allocate_posix_tid, PosixThreadBuilder, ThreadName},
|
||||
process_table,
|
||||
process_vm::ProcessVm,
|
||||
rlimit::ResourceLimits,
|
||||
signal::sig_disposition::SigDispositions,
|
||||
Credentials, ProgramToLoad,
|
||||
},
|
||||
sched::Nice,
|
||||
thread::Tid,
|
||||
};
|
||||
|
||||
/// Creates and schedules the init process to run.
|
||||
pub fn spawn_init_process(
|
||||
executable_path: &str,
|
||||
argv: Vec<CString>,
|
||||
envp: Vec<CString>,
|
||||
) -> Result<Arc<Process>> {
|
||||
// Ensure the path for init process executable is absolute.
|
||||
debug_assert!(executable_path.starts_with('/'));
|
||||
|
||||
let process = create_init_process(executable_path, argv, envp)?;
|
||||
|
||||
set_session_and_group(&process);
|
||||
|
||||
open_ntty_as_controlling_terminal(&process)?;
|
||||
|
||||
process.run();
|
||||
|
||||
Ok(process)
|
||||
}
|
||||
|
||||
fn create_init_process(
|
||||
executable_path: &str,
|
||||
argv: Vec<CString>,
|
||||
envp: Vec<CString>,
|
||||
) -> Result<Arc<Process>> {
|
||||
let pid = allocate_posix_tid();
|
||||
let parent = Weak::new();
|
||||
let process_vm = ProcessVm::alloc();
|
||||
let resource_limits = ResourceLimits::default();
|
||||
let nice = Nice::default();
|
||||
let sig_dispositions = Arc::new(Mutex::new(SigDispositions::default()));
|
||||
|
||||
let init_proc = Process::new(
|
||||
pid,
|
||||
parent,
|
||||
executable_path.to_string(),
|
||||
process_vm,
|
||||
resource_limits,
|
||||
nice,
|
||||
sig_dispositions,
|
||||
);
|
||||
|
||||
let init_task = create_init_task(
|
||||
pid,
|
||||
init_proc.vm(),
|
||||
executable_path,
|
||||
Arc::downgrade(&init_proc),
|
||||
argv,
|
||||
envp,
|
||||
)?;
|
||||
init_proc.tasks().lock().insert(init_task).unwrap();
|
||||
|
||||
Ok(init_proc)
|
||||
}
|
||||
|
||||
fn set_session_and_group(process: &Arc<Process>) {
|
||||
// Locking order: session table -> group table -> process table -> process group
|
||||
let mut session_table_mut = process_table::session_table_mut();
|
||||
let mut group_table_mut = process_table::group_table_mut();
|
||||
let mut process_table_mut = process_table::process_table_mut();
|
||||
|
||||
// Create a new process group and session for the process
|
||||
process.set_new_session(
|
||||
&mut process.process_group.lock(),
|
||||
&mut session_table_mut,
|
||||
&mut group_table_mut,
|
||||
);
|
||||
|
||||
// Add the new process to the global table
|
||||
process_table_mut.insert(process.pid(), process.clone());
|
||||
}
|
||||
|
||||
/// Creates the init task from the given executable file.
|
||||
fn create_init_task(
|
||||
tid: Tid,
|
||||
process_vm: &ProcessVm,
|
||||
executable_path: &str,
|
||||
process: Weak<Process>,
|
||||
argv: Vec<CString>,
|
||||
envp: Vec<CString>,
|
||||
) -> Result<Arc<Task>> {
|
||||
let credentials = Credentials::new_root();
|
||||
let fs = ThreadFsInfo::default();
|
||||
let (_, elf_load_info) = {
|
||||
let fs_resolver = fs.resolver().read();
|
||||
let fs_path = FsPath::new(AT_FDCWD, executable_path)?;
|
||||
let elf_file = fs.resolver().read().lookup(&fs_path)?;
|
||||
let program_to_load =
|
||||
ProgramToLoad::build_from_file(elf_file, &fs_resolver, argv, envp, 1)?;
|
||||
process_vm.clear_and_map();
|
||||
program_to_load.load_to_vm(process_vm, &fs_resolver)?
|
||||
};
|
||||
|
||||
let mut user_ctx = UserContext::default();
|
||||
user_ctx.set_instruction_pointer(elf_load_info.entry_point() as _);
|
||||
user_ctx.set_stack_pointer(elf_load_info.user_stack_top() as _);
|
||||
let thread_name = Some(ThreadName::new_from_executable_path(executable_path)?);
|
||||
let thread_builder = PosixThreadBuilder::new(tid, Arc::new(user_ctx), credentials)
|
||||
.thread_name(thread_name)
|
||||
.process(process)
|
||||
.fs(Arc::new(fs));
|
||||
Ok(thread_builder.build())
|
||||
}
|
||||
|
||||
/// Opens `N_TTY` as the controlling terminal for the process.
|
||||
fn open_ntty_as_controlling_terminal(process: &Process) -> Result<()> {
|
||||
let tty = get_n_tty();
|
||||
|
||||
let session = &process.session().unwrap();
|
||||
let process_group = process.process_group().unwrap();
|
||||
|
||||
session.set_terminal(|| {
|
||||
tty.job_control().set_session(session);
|
||||
Ok(tty.clone())
|
||||
})?;
|
||||
|
||||
tty.job_control().set_foreground(Some(&process_group))?;
|
||||
|
||||
Ok(())
|
||||
}
|
@ -4,7 +4,7 @@ use core::sync::atomic::{AtomicBool, AtomicU32, Ordering};
|
||||
|
||||
use self::timer_manager::PosixTimerManager;
|
||||
use super::{
|
||||
posix_thread::{allocate_posix_tid, AsPosixThread},
|
||||
posix_thread::AsPosixThread,
|
||||
process_table,
|
||||
process_vm::{Heap, InitStackReader, ProcessVm, ProcessVmarGuard},
|
||||
rlimit::ResourceLimits,
|
||||
@ -15,17 +15,15 @@ use super::{
|
||||
},
|
||||
status::ProcessStatus,
|
||||
task_set::TaskSet,
|
||||
Credentials,
|
||||
};
|
||||
use crate::{
|
||||
device::tty::open_ntty_as_controlling_terminal,
|
||||
prelude::*,
|
||||
sched::{AtomicNice, Nice},
|
||||
thread::{AsThread, Thread},
|
||||
time::clocks::ProfClock,
|
||||
};
|
||||
|
||||
mod builder;
|
||||
mod init_proc;
|
||||
mod job_control;
|
||||
mod process_group;
|
||||
mod session;
|
||||
@ -33,7 +31,7 @@ mod terminal;
|
||||
mod timer_manager;
|
||||
|
||||
use atomic_integer_wrapper::define_atomic_version_of_integer_like_type;
|
||||
pub use builder::ProcessBuilder;
|
||||
pub use init_proc::spawn_init_process;
|
||||
pub use job_control::JobControl;
|
||||
use ostd::{sync::WaitQueue, task::Task};
|
||||
pub use process_group::ProcessGroup;
|
||||
@ -184,7 +182,7 @@ impl Process {
|
||||
Some(Task::current()?.as_posix_thread()?.process())
|
||||
}
|
||||
|
||||
fn new(
|
||||
pub(super) fn new(
|
||||
pid: Pid,
|
||||
parent: Weak<Process>,
|
||||
executable_path: String,
|
||||
@ -222,57 +220,8 @@ impl Process {
|
||||
})
|
||||
}
|
||||
|
||||
/// init a user process and run the process
|
||||
pub fn spawn_user_process(
|
||||
executable_path: &str,
|
||||
argv: Vec<CString>,
|
||||
envp: Vec<CString>,
|
||||
) -> Result<Arc<Self>> {
|
||||
// spawn user process should give an absolute path
|
||||
debug_assert!(executable_path.starts_with('/'));
|
||||
let process = Process::create_user_process(executable_path, argv, envp)?;
|
||||
|
||||
open_ntty_as_controlling_terminal(&process)?;
|
||||
|
||||
process.run();
|
||||
Ok(process)
|
||||
}
|
||||
|
||||
fn create_user_process(
|
||||
executable_path: &str,
|
||||
argv: Vec<CString>,
|
||||
envp: Vec<CString>,
|
||||
) -> Result<Arc<Self>> {
|
||||
let process = {
|
||||
let pid = allocate_posix_tid();
|
||||
let parent = Weak::new();
|
||||
let credentials = Credentials::new_root();
|
||||
|
||||
let mut builder = ProcessBuilder::new(pid, executable_path, parent);
|
||||
builder.argv(argv).envp(envp).credentials(credentials);
|
||||
builder.build()?
|
||||
};
|
||||
|
||||
// Lock order: session table -> group table -> process table -> group of process
|
||||
let mut session_table_mut = process_table::session_table_mut();
|
||||
let mut group_table_mut = process_table::group_table_mut();
|
||||
let mut process_table_mut = process_table::process_table_mut();
|
||||
|
||||
// Create a new process group and a new session for the new process
|
||||
process.set_new_session(
|
||||
&mut process.process_group.lock(),
|
||||
&mut session_table_mut,
|
||||
&mut group_table_mut,
|
||||
);
|
||||
|
||||
// Insert the new process to the global table
|
||||
process_table_mut.insert(process.pid(), process.clone());
|
||||
|
||||
Ok(process)
|
||||
}
|
||||
|
||||
/// start to run current process
|
||||
pub fn run(&self) {
|
||||
/// Runs the process.
|
||||
pub(super) fn run(&self) {
|
||||
let tasks = self.tasks.lock();
|
||||
// when run the process, the process should has only one thread
|
||||
debug_assert!(tasks.as_slice().len() == 1);
|
||||
|
@ -26,6 +26,7 @@ const INIT_RLIMIT_MEMLOCK: u64 = 8 * 1024 * 1024;
|
||||
// https://github.com/torvalds/linux/blob/fac04efc5c793dccbd07e2d59af9f90b7fc0dca4/include/uapi/linux/mqueue.h#L26
|
||||
const INIT_RLIMIT_MSGQUEUE: u64 = 819200;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct ResourceLimits {
|
||||
rlimits: [RLimit64; RLIMIT_COUNT],
|
||||
}
|
||||
@ -169,3 +170,14 @@ impl Default for RLimit64 {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Clone for RLimit64 {
|
||||
fn clone(&self) -> Self {
|
||||
let (cur, max) = self.get_cur_and_max();
|
||||
Self {
|
||||
cur: AtomicU64::new(cur),
|
||||
max: AtomicU64::new(max),
|
||||
lock: SpinLock::new(()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user