Ver Fonte

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>
火花 há 9 horas atrás
pai
commit
bc9bb9607f

+ 0 - 1
.vscode/settings.json

@@ -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",

+ 2 - 1
docs/community/contact/index.rst

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

+ 6 - 3
kernel/src/arch/riscv64/ipc/signal.rs

@@ -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]

+ 13 - 2
kernel/src/driver/block/virtio_blk.rs

@@ -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 {}
 

+ 17 - 1
kernel/src/driver/char/virtio_console.rs

@@ -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>> {
         // 设置中断

+ 10 - 3
kernel/src/driver/net/virtio_net.rs

@@ -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()
     }
 }
 

+ 60 - 7
kernel/src/driver/tty/termios.rs

@@ -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)]

+ 11 - 4
kernel/src/driver/tty/tty_core.rs

@@ -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 {
     /// 表示流控是否被停止

+ 142 - 73
kernel/src/driver/tty/tty_job_control.rs

@@ -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);
-                }
+            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);
+        }
 
-                ctrl.pgid = Some(Pid::from(*pgrp as usize));
+        if !current.is_session_leader() || current.sig_info_irqsave().tty().is_some() {
+            return Err(SystemError::EPERM);
+        }
 
-                return Ok(0);
+        //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);
+        }
 
-            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)
-                {
+        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);
                 }
-
-                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);
+                return Err(e);
             }
+        };
 
-            _ => {
-                return Err(SystemError::ENOIOCTLCMD);
-            }
+        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);
     }
 }

+ 2 - 2
kernel/src/driver/tty/tty_ldisc/ntty.rs

@@ -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) {

+ 61 - 2
kernel/src/filesystem/procfs/mod.rs

@@ -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 => (),
         };

+ 1 - 1
kernel/src/init/initial_kthread.rs

@@ -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 {

+ 13 - 14
kernel/src/process/fork.rs

@@ -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(())
     }
 }

+ 24 - 32
kernel/src/process/mod.rs

@@ -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;
     }

+ 23 - 0
kernel/src/process/process_group.rs

@@ -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 {

+ 1 - 1
kernel/src/process/session.rs

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

+ 6 - 2
kernel/src/process/syscall.rs

@@ -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())
     }
 

+ 4 - 0
kernel/src/syscall/mod.rs

@@ -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 - 0
user/apps/busybox/.gitignore

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

+ 76 - 0
user/apps/busybox/Makefile

@@ -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

+ 36 - 0
user/dadk/config/busybox_1_35_0.toml

@@ -0,0 +1,36 @@
+# 用户程序名称
+name = "busybox"
+# 版本号
+version = "1.35.0"
+# 用户程序描述信息
+description = ""
+# (可选)是否只构建一次,如果为true,DADK会在构建成功后,将构建结果缓存起来,下次构建时,直接使用缓存的构建结果
+build-once = false
+#  (可选) 是否只安装一次,如果为true,DADK会在安装成功后,不再重复安装
+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"

+ 1 - 0
user/dadk/config/dragon_reach-0.1.0.toml

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

+ 4 - 0
user/sysconfig/etc/init.d/rcS

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

+ 27 - 0
user/sysconfig/etc/inittab

@@ -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

+ 2 - 0
user/sysconfig/etc/profile

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

+ 2 - 0
user/sysconfig/etc/reach/system/shell.service

@@ -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