瀏覽代碼

Merge branch 'master' into feat-dynamic-link

longjin 12 小時之前
父節點
當前提交
9ec4b6aa2c
共有 65 個文件被更改,包括 1418 次插入297 次删除
  1. 1 1
      .github/workflows/publish-dragonos-docker-image.yml
  2. 1 0
      .github/workflows/sync-to-cnb.yml
  3. 0 1
      .vscode/settings.json
  4. 2 1
      docs/community/contact/index.rst
  5. 4 3
      kernel/Cargo.lock
  6. 1 1
      kernel/Cargo.toml
  7. 3 0
      kernel/crates/asm_macros/src/lib.rs
  8. 280 0
      kernel/crates/asm_macros/src/loongarch64/context.rs
  9. 1 0
      kernel/crates/asm_macros/src/loongarch64/mod.rs
  10. 42 0
      kernel/src/arch/loongarch64/asm/mod.rs
  11. 4 1
      kernel/src/arch/loongarch64/cpu.rs
  12. 1 0
      kernel/src/arch/loongarch64/filesystem/mod.rs
  13. 1 0
      kernel/src/arch/loongarch64/filesystem/stat.rs
  14. 11 8
      kernel/src/arch/loongarch64/init/boot.rs
  15. 4 0
      kernel/src/arch/loongarch64/init/mod.rs
  16. 132 0
      kernel/src/arch/loongarch64/interrupt/entry.rs
  17. 87 0
      kernel/src/arch/loongarch64/interrupt/handle.rs
  18. 2 0
      kernel/src/arch/loongarch64/interrupt/mod.rs
  19. 1 2
      kernel/src/arch/loongarch64/link.ld
  20. 1 0
      kernel/src/arch/loongarch64/mod.rs
  21. 1 0
      kernel/src/arch/riscv64/filesystem/mod.rs
  22. 1 0
      kernel/src/arch/riscv64/filesystem/stat.rs
  23. 6 3
      kernel/src/arch/riscv64/ipc/signal.rs
  24. 1 0
      kernel/src/arch/riscv64/mod.rs
  25. 5 1
      kernel/src/arch/x86_64/vm/vmx/mod.rs
  26. 13 2
      kernel/src/driver/block/virtio_blk.rs
  27. 17 1
      kernel/src/driver/char/virtio_console.rs
  28. 10 3
      kernel/src/driver/net/virtio_net.rs
  29. 60 7
      kernel/src/driver/tty/termios.rs
  30. 11 4
      kernel/src/driver/tty/tty_core.rs
  31. 142 73
      kernel/src/driver/tty/tty_job_control.rs
  32. 2 2
      kernel/src/driver/tty/tty_ldisc/ntty.rs
  33. 4 7
      kernel/src/driver/tty/tty_port.rs
  34. 2 2
      kernel/src/filesystem/eventfd.rs
  35. 5 7
      kernel/src/filesystem/poll.rs
  36. 61 2
      kernel/src/filesystem/procfs/mod.rs
  37. 92 0
      kernel/src/filesystem/vfs/stat.rs
  38. 2 0
      kernel/src/filesystem/vfs/syscall.rs
  39. 3 3
      kernel/src/init/init.rs
  40. 1 1
      kernel/src/init/initial_kthread.rs
  41. 2 2
      kernel/src/ipc/pipe.rs
  42. 50 14
      kernel/src/namespaces/mnt_namespace.rs
  43. 3 3
      kernel/src/namespaces/mod.rs
  44. 6 5
      kernel/src/namespaces/namespace.rs
  45. 28 43
      kernel/src/net/event_poll/mod.rs
  46. 1 1
      kernel/src/net/net_core.rs
  47. 1 1
      kernel/src/perf/mod.rs
  48. 3 5
      kernel/src/process/exec.rs
  49. 35 13
      kernel/src/process/fork.rs
  50. 37 37
      kernel/src/process/mod.rs
  51. 23 0
      kernel/src/process/process_group.rs
  52. 1 1
      kernel/src/process/session.rs
  53. 6 2
      kernel/src/process/syscall.rs
  54. 4 0
      kernel/src/syscall/mod.rs
  55. 4 3
      tools/bootstrap.sh
  56. 26 19
      tools/run-qemu.sh
  57. 3 0
      user/apps/busybox/.gitignore
  58. 76 0
      user/apps/busybox/Makefile
  59. 19 12
      user/apps/test_epoll/main.c
  60. 36 0
      user/dadk/config/busybox_1_35_0.toml
  61. 1 0
      user/dadk/config/dragon_reach-0.1.0.toml
  62. 4 0
      user/sysconfig/etc/init.d/rcS
  63. 27 0
      user/sysconfig/etc/inittab
  64. 2 0
      user/sysconfig/etc/profile
  65. 2 0
      user/sysconfig/etc/reach/system/shell.service

+ 1 - 1
.github/workflows/publish-dragonos-docker-image.yml

@@ -35,5 +35,5 @@ jobs:
           context: "{{defaultContext}}:tools"
           file: Dockerfile
           platforms: linux/amd64
-          push: true
+          push: ${{ github.repository == 'DragonOS-Community/DragonOS' }}
           tags: dragonos/dragonos-dev:${{ steps.fetch-versions.outputs.build_container_version }}

+ 1 - 0
.github/workflows/sync-to-cnb.yml

@@ -3,6 +3,7 @@ on: [push]
 
 jobs:
   sync:
+    if: github.repository == 'DragonOS-Community/DragonOS'
     runs-on: ubuntu-latest
     steps:
       - uses: actions/checkout@v3

+ 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天内进行公开。
+

+ 4 - 3
kernel/Cargo.lock

@@ -938,11 +938,12 @@ checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94"
 
 [[package]]
 name = "loongArch64"
-version = "0.2.4"
-source = "git+https://github.com/fslongjin/loongArch64?rev=7af150e#7af150e01e7ce3139f519578751c95bbdaf4fb4d"
+version = "0.2.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7c9f0d275c70310e2a9d2fc23250c5ac826a73fa828a5f256401f85c5c554283"
 dependencies = [
  "bit_field",
- "bitflags 1.3.2",
+ "bitflags 2.9.0",
 ]
 
 [[package]]

+ 1 - 1
kernel/Cargo.toml

@@ -98,7 +98,7 @@ sbi-rt = { version = "=0.0.3", features = ["legacy"] }
 
 # target为loongarch64时,使用下面的依赖
 [target.'cfg(target_arch = "loongarch64")'.dependencies]
-loongArch64 = { git = "https://github.com/fslongjin/loongArch64", rev = "7af150e" }
+loongArch64 = "=0.2.5"
 
 # 由于unwinding库不支持loongarch64架构,因此需要排除该依赖项
 [target.'cfg(not(target_arch = "loongarch64"))'.dependencies]

+ 3 - 0
kernel/crates/asm_macros/src/lib.rs

@@ -5,3 +5,6 @@ pub mod x86_64;
 
 #[cfg(target_arch = "riscv64")]
 pub mod riscv64;
+
+#[cfg(target_arch = "loongarch64")]
+pub mod loongarch64;

+ 280 - 0
kernel/crates/asm_macros/src/loongarch64/context.rs

