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>
This commit is contained in:
火花 2025-05-08 15:05:02 +08:00 committed by GitHub
parent f3bfe77712
commit bc9bb9607f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
26 changed files with 552 additions and 154 deletions

View File

@ -4,7 +4,6 @@
},
"C_Cpp.errorSquiggles": "enabled",
"esbonio.sphinx.confDir": "",
"rust-analyzer.checkOnSave.allTargets": false,
"rust-analyzer.linkedProjects": [
"./kernel/Cargo.toml",
//"./tools/Cargo.toml",

View File

@ -31,3 +31,4 @@ DragonOS是一个开源项目我们欢迎任何形式的赞助和捐赠
-------------------------
DragonOS社区的捐赠信息将按年进行公开。赞助商、赞助者信息将在收到赞助后15天内进行公开。

View File

@ -93,11 +93,14 @@ impl From<i32> for Signal {
}
}
impl Into<SigSet> for Signal {
fn into(self) -> SigSet {
self.into_sigset()
impl From<Signal> for SigSet {
fn from(val: Signal) -> Self {
SigSet {
bits: (1 << (val as usize - 1) as u64),
}
}
}
impl Signal {
/// 判断一个数字是否为可用的信号
#[inline]

View File

@ -1,4 +1,7 @@
use core::{any::Any, fmt::Debug};
use core::{
any::Any,
fmt::{Debug, Formatter},
};
use alloc::{
string::{String, ToString},
@ -147,7 +150,6 @@ impl VirtIOBlkManager {
}
/// virtio block device
#[derive(Debug)]
#[cast_to([sync] VirtIODevice)]
#[cast_to([sync] Device)]
pub struct VirtIOBlkDevice {
@ -158,6 +160,15 @@ pub struct VirtIOBlkDevice {
self_ref: Weak<Self>,
}
impl Debug for VirtIOBlkDevice {
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
f.debug_struct("VirtIOBlkDevice")
.field("devname", &self.blkdev_meta.devname)
.field("dev_id", &self.dev_id.id())
.finish()
}
}
unsafe impl Send for VirtIOBlkDevice {}
unsafe impl Sync for VirtIOBlkDevice {}

View File

@ -90,7 +90,7 @@ pub fn virtio_console(
}
//
#[derive(Debug)]
#[cast_to([sync] VirtIODevice)]
#[cast_to([sync] Device)]
pub struct VirtIOConsoleDevice {
@ -103,6 +103,22 @@ pub struct VirtIOConsoleDevice {
unsafe impl Send for VirtIOConsoleDevice {}
unsafe impl Sync for VirtIOConsoleDevice {}
impl Debug for VirtIOConsoleDevice {
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
f.debug_struct("VirtIOConsoleDevice")
.field(
"devname",
&self
.dev_name
.try_get()
.map(|x| x.as_str())
.unwrap_or("uninitialized"),
)
.field("dev_id", &self.dev_id.id())
.finish()
}
}
impl VirtIOConsoleDevice {
pub fn new(transport: VirtIOTransport, dev_id: Arc<DeviceId>) -> Option<Arc<Self>> {
// 设置中断

View File

@ -1,7 +1,7 @@
use core::{
any::Any,
cell::UnsafeCell,
fmt::Debug,
fmt::{Debug, Formatter},
ops::{Deref, DerefMut},
};
@ -62,7 +62,6 @@ fn virtio_net_driver() -> Arc<VirtIONetDriver> {
}
/// virtio net device
#[derive(Debug)]
#[cast_to([sync] VirtIODevice)]
#[cast_to([sync] Device)]
pub struct VirtIONetDevice {
@ -71,6 +70,14 @@ pub struct VirtIONetDevice {
locked_kobj_state: LockedKObjectState,
}
impl Debug for VirtIONetDevice {
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
f.debug_struct("VirtIONetDevice")
.field("dev_id", &self.dev_id.id())
.finish()
}
}
unsafe impl Send for VirtIONetDevice {}
unsafe impl Sync for VirtIONetDevice {}
@ -84,7 +91,7 @@ struct InnerVirtIONetDevice {
impl Debug for InnerVirtIONetDevice {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_struct("InnerVirtIOBlkDevice").finish()
f.debug_struct("InnerVirtIONetDevice").finish()
}
}

View File

@ -44,10 +44,8 @@ pub struct PosixTermios {
pub c_oflag: u32,
pub c_cflag: u32,
pub c_lflag: u32,
pub c_cc: [u8; CONTORL_CHARACTER_NUM],
pub c_line: u8,
pub c_ispeed: u32,
pub c_ospeed: u32,
pub c_cc: [u8; CONTORL_CHARACTER_NUM],
}
impl PosixTermios {
@ -59,8 +57,6 @@ impl PosixTermios {
c_lflag: termios.local_mode.bits,
c_cc: termios.control_characters,
c_line: termios.line as u8,
c_ispeed: termios.input_speed,
c_ospeed: termios.output_speed,
}
}
@ -73,8 +69,24 @@ impl PosixTermios {
local_mode: LocalMode::from_bits_truncate(self.c_lflag),
control_characters: self.c_cc,
line: LineDisciplineType::from_line(self.c_line),
input_speed: self.c_ispeed,
output_speed: self.c_ospeed,
input_speed: self.input_speed().unwrap_or(38400),
output_speed: self.output_speed().unwrap_or(38400),
}
}
fn output_speed(&self) -> Option<u32> {
let flag = ControlMode::from_bits_truncate(
self.c_cflag & ControlMode::CBAUD.intersection(ControlMode::CBAUDEX).bits(),
); // CBAUD + CBAUDEX
flag.baud_rate()
}
fn input_speed(&self) -> Option<u32> {
let ibaud = (self.c_cflag & ControlMode::CIBAUD.bits()) >> 16;
if ibaud == 0 {
self.output_speed()
} else {
ControlMode::from_bits_truncate(ibaud).baud_rate()
}
}
}
@ -352,6 +364,47 @@ bitflags! {
}
}
impl ControlMode {
/// 获取波特率
pub fn baud_rate(&self) -> Option<u32> {
let flag = self.intersection(Self::CBAUD);
match flag {
Self::B0 => Some(0),
Self::B50 => Some(50),
Self::B75 => Some(75),
Self::B110 => Some(110),
Self::B134 => Some(134),
Self::B150 => Some(150),
Self::B200 => Some(200),
Self::B300 => Some(300),
Self::B600 => Some(600),
Self::B1200 => Some(1200),
Self::B1800 => Some(1800),
Self::B2400 => Some(2400),
Self::B4800 => Some(4800),
Self::B9600 => Some(9600),
Self::B19200 => Some(19200),
Self::B38400 => Some(38400),
Self::B57600 => Some(57600),
Self::B115200 => Some(115200),
Self::B230400 => Some(230400),
Self::B460800 => Some(460800),
Self::B500000 => Some(500000),
Self::B576000 => Some(576000),
Self::B921600 => Some(921600),
Self::B1000000 => Some(1000000),
Self::B1152000 => Some(1152000),
Self::B1500000 => Some(1500000),
Self::B2000000 => Some(2000000),
Self::B2500000 => Some(2500000),
Self::B3000000 => Some(3000000),
Self::B3500000 => Some(3500000),
Self::B4000000 => Some(4000000),
_ => None,
}
}
}
/// 对应termios中控制字符的索引
pub struct ControlCharIndex;
#[allow(dead_code)]

View File

@ -19,7 +19,7 @@ use crate::{
},
mm::VirtAddr,
net::event_poll::{EPollEventType, EPollItem},
process::Pid,
process::{process_group::Pgid, session::Sid, ProcessControlBlock},
syscall::user_access::{UserBufferReader, UserBufferWriter},
};
@ -280,16 +280,23 @@ impl TtyCore {
#[derive(Debug, Default)]
pub struct TtyContorlInfo {
/// 前台进程pid
pub session: Option<Pid>,
/// 当前会话的SId
pub session: Option<Sid>,
/// 前台进程组id
pub pgid: Option<Pid>,
pub pgid: Option<Pgid>,
/// packet模式下使用目前未用到
pub pktstatus: TtyPacketStatus,
pub packet: bool,
}
impl TtyContorlInfo {
pub fn set_info_by_pcb(&mut self, pcb: Arc<ProcessControlBlock>) {
self.session = Some(pcb.sid());
self.pgid = Some(pcb.pgid());
}
}
#[derive(Debug, Default)]
pub struct TtyFlowState {
/// 表示流控是否被停止

View File

@ -4,7 +4,7 @@ use system_error::SystemError;
use crate::{
arch::ipc::signal::{SigSet, Signal},
mm::VirtAddr,
process::{Pid, ProcessFlags, ProcessManager},
process::{process_group::Pgid, Pid, ProcessFlags, ProcessManager},
syscall::{
user_access::{UserBufferReader, UserBufferWriter},
Syscall,
@ -19,16 +19,13 @@ impl TtyJobCtrlManager {
/// ### 设置当前进程的tty
pub fn proc_set_tty(tty: Arc<TtyCore>) {
let core = tty.core();
let mut ctrl = core.contorl_info_irqsave();
let pcb = ProcessManager::current_pcb();
let pid = Pid::new(pcb.basic().sid().into());
ctrl.session = Some(pid);
assert!(pcb.sig_info_irqsave().tty().is_none());
let mut ctrl = core.contorl_info_irqsave();
ctrl.set_info_by_pcb(pcb.clone());
drop(ctrl);
let mut singal = pcb.sig_info_mut();
drop(ctrl);
singal.set_tty(Some(tty.clone()));
}
@ -42,27 +39,27 @@ impl TtyJobCtrlManager {
return Ok(());
}
let core = tty.core();
let ctrl = core.contorl_info_irqsave();
let pgid = pcb.pgid();
// todo pgid
let pgid = pcb.pid();
let ctrl = tty.core().contorl_info_irqsave();
let tty_pgid = ctrl.pgid;
drop(ctrl);
if tty_pgid.is_some() && tty_pgid.unwrap() != pgid {
if pcb
.sig_info_irqsave()
.sig_blocked()
.contains(SigSet::from_bits_truncate(1 << sig as u64))
.contains(SigSet::from(sig))
|| pcb.sig_struct_irqsave().handlers[sig as usize - 1].is_ignore()
{
// 忽略该信号
if sig == Signal::SIGTTIN {
return Err(SystemError::EIO);
}
} else if ProcessManager::is_current_pgrp_orphaned() {
return Err(SystemError::EIO);
} else {
// 暂时使用kill而不是killpg
Syscall::kill_process(pgid, sig)?;
Syscall::kill_process_group(pgid, sig)?;
ProcessManager::current_pcb()
.flags()
.insert(ProcessFlags::HAS_PENDING_SIGNAL);
@ -74,74 +71,146 @@ impl TtyJobCtrlManager {
Ok(())
}
pub fn job_ctrl_ioctl(tty: Arc<TtyCore>, cmd: u32, arg: usize) -> Result<usize, SystemError> {
pub fn job_ctrl_ioctl(
real_tty: Arc<TtyCore>,
cmd: u32,
arg: usize,
) -> Result<usize, SystemError> {
match cmd {
TtyIoctlCmd::TIOCSPGRP => {
match Self::tty_check_change(tty.clone(), Signal::SIGTTOU) {
Ok(_) => {}
Err(e) => {
if e == SystemError::EIO {
return Err(SystemError::ENOTTY);
}
return Err(e);
}
};
let user_reader = UserBufferReader::new(
VirtAddr::new(arg).as_ptr::<i32>(),
core::mem::size_of::<i32>(),
true,
)?;
let pgrp = user_reader.read_one_from_user::<i32>(0)?;
let current = ProcessManager::current_pcb();
let mut ctrl = tty.core().contorl_info_irqsave();
if current.sig_info_irqsave().tty().is_none()
|| !Arc::ptr_eq(&current.sig_info_irqsave().tty().clone().unwrap(), &tty)
|| ctrl.session.is_none()
|| ctrl.session.unwrap() != Pid::from(current.basic().sid().into())
{
return Err(SystemError::ENOTTY);
}
ctrl.pgid = Some(Pid::from(*pgrp as usize));
return Ok(0);
}
TtyIoctlCmd::TIOCGPGRP => {
let current = ProcessManager::current_pcb();
if current.sig_info_irqsave().tty().is_some()
&& !Arc::ptr_eq(&current.sig_info_irqsave().tty().unwrap(), &tty)
{
return Err(SystemError::ENOTTY);
}
let mut user_writer = UserBufferWriter::new(
VirtAddr::new(arg).as_ptr::<i32>(),
core::mem::size_of::<i32>(),
true,
)?;
user_writer.copy_one_to_user(
&(tty
.core()
.contorl_info_irqsave()
.pgid
.unwrap_or(Pid::new(0))
.data() as i32),
0,
)?;
return Ok(0);
}
TtyIoctlCmd::TIOCSPGRP => Self::tiocspgrp(real_tty, arg),
TtyIoctlCmd::TIOCGPGRP => Self::tiocgpgrp(real_tty, arg),
TtyIoctlCmd::TIOCGSID => Self::tiocgsid(real_tty, arg),
TtyIoctlCmd::TIOCSCTTY => Self::tiocsctty(real_tty),
_ => {
return Err(SystemError::ENOIOCTLCMD);
}
}
}
fn tiocsctty(real_tty: Arc<TtyCore>) -> Result<usize, SystemError> {
let current = ProcessManager::current_pcb();
// log::debug!("job_ctrl_ioctl: TIOCSCTTY,current: {:?}", current.pid());
if current.is_session_leader()
&& real_tty.core().contorl_info_irqsave().session.unwrap() == current.sid()
{
return Ok(0);
}
if !current.is_session_leader() || current.sig_info_irqsave().tty().is_some() {
return Err(SystemError::EPERM);
}
//todo 权限检查?
// https://code.dragonos.org.cn/xref/linux-6.6.21/drivers/tty/tty_jobctrl.c#tiocsctty
if let Some(sid) = real_tty.core().contorl_info_irqsave().session {
//todo 目前只有一个tty设备所以选择复用1号进程的tty因此修改1号进程的tty暂时被允许
if sid != Pid::new(1) {
return Err(SystemError::EPERM);
}
}
Self::proc_set_tty(real_tty);
Ok(0)
}
fn tiocgpgrp(real_tty: Arc<TtyCore>, arg: usize) -> Result<usize, SystemError> {
// log::debug!("job_ctrl_ioctl: TIOCGPGRP");
let current = ProcessManager::current_pcb();
if current.sig_info_irqsave().tty().is_some()
&& !Arc::ptr_eq(&current.sig_info_irqsave().tty().unwrap(), &real_tty)
{
return Err(SystemError::ENOTTY);
}
let mut user_writer = UserBufferWriter::new(
VirtAddr::new(arg).as_ptr::<i32>(),
core::mem::size_of::<i32>(),
true,
)?;
user_writer.copy_one_to_user(
&(real_tty
.core()
.contorl_info_irqsave()
.pgid
.unwrap_or(Pid::new(1))
.data() as i32),
0,
)?;
return Ok(0);
}
fn tiocgsid(real_tty: Arc<TtyCore>, arg: usize) -> Result<usize, SystemError> {
// log::debug!("job_ctrl_ioctl: TIOCGSID");
let current = ProcessManager::current_pcb();
if current.sig_info_irqsave().tty().is_some()
&& !Arc::ptr_eq(&current.sig_info_irqsave().tty().unwrap(), &real_tty)
{
return Err(SystemError::ENOTTY);
}
let guard = real_tty.core().contorl_info_irqsave();
if guard.session.is_none() {
return Err(SystemError::ENOTTY);
}
let sid = guard.session.unwrap();
drop(guard);
let mut user_writer = UserBufferWriter::new(
VirtAddr::new(arg).as_ptr::<i32>(),
core::mem::size_of::<i32>(),
true,
)?;
user_writer.copy_one_to_user(&(sid.data() as i32), 0)?;
return Ok(0);
}
fn tiocspgrp(real_tty: Arc<TtyCore>, arg: usize) -> Result<usize, SystemError> {
// log::debug!("job_ctrl_ioctl: TIOCSPGRP");
match Self::tty_check_change(real_tty.clone(), Signal::SIGTTOU) {
Ok(_) => {}
Err(e) => {
if e == SystemError::EIO {
return Err(SystemError::ENOTTY);
}
return Err(e);
}
};
let user_reader = UserBufferReader::new(
VirtAddr::new(arg).as_ptr::<i32>(),
core::mem::size_of::<i32>(),
true,
)?;
let pgrp = user_reader.read_one_from_user::<i32>(0)?;
let current = ProcessManager::current_pcb();
let mut ctrl = real_tty.core().contorl_info_irqsave();
if current.sig_info_irqsave().tty().is_none()
|| !Arc::ptr_eq(
&current.sig_info_irqsave().tty().clone().unwrap(),
&real_tty,
)
|| ctrl.session.is_none()
|| ctrl.session.unwrap() != current.sid()
{
return Err(SystemError::ENOTTY);
}
let pg = ProcessManager::find_process_group(Pgid::from(*pgrp as usize));
if pg.is_none() {
return Err(SystemError::ESRCH);
} else if !Arc::ptr_eq(&pg.unwrap().session().unwrap(), &current.session().unwrap()) {
return Err(SystemError::EPERM);
}
ctrl.pgid = Some(Pid::from(*pgrp as usize));
return Ok(0);
}
}

View File

@ -390,7 +390,7 @@ impl NTtyData {
continue;
}
if ((c as usize) < self.char_map.size()) && self.char_map.get(c as usize).unwrap() {
if ((c as usize) < self.char_map.len()) && self.char_map.get(c as usize).unwrap() {
// 特殊字符
self.receive_special_char(c, tty.clone(), lookahead_done);
} else {
@ -790,7 +790,7 @@ impl NTtyData {
let ctrl_info = tty.core().contorl_info_irqsave();
let pg = ctrl_info.pgid;
if let Some(pg) = pg {
let _ = Syscall::kill_process(pg, signal);
let _ = Syscall::kill_process_group(pg, signal);
}
if !termios.local_mode.contains(LocalMode::NOFLSH) {

View File

@ -50,6 +50,8 @@ pub enum ProcFileType {
ProcMeminfo = 1,
/// kmsg
ProcKmsg = 2,
/// 可执行路径
ProcExe = 3,
//todo: 其他文件类型
///默认文件类型
Default,
@ -61,6 +63,7 @@ impl From<u8> for ProcFileType {
0 => ProcFileType::ProcStatus,
1 => ProcFileType::ProcMeminfo,
2 => ProcFileType::ProcKmsg,
3 => ProcFileType::ProcExe,
_ => ProcFileType::Default,
}
}
@ -266,6 +269,28 @@ impl ProcFSInode {
return Ok((data.len() * size_of::<u8>()) as i64);
}
// 打开 exe 文件
fn open_exe(&self, _pdata: &mut ProcfsFilePrivateData) -> Result<i64, SystemError> {
// 这个文件是一个软链接直接返回0即可
return Ok(0);
}
// 读取exe文件
fn read_link(&self, buf: &mut [u8]) -> Result<usize, SystemError> {
// 判断是否有记录pid信息有的话就是当前进程的exe文件没有则是当前进程的exe文件
let pid = self.fdata.pid;
let pcb = if pid == Pid::from(0) {
ProcessManager::current_pcb()
} else {
ProcessManager::find(pid).ok_or(SystemError::ESRCH)?
};
let exe = pcb.execute_path();
let exe_bytes = exe.as_bytes();
let len = exe_bytes.len().min(buf.len());
buf[..len].copy_from_slice(&exe_bytes[..len]);
Ok(len)
}
/// proc文件系统读取函数
fn proc_read(
&self,
@ -419,6 +444,23 @@ impl ProcFS {
} else {
panic!("create version_signature error");
}
let self_dir = inode
.create("self", FileType::Dir, ModeType::from_bits_truncate(0o555))
.unwrap();
let binding = self_dir.create("exe", FileType::SymLink, ModeType::S_IRUGO);
if let Ok(exe) = binding {
let exe_file = exe
.as_any_ref()
.downcast_ref::<LockedProcFSInode>()
.unwrap();
exe_file.0.lock().fdata.pid = Pid::new(0);
exe_file.0.lock().fdata.ftype = ProcFileType::ProcExe;
} else {
panic!("create exe error");
}
return result;
}
@ -435,18 +477,32 @@ impl ProcFS {
)?;
// 创建相关文件
// status文件
let binding: Arc<dyn IndexNode> = pid_dir.create(
let status_binding: Arc<dyn IndexNode> = pid_dir.create(
"status",
FileType::File,
ModeType::from_bits_truncate(0o444),
)?;
let status_file: &LockedProcFSInode = binding
let status_file: &LockedProcFSInode = status_binding
.as_any_ref()
.downcast_ref::<LockedProcFSInode>()
.unwrap();
status_file.0.lock().fdata.pid = pid;
status_file.0.lock().fdata.ftype = ProcFileType::ProcStatus;
// exe文件
let exe_binding: Arc<dyn IndexNode> = pid_dir.create_with_data(
"exe",
FileType::SymLink,
ModeType::from_bits_truncate(0o444),
0,
)?;
let exe_file = exe_binding
.as_any_ref()
.downcast_ref::<LockedProcFSInode>()
.unwrap();
exe_file.0.lock().fdata.pid = pid;
exe_file.0.lock().fdata.ftype = ProcFileType::ProcExe;
//todo: 创建其他文件
return Ok(());
@ -461,6 +517,7 @@ impl ProcFS {
let pid_dir: Arc<dyn IndexNode> = proc.find(&pid.to_string())?;
// 删除进程文件夹下文件
pid_dir.unlink("status")?;
pid_dir.unlink("exe")?;
// 查看进程文件是否还存在
// let pf= pid_dir.find("status").expect("Cannot find status");
@ -490,6 +547,7 @@ impl IndexNode for LockedProcFSInode {
let file_size = match inode.fdata.ftype {
ProcFileType::ProcStatus => inode.open_status(&mut private_data)?,
ProcFileType::ProcMeminfo => inode.open_meminfo(&mut private_data)?,
ProcFileType::ProcExe => inode.open_exe(&mut private_data)?,
ProcFileType::Default => inode.data.len() as i64,
_ => {
todo!()
@ -548,6 +606,7 @@ impl IndexNode for LockedProcFSInode {
ProcFileType::ProcMeminfo => {
return inode.proc_read(offset, len, buf, &mut private_data)
}
ProcFileType::ProcExe => return inode.read_link(buf),
ProcFileType::ProcKmsg => (),
ProcFileType::Default => (),
};

View File

@ -24,9 +24,9 @@ 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),
("/bin/busybox", Some("init")),
];
pub fn initial_kernel_thread() -> i32 {

View File

@ -310,13 +310,21 @@ impl ProcessManager {
current_pcb: &Arc<ProcessControlBlock>,
new_pcb: &Arc<ProcessControlBlock>,
) -> Result<(), SystemError> {
// // 将信号的处理函数设置为default(除了那些被手动屏蔽的)
if clone_flags.contains(CloneFlags::CLONE_CLEAR_SIGHAND) {
flush_signal_handlers(new_pcb.clone(), false);
// todo SignalStruct结构需要更改属于线程组逻辑
if clone_flags.contains(CloneFlags::CLONE_SIGHAND) {
// log::debug!("copy_sighand: CLONE_SIGHAND");
current_pcb
.sig_struct_irqsave()
.cnt
.fetch_add(1, Ordering::SeqCst);
return Ok(());
}
if clone_flags.contains(CloneFlags::CLONE_SIGHAND) {
new_pcb.sig_struct_irqsave().handlers = current_pcb.sig_struct_irqsave().handlers;
// log::debug!("Just copy sighand");
new_pcb.sig_struct_irqsave().handlers = current_pcb.sig_struct_irqsave().handlers;
if clone_flags.contains(CloneFlags::CLONE_CLEAR_SIGHAND) {
flush_signal_handlers(new_pcb.clone(), false);
}
return Ok(());
}
@ -587,15 +595,6 @@ impl ProcessManager {
child_pcb.set_process_group(&pg);
let mut guard = child_pcb.basic_mut();
guard.set_pgid(pg.pgid());
drop(guard);
//todo 这里应该解除注释但是每次一到这里就触发调度然后由于当前进程持有锁的数量不等于0导致panic
//
// if let Some(session) = pg.session() {
// guard.set_sid(session.sid());
// }
Ok(())
}
}

View File

@ -737,6 +737,9 @@ pub struct ProcessControlBlock {
/// 进程组
process_group: Mutex<Weak<ProcessGroup>>,
/// 进程的可执行文件路径
executable_path: RwLock<String>,
}
impl ProcessControlBlock {
@ -788,14 +791,7 @@ impl ProcessControlBlock {
(Self::generate_pid(), ppid, cwd, cred, tty)
};
let basic_info = ProcessBasicInfo::new(
Pgid::from(pid.into()),
ppid,
Sid::from(pid.into()),
name,
cwd,
None,
);
let basic_info = ProcessBasicInfo::new(ppid, name.clone(), cwd, None);
let preempt_count = AtomicUsize::new(0);
let flags = unsafe { LockFreeFlags::new(ProcessFlags::empty()) };
@ -833,6 +829,7 @@ impl ProcessControlBlock {
self_ref: Weak::new(),
restart_block: SpinLock::new(None),
process_group: Mutex::new(Weak::new()),
executable_path: RwLock::new(name),
};
pcb.sig_info.write().set_tty(tty);
@ -1030,6 +1027,14 @@ impl ProcessControlBlock {
self.cred.lock().clone()
}
pub fn set_execute_path(&self, path: String) {
*self.executable_path.write() = path;
}
pub fn execute_path(&self) -> String {
self.executable_path.read().clone()
}
/// 根据文件描述符序号获取socket对象的Arc指针
///
/// ## 参数
@ -1206,6 +1211,17 @@ impl ProcessControlBlock {
*self.restart_block.lock() = restart_block;
return Err(SystemError::ERESTART_RESTARTBLOCK);
}
pub fn parent_pcb(&self) -> Option<Arc<ProcessControlBlock>> {
self.parent_pcb.read().upgrade()
}
pub fn is_exited(&self) -> bool {
self.sched_info
.inner_lock_read_irqsave()
.state()
.is_exited()
}
}
impl Drop for ProcessControlBlock {
@ -1264,12 +1280,8 @@ impl ThreadInfo {
/// 这个结构体保存进程的基本信息,主要是那些不会随着进程的运行而经常改变的信息。
#[derive(Debug)]
pub struct ProcessBasicInfo {
/// 当前进程的进程组id
pgid: Pgid,
/// 当前进程的父进程的pid
ppid: Pid,
/// 当前进程所属会话id
sid: Sid,
/// 进程的名字
name: String,
@ -1286,18 +1298,14 @@ pub struct ProcessBasicInfo {
impl ProcessBasicInfo {
#[inline(never)]
pub fn new(
pgid: Pgid,
ppid: Pid,
sid: Sid,
name: String,
cwd: String,
user_vm: Option<Arc<AddressSpace>>,
) -> RwLock<Self> {
let fd_table = Arc::new(RwLock::new(FileDescriptorVec::new()));
return RwLock::new(Self {
pgid,
ppid,
sid,
name,
cwd,
user_vm,
@ -1305,26 +1313,10 @@ impl ProcessBasicInfo {
});
}
pub fn pgid(&self) -> Pgid {
return self.pgid;
}
pub fn set_pgid(&mut self, pgid: Pgid) {
self.pgid = pgid;
}
pub fn ppid(&self) -> Pid {
return self.ppid;
}
pub fn sid(&self) -> Sid {
return self.sid;
}
pub fn set_sid(&mut self, sid: Sid) {
self.sid = sid;
}
pub fn name(&self) -> &str {
return &self.name;
}

View File

@ -171,6 +171,29 @@ impl ProcessManager {
}
}
}
// 参考 https://code.dragonos.org.cn/xref/linux-6.6.21/kernel/exit.c#345
pub fn is_current_pgrp_orphaned() -> bool {
let current_pcb = ProcessManager::current_pcb();
let sid = current_pcb.sid();
let process_group = current_pcb.process_group();
if let Some(pg) = process_group {
for process in pg.process_group_inner.lock().processes.values() {
if let Some(real_parent) = process.real_parent_pcb.read().clone().upgrade() {
//todo 添加判断: 1.是否被忽略 2.是否已经退出(线程组是否为空)
if real_parent.pid == Pid(1) || process.is_exited() {
log::debug!("is_current_pgrp_orphaned: real_parent is init or exited");
continue;
}
let real_parent_pg = real_parent.process_group().unwrap();
if real_parent_pg.pgid() != pg.pgid() && real_parent_pg.sid() == sid {
return false;
}
}
}
}
true
}
}
impl ProcessControlBlock {

View File

@ -215,6 +215,6 @@ impl ProcessControlBlock {
if let Some(session) = self.session() {
return session.sid();
}
return Sid::new(0);
return Sid::new(1);
}
}

View File

@ -139,15 +139,17 @@ impl Syscall {
.basic_mut()
.set_name(ProcessControlBlock::generate_name(&path, &argv));
Self::do_execve(path, argv, envp, frame)?;
Self::do_execve(path.clone(), argv, envp, frame)?;
let pcb = ProcessManager::current_pcb();
// 关闭设置了O_CLOEXEC的文件描述符
let fd_table = ProcessManager::current_pcb().fd_table();
let fd_table = pcb.fd_table();
fd_table.write().close_on_exec();
// debug!(
// "after execve: strong count: {}",
// Arc::strong_count(&ProcessManager::current_pcb())
// );
pcb.set_execute_path(path);
return Ok(());
}
@ -311,6 +313,8 @@ impl Syscall {
pub fn setsid() -> Result<usize, SystemError> {
let pcb = ProcessManager::current_pcb();
let session = pcb.go_to_new_session()?;
let mut guard = pcb.sig_info_mut();
guard.set_tty(None);
Ok(session.sid().into())
}

View File

@ -1236,6 +1236,10 @@ impl Syscall {
SYS_SETRLIMIT => Ok(0),
SYS_RESTART_SYSCALL => Self::restart_syscall(),
SYS_RT_SIGPENDING => Self::rt_sigpending(args[0], args[1]),
SYS_RT_SIGTIMEDWAIT => {
log::warn!("SYS_RT_SIGTIMEDWAIT has not yet been implemented");
Ok(0)
}
_ => panic!("Unsupported syscall ID: {}", syscall_num),
};

3
user/apps/busybox/.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
build/
busybox-1.35.0.tar.bz2
busybox-1.35.0.tar.bz2.md5sum

View File

@ -0,0 +1,76 @@
ARCH ?= x86_64
busybox_version := 1.35.0
busybox_tarball := busybox-$(busybox_version).tar.bz2
busybox_tarball_path := $(busybox_tarball)
build_dir := build/$(ARCH)
busybox_dir := $(build_dir)/busybox-$(busybox_version)
prefix := $(ARCH)-linux-musl-
bin := build/$(ARCH)/busybox
# 特殊架构处理
ifeq ($(ARCH), mipsel)
prefix := mipsel-linux-musln32-
endif
cc := $(prefix)gcc
strip := $(prefix)strip
# 下载 busybox 的 md5sum 文件
$(busybox_tarball_path).md5sum:
wget https://mirrors.dragonos.org.cn/pub/third_party/busybox/$(busybox_tarball).md5sum
# 下载源码
$(busybox_tarball_path): $(busybox_tarball_path).md5sum
@if [ ! -f $@ ] || ! md5sum -c $(busybox_tarball_path).md5sum; then \
echo "Downloading $@..."; \
wget https://mirrors.dragonos.org.cn/pub/third_party/busybox/$(busybox_tarball); \
fi
# 解压源码包
$(busybox_dir): $(busybox_tarball_path)
mkdir -p $(build_dir)
tar -xjf $< -C $(build_dir)
# 配置和编译
$(bin): $(busybox_dir)
@# 应用必要补丁和配置调整
cd $(busybox_dir) && \
make defconfig && \
sed -i '/CONFIG_STATIC/s/.*/CONFIG_STATIC=y/' .config && \
sed -i '/CONFIG_PIE/d' .config && \
sed -i '/CONFIG_FEATURE_EDITING/s/=y/=n/' .config && \
sed -i '/CONFIG_HUSH/s/=y/=n/' .config && \
sed -i '/CONFIG_NOMMU/s/=y/=n/' .config && \
echo "CONFIG_CROSS_COMPILER_PREFIX=\"$(prefix)\"" >> .config && \
echo "CONFIG_FEATURE_STATIC=y" >> .config && \
echo "CONFIG_STATIC_LIBGCC=y" >> .config && \
echo "CONFIG_ASH=y" >> .config && \
echo "CONFIG_ASH_READ_PROFILE=y" >> .config && \
echo "CONFIG_FEATURE_EDITING=y" >> .config && \
echo "CONFIG_HUSH=y" >> .config
@# 执行编译
cd $(busybox_dir) && \
KCONFIG_NOTIMESTAMP=1 make CC="$(cc)" CFLAGS_EXTRA="-static -Os" LDFLAGS="--static" -j$(nproc)
@# 处理编译输出
mkdir -p $(dir $(bin))
cp $(busybox_dir)/busybox $(bin)
$(strip) $(bin)
.PHONY: all clean menuconfig
all: $(bin)
install: all
mv $(bin) $(DADK_CURRENT_BUILD_DIR)/busybox
# 交互式配置菜单
menuconfig: $(busybox_dir)
cd $(busybox_dir) && make menuconfig
clean:
rm -rf build/
distclean: clean
rm -f $(busybox_tarball_path) $(busybox_tarball_path).md5sum

View File

@ -0,0 +1,36 @@
# 用户程序名称
name = "busybox"
# 版本号
version = "1.35.0"
# 用户程序描述信息
description = ""
# 可选是否只构建一次如果为trueDADK会在构建成功后将构建结果缓存起来下次构建时直接使用缓存的构建结果
build-once = false
# (可选) 是否只安装一次如果为trueDADK会在安装成功后不再重复安装
install-once = false
# 目标架构
# 可选值:"x86_64", "aarch64", "riscv64"
target-arch = ["x86_64"]
# 任务源
[task-source]
# 构建类型
# 可选值:"build-from_source", "install-from-prebuilt"
type = "build-from-source"
# 构建来源
# "build_from_source" 可选值:"git", "local", "archive"
# "install_from_prebuilt" 可选值:"local", "archive"
source = "local"
# 路径或URL
source-path = "user/apps/busybox"
# 构建相关信息
[build]
# (可选)构建命令
build-command = "make install"
# 安装相关信息
[install]
# 可选安装到DragonOS的路径
in-dragonos-path = "/bin"
# 清除相关信息
[clean]
# (可选)清除命令
clean-command = "make distclean"

View File

@ -47,3 +47,4 @@ clean-command = "make clean"
# 环境变量
# 注意:因为没有环境变量,所以这里不包含[[envs]]部分

4
user/sysconfig/etc/init.d/rcS Executable file
View File

@ -0,0 +1,4 @@
#!/bin/sh
echo "[rcS] Running system init script..."
/bin/about.elf
/bin/busybox stty erase 127

View File

@ -0,0 +1,27 @@
# /etc/inittab
::sysinit:busybox sh /etc/init.d/rcS # 系统初始化脚本
::askfirst:-/bin/busybox sh --login
# /etc/inittab - 根据源码弄出来的默认inittab
# https://code.dragonos.org.cn/xref/busybox-1.35.0/init/init.c#679
# # 系统初始化脚本
# ::sysinit:/etc/init.d/rcS
# # askfirst shell
# ::askfirst:-/bin/sh
# tty2::askfirst:-/bin/sh
# tty3::askfirst:-/bin/sh
# tty4::askfirst:-/bin/sh
# # Ctrl-Alt-Del 重启
# ::ctrlaltdel:/sbin/reboot
# # 系统关闭或重启前的动作
# ::shutdown:/bin/umount -a -r
# ::shutdown:/sbin/swapoff -a
# # 收到 QUIT 信号时重启 init
# ::restart:/sbin/init

View File

@ -0,0 +1,2 @@
#!/bin/sh
export PATH=/bin:/usr/bin:/usr/local/bin

View File

@ -6,3 +6,5 @@ Type=simple
ExecStart=/bin/NovaShell
Restart=always
ExecStartPre=-/bin/about.elf
ExecStartPre=/bin/busybox stty erase 127
Environment=PATH=/bin:/usr/bin:/usr/local/bin