diff --git a/.vscode/settings.json b/.vscode/settings.json index e422ff23..dddf29cd 100644 --- a/.vscode/settings.json +++ b/.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", diff --git a/docs/community/contact/index.rst b/docs/community/contact/index.rst index 15eb596a..d086423b 100644 --- a/docs/community/contact/index.rst +++ b/docs/community/contact/index.rst @@ -30,4 +30,5 @@ DragonOS是一个开源项目,我们欢迎任何形式的赞助和捐赠,您 财务及捐赠信息公开 ------------------------- -DragonOS社区的捐赠信息将按年进行公开。赞助商、赞助者信息将在收到赞助后,15天内进行公开。 \ No newline at end of file +DragonOS社区的捐赠信息将按年进行公开。赞助商、赞助者信息将在收到赞助后,15天内进行公开。 + diff --git a/kernel/src/arch/riscv64/ipc/signal.rs b/kernel/src/arch/riscv64/ipc/signal.rs index 92d280d5..0c049bb5 100644 --- a/kernel/src/arch/riscv64/ipc/signal.rs +++ b/kernel/src/arch/riscv64/ipc/signal.rs @@ -93,11 +93,14 @@ impl From for Signal { } } -impl Into for Signal { - fn into(self) -> SigSet { - self.into_sigset() +impl From for SigSet { + fn from(val: Signal) -> Self { + SigSet { + bits: (1 << (val as usize - 1) as u64), + } } } + impl Signal { /// 判断一个数字是否为可用的信号 #[inline] diff --git a/kernel/src/driver/block/virtio_blk.rs b/kernel/src/driver/block/virtio_blk.rs index 133ee11d..a7cc2ca2 100644 --- a/kernel/src/driver/block/virtio_blk.rs +++ b/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, } +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 {} diff --git a/kernel/src/driver/char/virtio_console.rs b/kernel/src/driver/char/virtio_console.rs index 46362288..12ac011c 100644 --- a/kernel/src/driver/char/virtio_console.rs +++ b/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) -> Option> { // 设置中断 diff --git a/kernel/src/driver/net/virtio_net.rs b/kernel/src/driver/net/virtio_net.rs index 32e7ddad..b2b226db 100644 --- a/kernel/src/driver/net/virtio_net.rs +++ b/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 { } /// 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() } } diff --git a/kernel/src/driver/tty/termios.rs b/kernel/src/driver/tty/termios.rs index 0a0ca4bb..919ec84c 100644 --- a/kernel/src/driver/tty/termios.rs +++ b/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 { + 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 { + 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 { + 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)] diff --git a/kernel/src/driver/tty/tty_core.rs b/kernel/src/driver/tty/tty_core.rs index b33310b2..aee86942 100644 --- a/kernel/src/driver/tty/tty_core.rs +++ b/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, + /// 当前会话的SId + pub session: Option, /// 前台进程组id - pub pgid: Option, + pub pgid: Option, /// packet模式下使用,目前未用到 pub pktstatus: TtyPacketStatus, pub packet: bool, } +impl TtyContorlInfo { + pub fn set_info_by_pcb(&mut self, pcb: Arc) { + self.session = Some(pcb.sid()); + self.pgid = Some(pcb.pgid()); + } +} + #[derive(Debug, Default)] pub struct TtyFlowState { /// 表示流控是否被停止 diff --git a/kernel/src/driver/tty/tty_job_control.rs b/kernel/src/driver/tty/tty_job_control.rs index 7d07ebd3..03980650 100644 --- a/kernel/src/driver/tty/tty_job_control.rs +++ b/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) { 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, cmd: u32, arg: usize) -> Result { + pub fn job_ctrl_ioctl( + real_tty: Arc, + cmd: u32, + arg: usize, + ) -> Result { 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::(), - core::mem::size_of::(), - true, - )?; - - let pgrp = user_reader.read_one_from_user::(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(¤t.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(¤t.sig_info_irqsave().tty().unwrap(), &tty) - { - return Err(SystemError::ENOTTY); - } - - let mut user_writer = UserBufferWriter::new( - VirtAddr::new(arg).as_ptr::(), - core::mem::size_of::(), - 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) -> Result { + 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, arg: usize) -> Result { + // log::debug!("job_ctrl_ioctl: TIOCGPGRP"); + let current = ProcessManager::current_pcb(); + if current.sig_info_irqsave().tty().is_some() + && !Arc::ptr_eq(¤t.sig_info_irqsave().tty().unwrap(), &real_tty) + { + return Err(SystemError::ENOTTY); + } + + let mut user_writer = UserBufferWriter::new( + VirtAddr::new(arg).as_ptr::(), + core::mem::size_of::(), + 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, arg: usize) -> Result { + // log::debug!("job_ctrl_ioctl: TIOCGSID"); + let current = ProcessManager::current_pcb(); + if current.sig_info_irqsave().tty().is_some() + && !Arc::ptr_eq(¤t.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::(), + core::mem::size_of::(), + true, + )?; + user_writer.copy_one_to_user(&(sid.data() as i32), 0)?; + + return Ok(0); + } + + fn tiocspgrp(real_tty: Arc, arg: usize) -> Result { + // 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::(), + core::mem::size_of::(), + true, + )?; + + let pgrp = user_reader.read_one_from_user::(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( + ¤t.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(), ¤t.session().unwrap()) { + return Err(SystemError::EPERM); + } + + ctrl.pgid = Some(Pid::from(*pgrp as usize)); + + return Ok(0); + } } diff --git a/kernel/src/driver/tty/tty_ldisc/ntty.rs b/kernel/src/driver/tty/tty_ldisc/ntty.rs index 90afe5f7..6b758931 100644 --- a/kernel/src/driver/tty/tty_ldisc/ntty.rs +++ b/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) { diff --git a/kernel/src/filesystem/procfs/mod.rs b/kernel/src/filesystem/procfs/mod.rs index 3c131032..07f0d36f 100644 --- a/kernel/src/filesystem/procfs/mod.rs +++ b/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 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::()) as i64); } + // 打开 exe 文件 + fn open_exe(&self, _pdata: &mut ProcfsFilePrivateData) -> Result { + // 这个文件是一个软链接,直接返回0即可 + return Ok(0); + } + + // 读取exe文件 + fn read_link(&self, buf: &mut [u8]) -> Result { + // 判断是否有记录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::() + .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 = pid_dir.create( + let status_binding: Arc = 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::() .unwrap(); status_file.0.lock().fdata.pid = pid; status_file.0.lock().fdata.ftype = ProcFileType::ProcStatus; + // exe文件 + let exe_binding: Arc = pid_dir.create_with_data( + "exe", + FileType::SymLink, + ModeType::from_bits_truncate(0o444), + 0, + )?; + let exe_file = exe_binding + .as_any_ref() + .downcast_ref::() + .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 = 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 => (), }; diff --git a/kernel/src/init/initial_kthread.rs b/kernel/src/init/initial_kthread.rs index 66839905..64538258 100644 --- a/kernel/src/init/initial_kthread.rs +++ b/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 { diff --git a/kernel/src/process/fork.rs b/kernel/src/process/fork.rs index a364b8b8..431e6432 100644 --- a/kernel/src/process/fork.rs +++ b/kernel/src/process/fork.rs @@ -310,13 +310,21 @@ impl ProcessManager { current_pcb: &Arc, new_pcb: &Arc, ) -> 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(()) } } diff --git a/kernel/src/process/mod.rs b/kernel/src/process/mod.rs index 4dd61252..1d568abe 100644 --- a/kernel/src/process/mod.rs +++ b/kernel/src/process/mod.rs @@ -737,6 +737,9 @@ pub struct ProcessControlBlock { /// 进程组 process_group: Mutex>, + + /// 进程的可执行文件路径 + executable_path: RwLock, } 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> { + 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>, ) -> RwLock { 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; } diff --git a/kernel/src/process/process_group.rs b/kernel/src/process/process_group.rs index 1ca9c9bd..751c8ec4 100644 --- a/kernel/src/process/process_group.rs +++ b/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 { diff --git a/kernel/src/process/session.rs b/kernel/src/process/session.rs index d86bebf2..45ac06b4 100644 --- a/kernel/src/process/session.rs +++ b/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); } } diff --git a/kernel/src/process/syscall.rs b/kernel/src/process/syscall.rs index 5d5d9fa6..b464e66f 100644 --- a/kernel/src/process/syscall.rs +++ b/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 { 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()) } diff --git a/kernel/src/syscall/mod.rs b/kernel/src/syscall/mod.rs index 9ee5f882..79c349c0 100644 --- a/kernel/src/syscall/mod.rs +++ b/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), }; diff --git a/user/apps/busybox/.gitignore b/user/apps/busybox/.gitignore new file mode 100644 index 00000000..879a99e1 --- /dev/null +++ b/user/apps/busybox/.gitignore @@ -0,0 +1,3 @@ +build/ +busybox-1.35.0.tar.bz2 +busybox-1.35.0.tar.bz2.md5sum \ No newline at end of file diff --git a/user/apps/busybox/Makefile b/user/apps/busybox/Makefile new file mode 100644 index 00000000..d7bbeabb --- /dev/null +++ b/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 diff --git a/user/dadk/config/busybox_1_35_0.toml b/user/dadk/config/busybox_1_35_0.toml new file mode 100644 index 00000000..39253931 --- /dev/null +++ b/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" diff --git a/user/dadk/config/dragon_reach-0.1.0.toml b/user/dadk/config/dragon_reach-0.1.0.toml index fcefd08e..59fd0b31 100644 --- a/user/dadk/config/dragon_reach-0.1.0.toml +++ b/user/dadk/config/dragon_reach-0.1.0.toml @@ -47,3 +47,4 @@ clean-command = "make clean" # 环境变量 # 注意:因为没有环境变量,所以这里不包含[[envs]]部分 + diff --git a/user/sysconfig/etc/init.d/rcS b/user/sysconfig/etc/init.d/rcS new file mode 100755 index 00000000..03ac8778 --- /dev/null +++ b/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 diff --git a/user/sysconfig/etc/inittab b/user/sysconfig/etc/inittab new file mode 100644 index 00000000..bdd68925 --- /dev/null +++ b/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 diff --git a/user/sysconfig/etc/profile b/user/sysconfig/etc/profile new file mode 100644 index 00000000..272156e9 --- /dev/null +++ b/user/sysconfig/etc/profile @@ -0,0 +1,2 @@ +#!/bin/sh +export PATH=/bin:/usr/bin:/usr/local/bin \ No newline at end of file diff --git a/user/sysconfig/etc/reach/system/shell.service b/user/sysconfig/etc/reach/system/shell.service index 75bd9a40..c11de496 100644 --- a/user/sysconfig/etc/reach/system/shell.service +++ b/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 \ No newline at end of file