@@ -0,0 +1,280 @@
+/// https://code.dragonos.org.cn/xref/linux-6.6.21/arch/loongarch/include/asm/stackframe.h#48
+#[macro_export]
+macro_rules! backup_t0t1 {
+    () => {
+        concat!(
+            "
+            csrwr $t0, {exception_ks0}
+            csrwr $t1, {exception_ks1}
+        "
+        )
+    };
+}
+
+/// https://code.dragonos.org.cn/xref/linux-6.6.21/arch/loongarch/include/asm/stackframe.h#53
+#[macro_export]
+macro_rules! reload_t0t1 {
+    () => {
+        concat!(
+            "
+            csrrd $t0, {exception_ks0}
+            csrrd $t1, {exception_ks1}
+        "
+        )
+    };
+}
+
+/// get_saved_sp returns the SP for the current CPU by looking in the
+/// kernelsp array for it. It stores the current sp in t0 and loads the
+/// new value in sp.
+///
+/// 参考 https://code.dragonos.org.cn/xref/linux-6.6.21/arch/loongarch/include/asm/stackframe.h?r=&mo=2487&fi=119#88
+#[macro_export]
+macro_rules! get_saved_sp {
+    () => {
+        concat!(
+            "
+            la.abs $t1, KERNEL_SP
+            csrrd $t0, {percpu_base_ks}
+            add.d $t1, $t1, $t0
+
+            move $t0, $sp
+            ld.d $sp, $t1, 0
+        "
+        )
+    };
+}
+
+/// 参考 https://code.dragonos.org.cn/xref/linux-6.6.21/arch/loongarch/include/asm/stackframe.h?r=&mo=2487&fi=119#101
+#[macro_export]
+macro_rules! set_saved_sp {
+    ($stackp:tt, $temp:tt) => {
+        concat!(
+            "la.pcrel ",
+            stringify!($temp),
+            ", KERNEL_SP\n",
+            "add.d ",
+            stringify!($temp),
+            ", ",
+            stringify!($temp),
+            ", $r21\n",
+            "st.d ",
+            stringify!($stackp),
+            ", ",
+            stringify!($temp),
+            ", 0\n"
+        )
+    };
+}
+
+/// https://code.dragonos.org.cn/xref/linux-6.6.21/arch/loongarch/include/asm/stackframe.h#109
+#[macro_export]
+macro_rules! save_some {
+    () => {
+        concat!(
+            "
+            csrrd $t1, {loongarch_csr_prmd}
+            andi	$t1, $t1, 0x3
+            move $t0, $sp
+            beqz $t1, 3f
+
+        ",
+            get_saved_sp!(),
+        "
+        3:
+            addi.d $sp, $sp, -{pt_size}
+        
+
+            st.d $t0, $sp, {off_usp} // 等价于 cfi_st	t0, PT_R3, docfi=0
+
+            st.d $zero, $sp, {off_r0}
+            csrrd $t0, {loongarch_csr_prmd}
+            st.d $t0, $sp, {off_csr_prmd}
+            csrrd $t0, {loongarch_csr_crmd}
+            st.d $t0, $sp, {off_csr_crmd}
+            csrrd $t0, {loongarch_csr_euen}
+            st.d $t0, $sp, {off_csr_euen}
+            csrrd $t0, {loongarch_csr_ecfg}
+            st.d $t0, $sp, {off_csr_ecfg}
+            csrrd $t0, {loongarch_csr_estat}
+            st.d $t0, $sp, {off_csr_estat}
+
+            st.d $ra, $sp, {off_ra}
+            st.d $a0, $sp, {off_a0}
+            st.d $a1, $sp, {off_a1}
+            st.d $a2, $sp, {off_a2}
+            st.d $a3, $sp, {off_a3}
+            st.d $a4, $sp, {off_a4}
+            st.d $a5, $sp, {off_a5}
+            st.d $a6, $sp, {off_a6}
+            st.d $a7, $sp, {off_a7}
+
+            csrrd $ra, {loongarch_csr_era}
+            st.d $ra, $sp, {off_csr_era}
+
+            st.d $tp, $sp, {off_tp}
+            st.d $fp, $sp, {off_fp}
+
+            /* Set thread_info if we're coming from user mode */
+            csrrd $t0, {loongarch_csr_prmd}
+            andi $t0, $t0, 0x3
+            beqz $t0, 9f
+
+            li.d $tp, ~{thread_mask}
+            and $tp, $tp, $sp
+            st.d $r21, $sp, {off_r21}
+            csrrd $r21, {percpu_base_ks}
+            9:
+        "
+        )
+    };
+}
+
+/// 参考 https://code.dragonos.org.cn/xref/linux-6.6.21/arch/loongarch/include/asm/stackframe.h#197
+#[macro_export]
+macro_rules! restore_some {
+    () => {
+        concat!(
+            "
+            ld.d $a0, $sp, {off_csr_prmd}
+            // extract pplv bit
+            andi $a0, $a0, 0x3
+            beqz $a0, 4f
+            ld.d $r21, $sp, {off_r21}
+
+            4:
+            ld.d $a0, $sp, {off_csr_era}
+            csrwr $a0, {loongarch_csr_era}
+            ld.d $a0, $sp, {off_csr_prmd}
+            csrwr $a0, {loongarch_csr_prmd}
+            ld.d $ra, $sp, {off_ra}
+            ld.d $a0, $sp, {off_a0}
+            ld.d $a1, $sp, {off_a1}
+            ld.d $a2, $sp, {off_a2}
+            ld.d $a3, $sp, {off_a3}
+            ld.d $a4, $sp, {off_a4}
+            ld.d $a5, $sp, {off_a5}
+            ld.d $a6, $sp, {off_a6}
+            ld.d $a7, $sp, {off_a7}
+            ld.d $tp, $sp, {off_tp}
+            ld.d $fp, $sp, {off_fp}
+            "
+        )
+    };
+}
+
+/// 参考 https://code.dragonos.org.cn/xref/linux-6.6.21/arch/loongarch/include/asm/stackframe.h#58
+#[macro_export]
+macro_rules! save_temp {
+    () => {
+        concat!(
+            reload_t0t1!(),
+            "
+            st.d $t0, $sp, {off_t0}
+            st.d $t1, $sp, {off_t1}
+            st.d $t2, $sp, {off_t2}
+            st.d $t3, $sp, {off_t3}
+            st.d $t4, $sp, {off_t4}
+            st.d $t5, $sp, {off_t5}
+            st.d $t6, $sp, {off_t6}
+            st.d $t7, $sp, {off_t7}
+            st.d $t8, $sp, {off_t8}
+            "
+        )
+    };
+}
+
+/// 参考 https://code.dragonos.org.cn/xref/linux-6.6.21/arch/loongarch/include/asm/stackframe.h#173
+#[macro_export]
+macro_rules! restore_temp {
+    () => {
+        concat!(
+            reload_t0t1!(),
+            "
+            ld.d $t0, $sp, {off_t0}
+            ld.d $t1, $sp, {off_t1}
+            ld.d $t2, $sp, {off_t2}
+            ld.d $t3, $sp, {off_t3}
+            ld.d $t4, $sp, {off_t4}
+            ld.d $t5, $sp, {off_t5}
+            ld.d $t6, $sp, {off_t6}
+            ld.d $t7, $sp, {off_t7}
+            ld.d $t8, $sp, {off_t8}
+            "
+        )
+    };
+}
+
+/// 参考 https://code.dragonos.org.cn/xref/linux-6.6.21/arch/loongarch/include/asm/stackframe.h#71
+#[macro_export]
+macro_rules! save_static {
+    () => {
+        concat!(
+            "
+            st.d $s0, $sp, {off_s0}
+            st.d $s1, $sp, {off_s1}
+            st.d $s2, $sp, {off_s2}
+            st.d $s3, $sp, {off_s3}
+            st.d $s4, $sp, {off_s4}
+            st.d $s5, $sp, {off_s5}
+            st.d $s6, $sp, {off_s6}
+            st.d $s7, $sp, {off_s7}
+            st.d $s8, $sp, {off_s8}
+            "
+        )
+    };
+}
+
+/// 参考 https://code.dragonos.org.cn/xref/linux-6.6.21/arch/loongarch/include/asm/stackframe.h#185
+#[macro_export]
+macro_rules! restore_static {
+    () => {
+        concat!(
+            "
+            ld.d $s0, $sp, {off_s0}
+            ld.d $s1, $sp, {off_s1}
+            ld.d $s2, $sp, {off_s2}
+            ld.d $s3, $sp, {off_s3}
+            ld.d $s4, $sp, {off_s4}
+            ld.d $s5, $sp, {off_s5}
+            ld.d $s6, $sp, {off_s6}
+            ld.d $s7, $sp, {off_s7}
+            ld.d $s8, $sp, {off_s8}
+            "
+        )
+    };
+}
+
+/// 参考 https://code.dragonos.org.cn/xref/linux-6.6.21/arch/loongarch/include/asm/stackframe.h#167
+#[macro_export]
+macro_rules! save_all {
+    () => {
+        concat!(save_some!(), "\n", save_temp!(), "\n", save_static!(),)
+    };
+}
+
+/// 参考 https://code.dragonos.org.cn/xref/linux-6.6.21/arch/loongarch/include/asm/stackframe.h#220
+#[macro_export]
+macro_rules! restore_sp_and_ret {
+    () => {
+        concat!(
+            "
+            ld.d $sp, $sp, {off_usp}
+            ertn
+            "
+        )
+    };
+}
+
+/// 参考 https://code.dragonos.org.cn/xref/linux-6.6.21/arch/loongarch/include/asm/stackframe.h#225
+#[macro_export]
+macro_rules! restore_all_and_ret {
+    () => {
+        concat!(
+            restore_static!(),
+            restore_temp!(),
+            restore_some!(),
+            restore_sp_and_ret!()
+        )
+    };
+}

+ 1 - 0
kernel/crates/asm_macros/src/loongarch64/mod.rs

@@ -0,0 +1 @@
+pub mod context;

+ 42 - 0
kernel/src/arch/loongarch64/asm/mod.rs

@@ -1,2 +1,44 @@
+use crate::process::KernelStack;
+
 pub mod bitops;
 pub mod boot;
