DragonOS/kernel/src/init/initial_kthread.rs
火花 bc9bb9607f
Feat(tty): Supplement process group logic (#1139)
* 添加busybox的编译

* 完善tty job control的逻辑

* 修改copy_sighand的逻辑,符合Linux语义

* 以busybox作为启动shell去运行

* 修改setsid的逻辑

* 解决前台进程组无法处理信号的问题

* 移除ProcessBasicInfo其中的pgid和sid信息

* 修改setsid

* 新增get_pcb_info

* 在etc目录下新增必要的文件

* 改用busybox init作为引导程序

* 恢复dragonreach文件

* 修改busybox编译选项,能够读取环境变量

* 先让SYS_RT_SIGTIMEDWAIT返回Ok(0),能够正常进入系统

* 一些小更改

* 删除get_pcb_info

* 增加对默认termios的判断

* 完成backspace的修复

* 更改inittab,在shell启动之后更改termios

* 增加executable_path信息

* 补充proc下的exe链接文件以及读取逻辑

* 更改PosixTermios,使用stty完成erase的设置

* 用busybox作为引导程序

* 修改波特率的获取

* 修改函数方法

* 在baud_rate方法中添加对于cbaud的与操作

* 为rv64下的SigSet实现From<Signal>

* refactor(driver): 移除`#[derive(Debug)]`并手动实现`Debug` trait

移除`VirtIOBlkDevice`、`VirtIOConsoleDevice`和`VirtIONetDevice`的`#[derive(Debug)]`,并手动实现`Debug` trait以提供更详细的调试信息。

Co-authored-by: longjin <longjin@DragonOS.org>
2025-05-08 15:05:02 +08:00

176 lines
5.2 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//! 这个文件内放置初始内核线程的代码。
use core::sync::atomic::{compiler_fence, Ordering};
use alloc::{ffi::CString, string::ToString};
use log::{debug, error};
use system_error::SystemError;
use crate::{
arch::{interrupt::TrapFrame, process::arch_switch_to_user},
driver::net::e1000e::e1000e::e1000e_init,
filesystem::vfs::core::mount_root_fs,
namespaces::NsProxy,
net::net_core::net_init,
process::{
exec::ProcInitInfo, kthread::KernelThreadMechanism, stdio::stdio_init, ProcessFlags,
ProcessManager,
},
smp::smp_init,
syscall::Syscall,
};
use super::{cmdline::kenrel_cmdline_param_manager, initcall::do_initcalls};
const INIT_PROC_TRYLIST: [(&str, Option<&str>); 4] = [
("/bin/dragonreach", None),
("/bin/busybox", Some("init")),
("/bin/init", None),
("/bin/sh", None),
];
pub fn initial_kernel_thread() -> i32 {
kernel_init().unwrap_or_else(|err| {
log::error!("Failed to initialize kernel: {:?}", err);
panic!()
});
switch_to_user();
}
fn kernel_init() -> Result<(), SystemError> {
KernelThreadMechanism::init_stage2();
kenrel_init_freeable()?;
#[cfg(target_arch = "x86_64")]
crate::driver::disk::ahci::ahci_init()
.inspect_err(|e| log::error!("ahci_init failed: {:?}", e))
.ok();
mount_root_fs().expect("Failed to mount root fs");
e1000e_init();
net_init().unwrap_or_else(|err| {
error!("Failed to initialize network: {:?}", err);
});
debug!("initial kernel thread done.");
return Ok(());
}
#[inline(never)]
fn kenrel_init_freeable() -> Result<(), SystemError> {
do_initcalls().unwrap_or_else(|err| {
panic!("Failed to initialize subsystems: {:?}", err);
});
stdio_init().expect("Failed to initialize stdio");
smp_init();
return Ok(());
}
/// 切换到用户态
#[inline(never)]
fn switch_to_user() -> ! {
let current_pcb = ProcessManager::current_pcb();
// 删除kthread的标志
current_pcb.flags().remove(ProcessFlags::KTHREAD);
current_pcb.worker_private().take();
*current_pcb.sched_info().sched_policy.write_irqsave() = crate::sched::SchedPolicy::CFS;
drop(current_pcb);
let mut proc_init_info = ProcInitInfo::new("");
proc_init_info.envs.push(CString::new("PATH=/").unwrap());
proc_init_info.args = kenrel_cmdline_param_manager().init_proc_args();
proc_init_info.envs = kenrel_cmdline_param_manager().init_proc_envs();
let mut trap_frame = TrapFrame::new();
if let Some(path) = kenrel_cmdline_param_manager().init_proc_path() {
log::info!("Boot with specified init process: {:?}", path);
try_to_run_init_process(
path.as_c_str().to_str().unwrap(),
&mut proc_init_info,
&None,
&mut trap_frame,
)
.unwrap_or_else(|e| {
panic!(
"Failed to run specified init process: {:?}, err: {:?}",
path, e
)
});
} else {
let mut ok = false;
for (path, ext_args) in INIT_PROC_TRYLIST.iter() {
if try_to_run_init_process(path, &mut proc_init_info, ext_args, &mut trap_frame).is_ok()
{
ok = true;
break;
}
}
if !ok {
panic!("Failed to run init process: No working init found.");
}
}
drop(proc_init_info);
// 需要确保执行到这里之后上面所有的资源都已经释放比如arc之类的
compiler_fence(Ordering::SeqCst);
unsafe { arch_switch_to_user(trap_frame) };
}
fn try_to_run_init_process(
path: &str,
proc_init_info: &mut ProcInitInfo,
ext_args: &Option<&str>,
trap_frame: &mut TrapFrame,
) -> Result<(), SystemError> {
log::debug!("Trying to run init process at {:?}", path);
let mut args_to_insert = alloc::vec::Vec::new();
args_to_insert.push(CString::new(path).unwrap());
if let Some(ext_args) = ext_args {
// Split ext_args by whitespace and trim each part
for arg in ext_args.split_whitespace() {
args_to_insert.push(CString::new(arg.trim()).unwrap());
}
}
proc_init_info.proc_name = CString::new(path).unwrap();
let elements_to_remove = args_to_insert.len();
let old_args = core::mem::replace(&mut proc_init_info.args, args_to_insert);
proc_init_info.args.extend(old_args);
if let Err(e) = run_init_process(proc_init_info, trap_frame) {
if e != SystemError::ENOENT {
error!(
"Failed to run init process: {path} exists but couldn't execute it (error {:?})",
e
);
}
proc_init_info.args.drain(0..elements_to_remove);
return Err(e);
}
Ok(())
}
fn run_init_process(
proc_init_info: &ProcInitInfo,
trap_frame: &mut TrapFrame,
) -> Result<(), SystemError> {
compiler_fence(Ordering::SeqCst);
ProcessManager::current_pcb().set_nsproxy(NsProxy::new()); // 初始化init进程的namespace
let path = proc_init_info.proc_name.to_str().unwrap();
Syscall::do_execve(
path.to_string(),
proc_init_info.args.clone(),
proc_init_info.envs.clone(),
trap_frame,
)?;
Ok(())
}