+
+/* KSave registers */
+pub const LOONGARCH_CSR_KS0: usize = 0x30;
+pub const LOONGARCH_CSR_KS1: usize = 0x31;
+pub const LOONGARCH_CSR_KS2: usize = 0x32;
+pub const LOONGARCH_CSR_KS3: usize = 0x33;
+pub const LOONGARCH_CSR_KS4: usize = 0x34;
+pub const LOONGARCH_CSR_KS5: usize = 0x35;
+pub const LOONGARCH_CSR_KS6: usize = 0x36;
+pub const LOONGARCH_CSR_KS7: usize = 0x37;
+pub const LOONGARCH_CSR_KS8: usize = 0x38;
+
+/// Current mode info
+pub const LOONGARCH_CSR_CRMD: usize = 0x0;
+/// Prev-exception mode info
+pub const LOONGARCH_CSR_PRMD: usize = 0x1;
+
+/// Extended unit enable
+pub const LOONGARCH_CSR_EUEN: usize = 0x2;
+
+/// Exception config
+pub const LOONGARCH_CSR_ECFG: usize = 0x4;
+/// Exception status
+pub const LOONGARCH_CSR_ESTAT: usize = 0x5;
+
+/// Exception return address.
+pub const LOONGARCH_CSR_ERA: usize = 0x6;
+
+/// Bad virtual address.
+pub const LOONGARCH_CSR_BADV: usize = 0x7;
+
+/* Exception allocated KS0, KS1 and KS2 statically */
+pub const EXCEPTION_KS0: usize = LOONGARCH_CSR_KS0;
+pub const EXCEPTION_KS1: usize = LOONGARCH_CSR_KS1;
+
+/* Percpu-data base allocated KS3 statically */
+pub const PERCPU_BASE_KS: usize = LOONGARCH_CSR_KS3;
+pub const PERCPU_KSAVE_MASK: usize = 1 << 3;
+
+pub const _THREAD_MASK: usize = KernelStack::SIZE - 1;

+ 4 - 1
kernel/src/arch/loongarch64/cpu.rs

@@ -1,4 +1,4 @@
-use crate::smp::cpu::ProcessorId;
+use crate::{mm::percpu::PerCpu, smp::cpu::ProcessorId};
 
 /// 重置cpu
 pub unsafe fn cpu_reset() -> ! {
@@ -13,3 +13,6 @@ pub unsafe fn cpu_reset() -> ! {
 pub fn current_cpu_id() -> ProcessorId {
     ProcessorId::new(loongArch64::register::cpuid::read().core_id() as u32)
 }
+
+#[no_mangle]
+pub static mut KERNEL_SP: [usize; PerCpu::MAX_CPU_NUM as usize] = [0; PerCpu::MAX_CPU_NUM as usize];

+ 1 - 0
kernel/src/arch/loongarch64/filesystem/mod.rs

@@ -0,0 +1 @@
+pub mod stat;

+ 1 - 0
kernel/src/arch/loongarch64/filesystem/stat.rs

@@ -0,0 +1 @@
+pub use crate::filesystem::vfs::stat::GenericPosixStat as PosixStat;

+ 11 - 8
kernel/src/arch/loongarch64/init/boot.rs

@@ -1,6 +1,6 @@
 use loongArch64::register::{ecfg, eentry};
 
-use crate::{init::init::start_kernel, mm::PhysAddr};
+use crate::{arch::interrupt::entry::handle_reserved_, init::init::start_kernel, mm::PhysAddr};
 
 static mut BOOT_HARTID: u32 = 0;
 static mut BOOT_FDT_PADDR: PhysAddr = PhysAddr::new(0);
@@ -15,16 +15,19 @@ pub unsafe extern "C" fn kernel_main(hartid: usize, fdt_paddr: usize) -> ! {
         BOOT_HARTID = hartid as u32;
         BOOT_FDT_PADDR = fdt_paddr;
     }
-    setup_trap_vector();
+    boot_tmp_setup_trap_vector();
+
     start_kernel();
 }
 
-/// 设置中断、异常处理函数
-fn setup_trap_vector() {
-    // todo!();
-    // let ptr = handle_exception as *const () as usize;
-    // ecfg::set_vs(0);
-    // eentry::set_eentry(handle_exception as usize);
+/// 临时设置中断、异常处理函数
+///
+/// 后续需要通过 https://code.dragonos.org.cn/xref/linux-6.6.21/arch/loongarch/kernel/traps.c#1085
+/// 这里的这个函数来重新设置中断、异常处理函数
+fn boot_tmp_setup_trap_vector() {
+    let ptr = handle_reserved_ as *const () as usize;
+    ecfg::set_vs(0);
+    eentry::set_eentry(ptr);
 }
 
 /// Clear the bss section

+ 4 - 0
kernel/src/arch/loongarch64/init/mod.rs

@@ -1,4 +1,6 @@
 use system_error::SystemError;
+
+use crate::driver::serial::serial8250::send_to_default_serial8250_port;
 pub mod boot;
 
 #[derive(Debug)]
@@ -10,6 +12,8 @@ impl ArchBootParams {
 
 #[inline(never)]
 pub fn early_setup_arch() -> Result<(), SystemError> {
+    send_to_default_serial8250_port(b"la64:early_setup_arch");
+    loop {}
     todo!("la64:early_setup_arch");
 }
 

+ 132 - 0
kernel/src/arch/loongarch64/interrupt/entry.rs

@@ -0,0 +1,132 @@
+use asm_macros::*;
+use kdepends::memoffset::offset_of;
+
+use crate::arch::{asm::*, interrupt::TrapFrame};
+
+/// https://code.dragonos.org.cn/xref/linux-6.6.21/arch/loongarch/kernel/genex.S#55
+macro_rules! build_prep_badv_ {
+    () => {
+        concat!(
+            "
+        csrrd $t0, {loongarch_csr_badv}
+        st.d $t0, $sp, {off_csr_badvaddr}
+        "
+        )
+    };
+}
+
+/// https://code.dragonos.org.cn/xref/linux-6.6.21/arch/loongarch/kernel/genex.S#60
+macro_rules! build_prep_fcsr_ {
+    () => {
+        concat!(
+            "
+        movfcsr2gr	$a1, $fcsr0
+        "
+        )
+    };
+}
+
+/// https://code.dragonos.org.cn/xref/linux-6.6.21/arch/loongarch/kernel/genex.S#64
+macro_rules! build_prep_none_ {
+    () => {
+        ""
+    };
+}
+
+/// https://code.dragonos.org.cn/xref/linux-6.6.21/arch/loongarch/kernel/genex.S#67
+macro_rules! build_handler {
+    ($exception:expr, $handler:expr, $prep:ident) => {
+        paste::paste! {
+            /// handle exception的实现请参考 https://code.dragonos.org.cn/xref/linux-6.6.21/arch/loongarch/kernel/genex.S#69
+            #[naked]
+            #[no_mangle]
+            #[repr(align(8))]
+            pub unsafe extern "C" fn [<handle_ $exception _>]() -> ! {
+                core::arch::naked_asm!(concat!(
+                    backup_t0t1!(),
+                    save_all!(),
+                    [<build_prep_ $prep _>]!(),
+                    "
+                    move $a0, $sp
+                    la.abs $t0, ", stringify!([<do_ $handler _>]),
+                    "
+                    jirl $ra, $t0, 0
+                    ",
+                    restore_all_and_ret!(),
+                    "
+                    // 以下是为了编译器不报错说变量未使用,才保留的代码
+                        /* {off_csr_badvaddr} */
+                        /* {loongarch_csr_badv} */
+                    "
+                ),
+                exception_ks0 = const EXCEPTION_KS0,
+                exception_ks1 = const EXCEPTION_KS1,
+                loongarch_csr_prmd = const LOONGARCH_CSR_PRMD,
+                loongarch_csr_crmd = const LOONGARCH_CSR_CRMD,
+                loongarch_csr_euen = const LOONGARCH_CSR_EUEN,
+                loongarch_csr_ecfg = const LOONGARCH_CSR_ECFG,
+                loongarch_csr_estat = const LOONGARCH_CSR_ESTAT,
+                loongarch_csr_era = const LOONGARCH_CSR_ERA,
+                loongarch_csr_badv = const LOONGARCH_CSR_BADV,
+                percpu_base_ks = const PERCPU_BASE_KS,
+                thread_mask = const _THREAD_MASK,
+                pt_size = const core::mem::size_of::<TrapFrame>(),
+                off_r0 = const offset_of!(TrapFrame, r0),
+                off_ra = const offset_of!(TrapFrame, ra),
+                off_tp = const offset_of!(TrapFrame, tp),
+                off_usp = const offset_of!(TrapFrame, usp),
+                off_a0 = const offset_of!(TrapFrame, a0),
+                off_a1 = const offset_of!(TrapFrame, a1),
+                off_a2 = const offset_of!(TrapFrame, a2),
+                off_a3 = const offset_of!(TrapFrame, a3),
+                off_a4 = const offset_of!(TrapFrame, a4),
+                off_a5 = const offset_of!(TrapFrame, a5),
+                off_a6 = const offset_of!(TrapFrame, a6),
+                off_a7 = const offset_of!(TrapFrame, a7),
+                off_t0 = const offset_of!(TrapFrame, t0),
+                off_t1 = const offset_of!(TrapFrame, t1),
+                off_t2 = const offset_of!(TrapFrame, t2),
+                off_t3 = const offset_of!(TrapFrame, t3),
+                off_t4 = const offset_of!(TrapFrame, t4),
+                off_t5 = const offset_of!(TrapFrame, t5),
+                off_t6 = const offset_of!(TrapFrame, t6),
+                off_t7 = const offset_of!(TrapFrame, t7),
+                off_t8 = const offset_of!(TrapFrame, t8),
+                off_r21 = const offset_of!(TrapFrame, r21),
+                off_fp = const offset_of!(TrapFrame, fp),
+                off_s0 = const offset_of!(TrapFrame, s0),
+                off_s1 = const offset_of!(TrapFrame, s1),
+                off_s2 = const offset_of!(TrapFrame, s2),
+                off_s3 = const offset_of!(TrapFrame, s3),
+                off_s4 = const offset_of!(TrapFrame, s4),
+                off_s5 = const offset_of!(TrapFrame, s5),
+                off_s6 = const offset_of!(TrapFrame, s6),
+                off_s7 = const offset_of!(TrapFrame, s7),
+                off_s8 = const offset_of!(TrapFrame, s8),
+                // off_orig_a0 = const offset_of!(TrapFrame, orig_a0),
+                off_csr_era = const offset_of!(TrapFrame, csr_era),
+                off_csr_badvaddr = const offset_of!(TrapFrame, csr_badvaddr),
+                off_csr_crmd = const offset_of!(TrapFrame, csr_crmd),
+                off_csr_prmd = const offset_of!(TrapFrame, csr_prmd),
+                off_csr_euen = const offset_of!(TrapFrame, csr_euen),
+                off_csr_ecfg = const offset_of!(TrapFrame, csr_ecfg),
+                off_csr_estat = const offset_of!(TrapFrame, csr_estat),
+                )
+            }
+
+        }
+    };
+}
+
+build_handler!(ade, ade, badv);
+build_handler!(ale, ale, badv);
+build_handler!(bce, bce, none);
+build_handler!(bp, bp, none);
+build_handler!(fpe, fpe, fcsr);
+build_handler!(fpu, fpu, none);
+build_handler!(lsx, lsx, none);
+build_handler!(lasx, lasx, none);
+build_handler!(lbt, lbt, none);
+build_handler!(ri, ri, none);
+build_handler!(watch, watch, none);
+build_handler!(reserved, reserved, none); /* others */

+ 87 - 0
kernel/src/arch/loongarch64/interrupt/handle.rs

@@ -0,0 +1,87 @@
+use crate::driver::serial::serial8250::send_to_default_serial8250_port;
+
+use super::TrapFrame;
+
+/// https://code.dragonos.org.cn/xref/linux-6.6.21/arch/loongarch/kernel/traps.c#508
+#[no_mangle]
+unsafe extern "C" fn do_ade_(frame: *mut TrapFrame) {
+    send_to_default_serial8250_port(b"la64: do_ade_()\n");
+    loop {}
+}
+
+/// https://code.dragonos.org.cn/xref/linux-6.6.21/arch/loongarch/kernel/traps.c#522
+#[no_mangle]
+unsafe extern "C" fn do_ale_(frame: *mut TrapFrame) {
+    send_to_default_serial8250_port(b"la64: do_ale_()\n");
+    loop {}
+}
+
+/// https://code.dragonos.org.cn/xref/linux-6.6.21/arch/loongarch/kernel/traps.c#583
+#[no_mangle]
+unsafe extern "C" fn do_bce_(frame: *mut TrapFrame) {
+    send_to_default_serial8250_port(b"la64: do_bce_()\n");
+    loop {}
+}
+
+/// https://code.dragonos.org.cn/xref/linux-6.6.21/arch/loongarch/kernel/traps.c#672
+#[no_mangle]
+unsafe extern "C" fn do_bp_(frame: *mut TrapFrame) {
+    send_to_default_serial8250_port(b"la64: do_bp_()\n");
+    loop {}
+}
+
+/// https://code.dragonos.org.cn/xref/linux-6.6.21/arch/loongarch/kernel/traps.c#481
+#[no_mangle]
+unsafe extern "C" fn do_fpe_(frame: *mut TrapFrame) {
+    send_to_default_serial8250_port(b"la64: do_fpe_()\n");
+    loop {}
+}
+
+/// https://code.dragonos.org.cn/xref/linux-6.6.21/arch/loongarch/kernel/traps.c#904
+#[no_mangle]
+unsafe extern "C" fn do_fpu_(frame: *mut TrapFrame) {
+    send_to_default_serial8250_port(b"la64: do_fpu_()\n");
+    loop {}
+}
+
+/// https://code.dragonos.org.cn/xref/linux-6.6.21/arch/loongarch/kernel/traps.c#921
+#[no_mangle]
+unsafe extern "C" fn do_lsx_(frame: *mut TrapFrame) {
+    send_to_default_serial8250_port(b"la64: do_lsx_()\n");
+    loop {}
+}
+
+/// https://code.dragonos.org.cn/xref/linux-6.6.21/arch/loongarch/kernel/traps.c#943
+#[no_mangle]
+unsafe extern "C" fn do_lasx_(frame: *mut TrapFrame) {
+    send_to_default_serial8250_port(b"la64: do_lasx_()\n");
+    loop {}
+}
+
+/// https://code.dragonos.org.cn/xref/linux-6.6.21/arch/loongarch/kernel/traps.c#978
+#[no_mangle]
+unsafe extern "C" fn do_lbt_(frame: *mut TrapFrame) {
+    send_to_default_serial8250_port(b"la64: do_lbt_()\n");
+    loop {}
+}
+
+/// https://code.dragonos.org.cn/xref/linux-6.6.21/arch/loongarch/kernel/traps.c#809
+#[no_mangle]
+unsafe extern "C" fn do_ri_(frame: *mut TrapFrame) {
+    send_to_default_serial8250_port(b"la64: do_ri_()\n");
+    loop {}
+}
+
+/// https://code.dragonos.org.cn/xref/linux-6.6.21/arch/loongarch/kernel/traps.c#756
+#[no_mangle]
+unsafe extern "C" fn do_watch_(frame: *mut TrapFrame) {
+    send_to_default_serial8250_port(b"la64: do_watch_()\n");
+    loop {}
+}
+
+/// https://code.dragonos.org.cn/xref/linux-6.6.21/arch/loongarch/kernel/traps.c#1009
+#[no_mangle]
+unsafe extern "C" fn do_reserved_(frame: *mut TrapFrame) {
+    send_to_default_serial8250_port(b"la64: do_reserved_()\n");
+    // loop {}
+}

+ 2 - 0
kernel/src/arch/loongarch64/interrupt/mod.rs

@@ -1,3 +1,5 @@
+pub mod entry;
+mod handle;
 pub mod ipi;
 
 use core::any::Any;

+ 1 - 2
kernel/src/arch/loongarch64/link.ld

@@ -21,7 +21,6 @@ SECTIONS
 		*(.bootstrap.*)
 		. = ALIGN(4096);
 		*(.initial_pgtable_section)
-		. = ALIGN(4096);
 	}
 
 
@@ -68,7 +67,7 @@ SECTIONS
 	. = ALIGN(32768);
 	
 	trace_point_start_pa = .;
-	.tracepoint (trace_point_start_pa): AT(trace_point_start_pa - KERNEL_VMA)
+	.tracepoint (trace_point_start_pa):
     {
         _tracepoint = .;
         *(.tracepoint)

+ 1 - 0
kernel/src/arch/loongarch64/mod.rs

@@ -1,6 +1,7 @@
 pub mod asm;
 pub mod cpu;
 pub mod elf;
+pub mod filesystem;
 pub mod init;
 pub mod interrupt;
 pub mod ipc;

+ 1 - 0
kernel/src/arch/riscv64/filesystem/mod.rs

@@ -0,0 +1 @@
+pub mod stat;

+ 1 - 0
kernel/src/arch/riscv64/filesystem/stat.rs

@@ -0,0 +1 @@
+pub use crate::filesystem::vfs::stat::GenericPosixStat as PosixStat;

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

+ 1 - 0
kernel/src/arch/riscv64/mod.rs

@@ -2,6 +2,7 @@ pub mod asm;
 pub mod cpu;
 pub mod driver;
 pub mod elf;
+pub mod filesystem;
 pub mod init;
 pub mod interrupt;
 pub mod ipc;

+ 5 - 1
kernel/src/arch/x86_64/vm/vmx/mod.rs

@@ -3743,8 +3743,12 @@ pub static L1TF_VMX_MITIGATION: RwLock<VmxL1dFlushState> = RwLock::new(VmxL1dFlu
 
 pub fn vmx_init() -> Result<(), SystemError> {
     let cpuid = CpuId::new();
-    let cpu_feat = cpuid.get_feature_info().ok_or(SystemError::ENOSYS)?;
+    let cpu_feat = cpuid.get_feature_info().ok_or_else(|| {
+        log::warn!("Failed to get CPU feature info, perhaps not AMD or Intel CPU");
+        SystemError::ENOSYS
+    })?;
     if !cpu_feat.has_vmx() {
+        log::warn!("VMX not supported or enabled");
         return Err(SystemError::ENOSYS);
     }
 

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

+ 4 - 7
kernel/src/driver/tty/tty_port.rs

@@ -6,7 +6,7 @@ use system_error::SystemError;
 
 use crate::{
     libs::spinlock::{SpinLock, SpinLockGuard},
-    net::event_poll::EventPoll,
+    net::event_poll::{EPollEventType, EventPoll},
 };
 
 use super::tty_core::TtyCore;
@@ -80,17 +80,14 @@ pub trait TtyPort: Sync + Send + Debug {
     /// 作为客户端的tty ports接收数据
     fn receive_buf(&self, buf: &[u8], _flags: &[u8], count: usize) -> Result<usize, SystemError> {
         let tty = self.port_data().internal_tty().unwrap();
-
         let ld = tty.ldisc();
-
         let ret = ld.receive_buf2(tty.clone(), buf, None, count);
-
         if let Err(SystemError::ENOSYS) = ret {
             return ld.receive_buf(tty, buf, None, count);
         }
-
-        EventPoll::wakeup_epoll(tty.core().eptiems(), None)?;
-
+        let event: usize = ld.poll(tty.clone())?;
+        let pollflag = EPollEventType::from_bits_truncate(event as u32);
+        EventPoll::wakeup_epoll(tty.core().eptiems(), pollflag)?;
         ret
     }
 }

+ 2 - 2
kernel/src/filesystem/eventfd.rs

@@ -186,7 +186,7 @@ impl IndexNode for EventFdInode {
         drop(eventfd);
 
         // 唤醒epoll中等待的进程
-        EventPoll::wakeup_epoll(&self.epitems, Some(pollflag))?;
+        EventPoll::wakeup_epoll(&self.epitems, pollflag)?;
 
         return Ok(8);
     }
@@ -240,7 +240,7 @@ impl IndexNode for EventFdInode {
         drop(eventfd);
 
         // 唤醒epoll中等待的进程
-        EventPoll::wakeup_epoll(&self.epitems, Some(pollflag))?;
+        EventPoll::wakeup_epoll(&self.epitems, pollflag)?;
         return Ok(8);
     }
 

+ 5 - 7
kernel/src/filesystem/poll.rs

@@ -64,9 +64,11 @@ impl<'a> PollAdapter<'a> {
     fn poll_all_fds(&mut self, timeout: Option<Instant>) -> Result<usize, SystemError> {
         let mut epoll_events = vec![EPollEvent::default(); self.poll_fds.len()];
         let len = epoll_events.len() as i32;
-        let remain_timeout = timeout
-            .and_then(|t| t.duration_since(Instant::now()))
-            .map(|t| t.into());
+        let remain_timeout = timeout.map(|t| {
+            t.duration_since(Instant::now())
+                .unwrap_or(Duration::ZERO)
+                .into()
+        });
         let events = EventPoll::epoll_wait_with_file(
             self.ep_file.clone(),
             &mut epoll_events,
@@ -176,10 +178,6 @@ fn do_sys_poll(poll_fds: &mut [PollFd], timeout: Option<Instant>) -> Result<usiz
 
 /// 计算超时的时刻
 fn poll_select_set_timeout(timeout_ms: u64) -> Option<Instant> {
-    if timeout_ms == 0 {
-        return None;
-    }
-
     Some(Instant::now() + Duration::from_millis(timeout_ms))
 }
 

+ 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,
@@ -420,6 +445,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;
     }
 
@@ -436,18 +478,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(());
@@ -462,6 +518,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");
@@ -491,6 +548,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!()
@@ -549,6 +607,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 => (),
         };

+ 92 - 0
kernel/src/filesystem/vfs/stat.rs

@@ -460,3 +460,95 @@ impl PosixKstat {
         }
     }
 }
+
+/// 通用的PosixStat
+#[allow(unused)]
+#[repr(C)]
+#[derive(Default, Clone, Copy)]
+pub struct GenericPosixStat {
+    /// Device ID
+    pub st_dev: u64,
+    /// File serial number (inode)
+    pub st_ino: u64,
+    /// File mode
+    pub st_mode: u32,
+    /// Link count
+    pub st_nlink: u32,
+    /// User ID of the file's owner
+    pub st_uid: u32,
+    /// Group ID of the file's group
+    pub st_gid: u32,
+    /// Device number, if device
+    pub st_rdev: u64,
+    /// Padding
+    pub __pad1: u64,
+    /// Size of file, in bytes
+    pub st_size: i64,
+    /// Optimal block size for I/O
+    pub st_blksize: i32,
+    /// Padding
+    pub __pad2: i32,
+    /// Number 512-byte blocks allocated
+    pub st_blocks: i64,
+    /// Time of last access (seconds)
+    pub st_atime: i64,
+    /// Time of last access (nanoseconds)
+    pub st_atime_nsec: u64,
+    /// Time of last modification (seconds)
+    pub st_mtime: i64,
+    /// Time of last modification (nanoseconds)
+    pub st_mtime_nsec: u64,
+    /// Time of last status change (seconds)
+    pub st_ctime: i64,
+    /// Time of last status change (nanoseconds)
+    pub st_ctime_nsec: u64,
+    /// Unused
+    pub __unused4: u32,
+    /// Unused
+    pub __unused5: u32,
+}
+
+/// 转换的代码参考 https://code.dragonos.org.cn/xref/linux-6.6.21/fs/stat.c#393
+impl TryFrom<KStat> for GenericPosixStat {
+    type Error = SystemError;
+
+    fn try_from(kstat: KStat) -> Result<Self, Self::Error> {
+        let mut tmp = GenericPosixStat::default();
+        if core::mem::size_of_val(&tmp.st_dev) < 4 && !kstat.dev.old_valid_dev() {
+            return Err(SystemError::EOVERFLOW);
+        }
+        if core::mem::size_of_val(&tmp.st_rdev) < 4 && !kstat.rdev.old_valid_dev() {
+            return Err(SystemError::EOVERFLOW);
+        }
+
+        tmp.st_dev = kstat.dev.new_encode_dev() as u64;
+        tmp.st_ino = kstat.ino;
+
+        if core::mem::size_of_val(&tmp.st_ino) < core::mem::size_of_val(&kstat.ino)
+            && tmp.st_ino != kstat.ino
+        {
+            return Err(SystemError::EOVERFLOW);
+        }
+
+        tmp.st_mode = kstat.mode.bits();
+        tmp.st_nlink = kstat.nlink;
+
+        // todo: 处理user namespace (https://code.dragonos.org.cn/xref/linux-6.6.21/fs/stat.c#415)
+        tmp.st_uid = kstat.uid;
+        tmp.st_gid = kstat.gid;
+
+        tmp.st_rdev = kstat.rdev.data() as u64;
+        tmp.st_size = kstat.size as i64;
+
+        tmp.st_atime = kstat.atime.tv_sec;
+        tmp.st_mtime = kstat.mtime.tv_sec;
+        tmp.st_ctime = kstat.ctime.tv_sec;
+        tmp.st_atime_nsec = kstat.atime.tv_nsec as u64;
+        tmp.st_mtime_nsec = kstat.mtime.tv_nsec as u64;
+        tmp.st_ctime_nsec = kstat.ctime.tv_nsec as u64;
+        tmp.st_blocks = kstat.blocks as i64;
+        tmp.st_blksize = kstat.blksize as i32;
+
+        Ok(tmp)
+    }
+}

+ 2 - 0
kernel/src/filesystem/vfs/syscall.rs

@@ -679,6 +679,7 @@ impl Syscall {
         let metadata = inode.metadata()?;
         if metadata.file_type == FileType::Dir {
             proc.basic_mut().set_cwd(new_path);
+            proc.fs_struct_mut().set_pwd(inode);
             return Ok(0);
         } else {
             return Err(SystemError::ENOTDIR);
@@ -698,6 +699,7 @@ impl Syscall {
         }
         let path = inode.absolute_path()?;
         pcb.basic_mut().set_cwd(path);
+        pcb.fs_struct_mut().set_pwd(inode);
         return Ok(0);
     }
 

+ 3 - 3
kernel/src/init/init.rs

@@ -93,10 +93,10 @@ fn do_start_kernel() {
     crate::bpf::init_bpf_system();
     crate::debug::jump_label::static_keys_init();
 
-    // #[cfg(all(target_arch = "x86_64", feature = "kvm"))]
-    // crate::virt::kvm::kvm_init();
     #[cfg(all(target_arch = "x86_64", feature = "kvm"))]
-    crate::arch::vm::vmx::vmx_init().unwrap();
+    if crate::arch::vm::vmx::vmx_init().is_err() {
+        log::warn!("vmx init failed, will not be enabled");
+    }
 }
 
 /// 在内存管理初始化之前,执行的初始化

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

+ 2 - 2
kernel/src/ipc/pipe.rs

@@ -288,7 +288,7 @@ impl IndexNode for LockedPipeInode {
         let pollflag = EPollEventType::from_bits_truncate(inner_guard.poll(&data)? as u32);
         drop(inner_guard);
         // 唤醒epoll中等待的进程
-        EventPoll::wakeup_epoll(&self.epitems, Some(pollflag))?;
+        EventPoll::wakeup_epoll(&self.epitems, pollflag)?;
 
         //返回读取的字节数
         return Ok(num);
@@ -477,7 +477,7 @@ impl IndexNode for LockedPipeInode {
 
         drop(inner_guard);
         // 唤醒epoll中等待的进程
-        EventPoll::wakeup_epoll(&self.epitems, Some(pollflag))?;
+        EventPoll::wakeup_epoll(&self.epitems, pollflag)?;
 
         // 返回写入的字节数
         return Ok(len);

+ 50 - 14
kernel/src/namespaces/mnt_namespace.rs

@@ -16,11 +16,13 @@ use super::ucount::Ucount::MntNamespaces;
 use super::{namespace::NsCommon, ucount::UCounts, user_namespace::UserNamespace};
 use crate::container_of;
 use crate::filesystem::vfs::mount::MountFSInode;
+use crate::filesystem::vfs::syscall::ModeType;
 use crate::filesystem::vfs::IndexNode;
 use crate::filesystem::vfs::InodeId;
 use crate::filesystem::vfs::MountFS;
 use crate::filesystem::vfs::ROOT_INODE;
 use crate::libs::rbtree::RBTree;
+use crate::libs::rwlock::RwLock;
 use crate::libs::wait_queue::WaitQueue;
 use crate::process::fork::CloneFlags;
 use crate::process::ProcessManager;
@@ -60,13 +62,36 @@ struct MntNsOperations {
     clone_flags: CloneFlags,
 }
 
-/// 使用该结构体的时候加spinlock
-#[derive(Clone, Debug)]
+#[derive(Debug, Clone)]
+struct PathContext {
+    root: Arc<dyn IndexNode>,
+    pwd: Arc<dyn IndexNode>,
+}
+
+impl PathContext {
+    pub fn new() -> Self {
+        Self {
+            root: ROOT_INODE(),
+            pwd: ROOT_INODE(),
+        }
+    }
+}
+
+#[derive(Debug)]
 pub struct FsStruct {
-    umask: u32, //文件权限掩码
-    pub root: Arc<dyn IndexNode>,
-    pub pwd: Arc<dyn IndexNode>,
+    umask: ModeType, //文件权限掩码
+    path_context: RwLock<PathContext>,
+}
+
+impl Clone for FsStruct {
+    fn clone(&self) -> Self {
+        Self {
+            umask: self.umask,
+            path_context: RwLock::new(self.path_context.read().clone()),
+        }
+    }
 }
+
 impl Default for FsStruct {
     fn default() -> Self {
         Self::new()
@@ -76,16 +101,25 @@ impl Default for FsStruct {
 impl FsStruct {
     pub fn new() -> Self {
         Self {
-            umask: 0o22,
-            root: ROOT_INODE(),
-            pwd: ROOT_INODE(),
+            umask: ModeType::S_IWUGO,
+            path_context: RwLock::new(PathContext::new()),
         }
     }
-    pub fn set_root(&mut self, inode: Arc<dyn IndexNode>) {
-        self.root = inode;
+
+    pub fn set_root(&self, inode: Arc<dyn IndexNode>) {
+        self.path_context.write().root = inode;
     }
-    pub fn set_pwd(&mut self, inode: Arc<dyn IndexNode>) {
-        self.pwd = inode;
+
+    pub fn set_pwd(&self, inode: Arc<dyn IndexNode>) {
+        self.path_context.write().pwd = inode;
+    }
+
+    pub fn pwd(&self) -> Arc<dyn IndexNode> {
+        self.path_context.read().pwd.clone()
+    }
+
+    pub fn root(&self) -> Arc<dyn IndexNode> {
+        self.path_context.read().root.clone()
     }
 }
 
@@ -127,8 +161,10 @@ impl NsOperations for MntNsOperations {
         }
         nsproxy.mnt_namespace = mnt_ns;
 
-        nsset.fs.lock().set_pwd(ROOT_INODE());
-        nsset.fs.lock().set_root(ROOT_INODE());
+        let guard = nsset.fs.write();
+        guard.set_pwd(ROOT_INODE());
+        guard.set_root(ROOT_INODE());
+
         Ok(())
     }
     fn owner(&self, ns_common: Arc<NsCommon>) -> Arc<UserNamespace> {

+ 3 - 3
kernel/src/namespaces/mod.rs

@@ -5,7 +5,7 @@ use system_error::SystemError;
 use user_namespace::UserNamespace;
 
 use crate::{
-    libs::spinlock::SpinLock,
+    libs::rwlock::RwLock,
     process::{fork::CloneFlags, ProcessControlBlock},
 };
 
@@ -17,12 +17,12 @@ pub mod ucount;
 pub mod user_namespace;
 
 /// 管理 namespace,包含了所有namespace的信息
-#[derive(Clone)]
 pub struct NsSet {
     flags: u64,
     nsproxy: NsProxy,
-    pub fs: Arc<SpinLock<FsStruct>>,
+    pub fs: RwLock<Arc<FsStruct>>,
 }
+
 #[derive(Debug, Clone)]
 pub struct NsProxy {
     pub pid_namespace: Arc<PidNamespace>,

+ 6 - 5
kernel/src/namespaces/namespace.rs

@@ -3,6 +3,7 @@ use core::fmt::Debug;
 
 use crate::filesystem::procfs::ProcFSInode;
 use crate::filesystem::vfs::{IndexNode, ROOT_INODE};
+use crate::libs::rwlock::RwLock;
 use crate::namespaces::user_namespace::UserNamespace;
 use crate::process::fork::CloneFlags;
 use crate::process::{Pid, ProcessControlBlock, ProcessManager};
@@ -101,7 +102,7 @@ pub fn prepare_nsset(flags: u64) -> Result<NsSet, SystemError> {
     let current = ProcessManager::current_pcb();
     Ok(NsSet {
         flags,
-        fs: current.fs_struct(),
+        fs: RwLock::new(current.fs_struct()),
         nsproxy: create_new_namespaces(flags, &current, USER_NS.clone())?,
     })
 }
@@ -110,10 +111,10 @@ pub fn commit_nsset(nsset: NsSet) {
     let flags = CloneFlags::from_bits_truncate(nsset.flags);
     let current = ProcessManager::current_pcb();
     if flags.contains(CloneFlags::CLONE_NEWNS) {
-        let fs = current.fs_struct();
-        let nsset_fs = nsset.fs.lock();
-        fs.lock().set_pwd(nsset_fs.pwd.clone());
-        fs.lock().set_root(nsset_fs.root.clone());
+        let nsset_fs = nsset.fs.read();
+        let fs = current.fs_struct_mut();
+        fs.set_pwd(nsset_fs.pwd());
+        fs.set_root(nsset_fs.root());
     }
     switch_task_namespace(current, nsset.nsproxy); // 转移所有权
 }

+ 28 - 43
kernel/src/net/event_poll/mod.rs

@@ -479,7 +479,7 @@ impl EventPoll {
                 }
             } else if timespec.is_none() {
                 // 非阻塞情况
-                timeout = true;
+                timeout = false;
             }
             // 判断epoll上有没有就绪事件
             let mut available = epoll_guard.ep_events_available();
@@ -775,52 +775,37 @@ impl EventPoll {
     /// ### epoll的回调,支持epoll的文件有事件到来时直接调用该方法即可
     pub fn wakeup_epoll(
         epitems: &SpinLock<LinkedList<Arc<EPollItem>>>,
-        pollflags: Option<EPollEventType>,
+        pollflags: EPollEventType,
     ) -> Result<(), SystemError> {
-        let mut epitems_guard = epitems.try_lock_irqsave()?;
-        // 一次只取一个,因为一次也只有一个进程能拿到对应文件的🔓
-        if let Some(epitem) = epitems_guard.pop_front() {
-            let pollflags = match pollflags {
-                Some(flags) => flags,
-                None => {
-                    if let Some(file) = epitem.file.upgrade() {
-                        // warning: deadlock will happen if poll() is called when pollflags is None
-                        EPollEventType::from_bits_truncate(file.poll()? as u32)
-                    } else {
-                        EPollEventType::empty()
-                    }
-                }
-            };
+        let epitems_guard = epitems.try_lock_irqsave()?;
+        for epitem in epitems_guard.iter() {
+            // The upgrade is safe because EventPoll always exists when the epitem is in the list
+            let epoll = epitem.epoll().upgrade().unwrap();
+            let mut epoll_guard = epoll.try_lock()?;
+            let binding = epitem.clone();
+            let event_guard = binding.event().read();
+            let ep_events = EPollEventType::from_bits_truncate(event_guard.events());
+            // 检查事件合理性以及是否有感兴趣的事件
+            if !(ep_events
+                .difference(EPollEventType::EP_PRIVATE_BITS)
+                .is_empty()
+                || pollflags.difference(ep_events).is_empty())
+            {
+                // TODO: 未处理pm相关
 
-            if let Some(epoll) = epitem.epoll().upgrade() {
-                let mut epoll_guard = epoll.try_lock()?;
-                let binding = epitem.clone();
-                let event_guard = binding.event().read();
-                let ep_events = EPollEventType::from_bits_truncate(event_guard.events());
-                // 检查事件合理性以及是否有感兴趣的事件
-                if !(ep_events
-                    .difference(EPollEventType::EP_PRIVATE_BITS)
-                    .is_empty()
-                    || pollflags.difference(ep_events).is_empty())
-                {
-                    // TODO: 未处理pm相关
-
-                    // 首先将就绪的epitem加入等待队列
-                    epoll_guard.ep_add_ready(epitem.clone());
-
-                    if epoll_guard.ep_has_waiter() {
-                        if ep_events.contains(EPollEventType::EPOLLEXCLUSIVE)
-                            && !pollflags.contains(EPollEventType::POLLFREE)
-                        {
-                            // 避免惊群
-                            epoll_guard.ep_wake_one();
-                        } else {
-                            epoll_guard.ep_wake_all();
-                        }
+                // 首先将就绪的epitem加入等待队列
+                epoll_guard.ep_add_ready(epitem.clone());
+
+                if epoll_guard.ep_has_waiter() {
+                    if ep_events.contains(EPollEventType::EPOLLEXCLUSIVE)
+                        && !pollflags.contains(EPollEventType::POLLFREE)
+                    {
+                        // 避免惊群
+                        epoll_guard.ep_wake_one();
+                    } else {
+                        epoll_guard.ep_wake_all();
                     }
                 }
-
-                epitems_guard.push_back(epitem);
             }
         }
         Ok(())

+ 1 - 1
kernel/src/net/net_core.rs

@@ -245,7 +245,7 @@ fn send_event(sockets: &smoltcp::iface::SocketSet) -> Result<(), SystemError> {
         }
         EventPoll::wakeup_epoll(
             &posix_item.epitems,
-            Some(EPollEventType::from_bits_truncate(events as u32)),
+            EPollEventType::from_bits_truncate(events as u32),
         )?;
         drop(handle_guard);
         // crate::debug!(

+ 1 - 1
kernel/src/perf/mod.rs

@@ -77,7 +77,7 @@ impl PerfEventInode {
     fn epoll_callback(&self) -> Result<()> {
         let pollflag = EPollEventType::from_bits_truncate(self.do_poll()? as u32);
         // 唤醒epoll中等待的进程
-        EventPoll::wakeup_epoll(&self.epitems, Some(pollflag))
+        EventPoll::wakeup_epoll(&self.epitems, pollflag)
     }
 }
 

+ 3 - 5
kernel/src/process/exec.rs

@@ -5,10 +5,7 @@ use system_error::SystemError;
 
 use crate::{
     driver::base::block::SeekFrom,
-    filesystem::vfs::{
-        file::{File, FileMode},
-        ROOT_INODE,
-    },
+    filesystem::vfs::file::{File, FileMode},
     libs::elf::ELF_LOADER,
     mm::{
         ucontext::{AddressSpace, UserStack},
@@ -118,7 +115,8 @@ impl ExecParam {
         vm: Arc<AddressSpace>,
         flags: ExecParamFlags,
     ) -> Result<Self, SystemError> {
-        let inode = ROOT_INODE().lookup(file_path)?;
+        let pwd = ProcessManager::current_pcb().pwd_inode();
+        let inode = pwd.lookup(file_path)?;
 
         // 读取文件头部,用于判断文件类型
         let file = File::new(inode, FileMode::O_RDONLY)?;

+ 35 - 13
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(());
     }
@@ -541,6 +549,13 @@ impl ProcessManager {
             )
         });
 
+        Self::copy_fs(&clone_flags, current_pcb, pcb).unwrap_or_else(|e| {
+            panic!(
+                "fork: Failed to copy fs from current process, current pid: [{:?}], new pid: [{:?}]. Error: {:?}",
+                current_pcb.pid(), pcb.pid(), e
+            )
+        });
+
         sched_cgroup_fork(pcb);
 
         Ok(())
@@ -587,15 +602,22 @@ 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(())
+    }
 
+    fn copy_fs(
+        clone_flags: &CloneFlags,
+        parent_pcb: &Arc<ProcessControlBlock>,
+        child_pcb: &Arc<ProcessControlBlock>,
+    ) -> Result<(), SystemError> {
+        let fs = parent_pcb.fs_struct();
+        let mut guard = child_pcb.fs_struct_mut();
+        if clone_flags.contains(CloneFlags::CLONE_FS) {
+            *guard = fs.clone();
+        } else {
+            let new_fs = (*fs).clone();
+            *guard = Arc::new(new_fs);
+        }
         Ok(())
     }
 }

+ 37 - 37
kernel/src/process/mod.rs

@@ -31,7 +31,7 @@ use crate::{
     exception::InterruptArch,
     filesystem::{
         procfs::procfs_unregister_pid,
-        vfs::{file::FileDescriptorVec, FileType},
+        vfs::{file::FileDescriptorVec, FileType, IndexNode},
     },
     ipc::{
         signal::RestartBlock,
@@ -718,7 +718,7 @@ pub struct ProcessControlBlock {
     thread: RwLock<ThreadInfo>,
 
     /// 进程文件系统的状态
-    fs: Arc<SpinLock<FsStruct>>,
+    fs: RwLock<Arc<FsStruct>>,
 
     ///闹钟定时器
     alarm_timer: SpinLock<Option<AlarmTimer>>,
@@ -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()) };
 
@@ -825,7 +821,7 @@ impl ProcessControlBlock {
             children: RwLock::new(Vec::new()),
             wait_queue: WaitQueue::default(),
             thread: RwLock::new(ThreadInfo::new()),
-            fs: Arc::new(SpinLock::new(FsStruct::new())),
+            fs: RwLock::new(Arc::new(FsStruct::new())),
             alarm_timer: SpinLock::new(None),
             robust_list: RwLock::new(None),
             nsproxy: Arc::new(RwLock::new(NsProxy::new())),
@@ -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);
@@ -1015,8 +1012,16 @@ impl ProcessControlBlock {
     }
 
     #[inline(always)]
-    pub fn fs_struct(&self) -> Arc<SpinLock<FsStruct>> {
-        self.fs.clone()
+    pub fn fs_struct(&self) -> Arc<FsStruct> {
+        self.fs.read().clone()
+    }
+
+    pub fn fs_struct_mut(&self) -> RwLockWriteGuard<Arc<FsStruct>> {
+        self.fs.write()
+    }
+
+    pub fn pwd_inode(&self) -> Arc<dyn IndexNode> {
+        self.fs.read().pwd()
     }
 
     /// 获取文件描述符表的Arc指针
@@ -1030,6 +1035,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 +1219,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 +1288,8 @@ impl ThreadInfo {
 /// 这个结构体保存进程的基本信息,主要是那些不会随着进程的运行而经常改变的信息。
 #[derive(Debug)]
 pub struct ProcessBasicInfo {
-    /// 当前进程的进程组id
-    pgid: Pgid,
     /// 当前进程的父进程的pid
     ppid: Pid,
-    /// 当前进程所属会话id
-    sid: Sid,
     /// 进程的名字
     name: String,
 
@@ -1286,18 +1306,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 +1321,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

@@ -140,15 +140,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(());
     }
@@ -314,6 +316,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

@@ -1233,6 +1233,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),
         };
 

+ 4 - 3
tools/bootstrap.sh

@@ -43,7 +43,7 @@ congratulations()
     echo "|   请[关闭]当前终端, 并[重新打开]一个终端 |"
 	echo "|   然后通过以下命令运行:                  |"
 	echo "|                                          |"
-	echo "|                make run                  |"
+	echo "|          make run-nographic              |"
 	echo "|                                          |"
 	echo "|------------------------------------------|"
 }
@@ -232,8 +232,7 @@ rustInstall() {
 		fi
 
         echo "正在安装DragonOS所需的rust组件...首次安装需要一些时间来更新索引,请耐心等待..."
-        cargo install cargo-binutils
-		cargo install bpf-linker
+        
 		rustup toolchain install $RUST_VERSION-x86_64-unknown-linux-gnu
 		rustup toolchain install $RUST_VERSION_OLD-x86_64-unknown-linux-gnu
 		rustup component add rust-src --toolchain $RUST_VERSION-x86_64-unknown-linux-gnu
@@ -255,6 +254,8 @@ rustInstall() {
 		rustup component add rust-src
         rustup component add llvm-tools-preview
 		rustup default $RUST_VERSION
+		cargo install cargo-binutils
+		cargo install bpf-linker
 		
 		echo "Rust已经成功的在您的计算机上安装!请运行 source ~/.cargo/env 以使rust在当前窗口生效!"
 	fi

+ 26 - 19
tools/run-qemu.sh

@@ -169,6 +169,19 @@ while true;do
       esac
   done
 
+setup_kernel_init_program() {
+    if [ ${ARCH} == "x86_64" ]; then
+        # KERNEL_CMDLINE+=" init=/bin/busybox init "
+        KERNEL_CMDLINE+=" init=/bin/dragonreach "
+    elif [ ${ARCH} == "riscv64" ]; then
+        KERNEL_CMDLINE+=" init=/bin/riscv_rust_init "
+    fi
+}
+
+# 设置内核init程序
+setup_kernel_init_program
+
+
 if [ ${QEMU_NOGRAPHIC} == true ]; then
     QEMU_SERIAL=" -serial chardev:mux -monitor chardev:mux -chardev stdio,id=mux,mux=on,signal=off,logfile=${QEMU_SERIAL_LOG_FILE} "
 
@@ -181,27 +194,21 @@ if [ ${QEMU_NOGRAPHIC} == true ]; then
       QEMU_DEVICES+=" -device virtio-serial-device -device virtconsole,chardev=mux "
     fi
 
-    KERNEL_CMDLINE+=" console=/dev/hvc0 "
+    KERNEL_CMDLINE=" console=/dev/hvc0 ${KERNEL_CMDLINE}"
     QEMU_MONITOR=""
     QEMU_ARGUMENT+=" --nographic "
 
-    if [ ${ARCH} == "x86_64" ]; then
-      QEMU_ARGUMENT+=" -kernel ../bin/kernel/kernel.elf "
-    elif [ ${ARCH} == "loongarch64" ]; then
-      QEMU_ARGUMENT+=" -kernel ../bin/kernel/kernel.elf "
-    fi
-fi
+    KERNEL_CMDLINE=$(echo "${KERNEL_CMDLINE}" | sed 's/^[ \t]*//;s/[ \t]*$//')
 
-setup_kernel_init_program() {
     if [ ${ARCH} == "x86_64" ]; then
-        KERNEL_CMDLINE+=" init=/bin/dragonreach "
+      QEMU_ARGUMENT+=" -kernel ../bin/kernel/kernel.elf -append \"${KERNEL_CMDLINE}\" "
+    elif [ ${ARCH} == "loongarch64" ]; then
+      QEMU_ARGUMENT+=" -kernel ../bin/kernel/kernel.elf -append \"${KERNEL_CMDLINE}\" "
     elif [ ${ARCH} == "riscv64" ]; then
-        KERNEL_CMDLINE+=" init=/bin/riscv_rust_init "
+      QEMU_ARGUMENT+=" -append \"${KERNEL_CMDLINE}\" "
     fi
-}
+fi
 
-# 设置内核init程序
-setup_kernel_init_program
 
 # ps: 下面这条使用tap的方式,无法dhcp获取到ip,暂时不知道为什么
 # QEMU_DEVICES="-device ahci,id=ahci -device ide-hd,drive=disk,bus=ahci.0 -net nic,netdev=nic0 -netdev tap,id=nic0,model=virtio-net-pci,script=qemu/ifup-nat,downscript=qemu/ifdown-nat -usb -device qemu-xhci,id=xhci,p2=8,p3=4 "
@@ -252,25 +259,25 @@ sudo rm -rf ${QEMU_MEMORY_BACKEND_PATH_PREFIX}/${QEMU_MEMORY_BACKEND}
 
 if [ ${BIOS_TYPE} == uefi ] ;then
   if [ ${ARCH} == x86_64 ] ;then
-    sudo ${QEMU} -bios arch/x86_64/efi/OVMF-pure-efi.fd ${QEMU_ARGUMENT}
+    sh -c "sudo ${QEMU} -bios arch/x86_64/efi/OVMF-pure-efi.fd ${QEMU_ARGUMENT}"
   elif [ ${ARCH} == i386 ] ;then
-    sudo ${QEMU} -bios arch/i386/efi/OVMF-pure-efi.fd ${QEMU_ARGUMENT}
+    sh -c "sudo ${QEMU} -bios arch/i386/efi/OVMF-pure-efi.fd ${QEMU_ARGUMENT}"
   elif [ ${ARCH} == riscv64 ] ;then
     install_riscv_uboot
-    sudo ${QEMU} -kernel ${RISCV64_UBOOT_PATH}/u-boot.bin ${QEMU_ARGUMENT}
+    sh -c "sudo ${QEMU} -kernel ${RISCV64_UBOOT_PATH}/u-boot.bin ${QEMU_ARGUMENT}"
   else
     echo "不支持的架构: ${ARCH}"
   fi
 else
   # 如果是i386架构或者x86_64架构,就直接启动
   if [ ${ARCH} == x86_64 ] || [ ${ARCH} == i386 ] ;then
-    sudo ${QEMU} ${QEMU_ARGUMENT}
+    sh -c "sudo ${QEMU} ${QEMU_ARGUMENT}"
   elif [ ${ARCH} == riscv64 ] ;then
     # 如果是riscv64架构,就与efi启动一样
     install_riscv_uboot
-    sudo ${QEMU} -kernel ${RISCV64_UBOOT_PATH}/u-boot.bin ${QEMU_ARGUMENT} -append "${KERNEL_CMDLINE}"
+    sh -c "sudo ${QEMU} -kernel ${RISCV64_UBOOT_PATH}/u-boot.bin ${QEMU_ARGUMENT}"
   elif [ ${ARCH} == loongarch64 ] ;then
-    sudo ${QEMU} ${QEMU_ARGUMENT}
+    sh -c "sudo ${QEMU} ${QEMU_ARGUMENT}"
   else
     echo "不支持的架构: ${ARCH}"
   fi

+ 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

+ 19 - 12
user/apps/test_epoll/main.c

@@ -98,19 +98,26 @@ int main() {
     printf("主线程:epoll_wait 返回,事件数量 = %d\n", nfds);
   }
 
+  if (nfds != 2) {
+    printf("主线程:事件数量不匹配,预期 2,实际 %d\n", nfds);
+    exit(EXIT_FAILURE);
+  }
+
+  // 由于dup复制了 eventfd 描述符,所以 只需要处理一个就行
+  nfds -= 1;
   // 处理就绪事件
-  //   for (int i = 0; i < nfds; i++) {
-  //     if (events[i].data.fd == efd || events[i].data.fd == efd2) {
-  //       uint64_t count;
-  //       int fd = events[i].data.fd;
-  //       printf("主线程:事件发生在 fd = %d\n", fd);
-  //       if (read(fd, &count, sizeof(count)) != sizeof(count)) {
-  //         perror("从 eventfd 读取失败");
-  //         exit(EXIT_FAILURE);
-  //       }
-  //       printf("主线程:接收到 eventfd 事件,计数值 = %lu\n", count);
-  //     }
-  //   }
+  for (int i = 0; i < nfds; i++) {
+    if (events[i].data.fd == efd || events[i].data.fd == efd2) {
+      uint64_t count;
+      int fd = events[i].data.fd;
+      printf("主线程:事件发生在 fd = %d\n", fd);
+      if (read(fd, &count, sizeof(count)) != sizeof(count)) {
+        perror("从 eventfd 读取失败");
+        exit(EXIT_FAILURE);
+      }
+      printf("主线程:接收到 eventfd 事件,计数值 = %lu\n", count);
+    }
+  }
 
   // 等待工作线程结束
   pthread_join(tid, NULL);

+ 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