fix: 修复无法执行当前目录下程序的bug (#1154)

* 更改pcb中的fs以及fNsSet结构体,以便从fs中获取pwd inode

* fmt

* 更改run-qemu.sh,为x86_64传入KERNEL_CMDLINE参数

* 提取FsStruct中的root和pwd信息

* chore(run-qemu.sh): 重构内核启动参数处理逻辑

- 优化KERNEL_CMDLINE拼接逻辑,确保参数顺序正确
- 统一使用sh -c执行QEMU命令

Signed-off-by: longjin <longjin@DragonOS.org>

* refactor(mnt_namespace): 重构FsStruct使用ModeType并移除Arc包装

- 将umask类型从u32改为ModeType
- 移除path_context的Arc包装,改为直接使用RwLock
- 实现Clone trait替代自动derive
- 更新默认umask值为ModeType::S_IWUGO

Signed-off-by: longjin <longjin@DragonOS.org>

* fix(run-qemu): 修改x86_64架构的init程序路径

将x86_64架构的init程序从/bin/busybox改为/bin/dragonreach

Signed-off-by: longjin <longjin@DragonOS.org>

---------

Signed-off-by: longjin <longjin@DragonOS.org>
Co-authored-by: longjin <longjin@DragonOS.org>
This commit is contained in:
火花 2025-05-09 15:16:10 +08:00 committed by GitHub
parent 0b89d7130e
commit 5422256d63
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 127 additions and 52 deletions

View File

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

View File

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

View File

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

View File

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

View File

@ -5,10 +5,7 @@ use system_error::SystemError;
use crate::{ use crate::{
driver::base::block::SeekFrom, driver::base::block::SeekFrom,
filesystem::vfs::{ filesystem::vfs::file::{File, FileMode},
file::{File, FileMode},
ROOT_INODE,
},
libs::elf::ELF_LOADER, libs::elf::ELF_LOADER,
mm::{ mm::{
ucontext::{AddressSpace, UserStack}, ucontext::{AddressSpace, UserStack},
@ -118,7 +115,8 @@ impl ExecParam {
vm: Arc<AddressSpace>, vm: Arc<AddressSpace>,
flags: ExecParamFlags, flags: ExecParamFlags,
) -> Result<Self, SystemError> { ) -> 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)?; let file = File::new(inode, FileMode::O_RDONLY)?;

View File

@ -549,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); sched_cgroup_fork(pcb);
Ok(()) Ok(())
@ -597,4 +604,20 @@ impl ProcessManager {
Ok(()) 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(())
}
} }

View File

@ -31,7 +31,7 @@ use crate::{
exception::InterruptArch, exception::InterruptArch,
filesystem::{ filesystem::{
procfs::procfs_unregister_pid, procfs::procfs_unregister_pid,
vfs::{file::FileDescriptorVec, FileType}, vfs::{file::FileDescriptorVec, FileType, IndexNode},
}, },
ipc::{ ipc::{
signal::RestartBlock, signal::RestartBlock,
@ -718,7 +718,7 @@ pub struct ProcessControlBlock {
thread: RwLock<ThreadInfo>, thread: RwLock<ThreadInfo>,
/// 进程文件系统的状态 /// 进程文件系统的状态
fs: Arc<SpinLock<FsStruct>>, fs: RwLock<Arc<FsStruct>>,
///闹钟定时器 ///闹钟定时器
alarm_timer: SpinLock<Option<AlarmTimer>>, alarm_timer: SpinLock<Option<AlarmTimer>>,
@ -821,7 +821,7 @@ impl ProcessControlBlock {
children: RwLock::new(Vec::new()), children: RwLock::new(Vec::new()),
wait_queue: WaitQueue::default(), wait_queue: WaitQueue::default(),
thread: RwLock::new(ThreadInfo::new()), thread: RwLock::new(ThreadInfo::new()),
fs: Arc::new(SpinLock::new(FsStruct::new())), fs: RwLock::new(Arc::new(FsStruct::new())),
alarm_timer: SpinLock::new(None), alarm_timer: SpinLock::new(None),
robust_list: RwLock::new(None), robust_list: RwLock::new(None),
nsproxy: Arc::new(RwLock::new(NsProxy::new())), nsproxy: Arc::new(RwLock::new(NsProxy::new())),
@ -1012,8 +1012,16 @@ impl ProcessControlBlock {
} }
#[inline(always)] #[inline(always)]
pub fn fs_struct(&self) -> Arc<SpinLock<FsStruct>> { pub fn fs_struct(&self) -> Arc<FsStruct> {
self.fs.clone() 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指针 /// 获取文件描述符表的Arc指针

View File

@ -169,6 +169,19 @@ while true;do
esac esac
done 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 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} " 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 " QEMU_DEVICES+=" -device virtio-serial-device -device virtconsole,chardev=mux "
fi fi
KERNEL_CMDLINE+=" console=/dev/hvc0 " KERNEL_CMDLINE=" console=/dev/hvc0 ${KERNEL_CMDLINE}"
QEMU_MONITOR="" QEMU_MONITOR=""
QEMU_ARGUMENT+=" --nographic " QEMU_ARGUMENT+=" --nographic "
KERNEL_CMDLINE=$(echo "${KERNEL_CMDLINE}" | sed 's/^[ \t]*//;s/[ \t]*$//')
if [ ${ARCH} == "x86_64" ]; then if [ ${ARCH} == "x86_64" ]; then
QEMU_ARGUMENT+=" -kernel ../bin/kernel/kernel.elf " QEMU_ARGUMENT+=" -kernel ../bin/kernel/kernel.elf -append \"${KERNEL_CMDLINE}\" "
elif [ ${ARCH} == "loongarch64" ]; then elif [ ${ARCH} == "loongarch64" ]; then
QEMU_ARGUMENT+=" -kernel ../bin/kernel/kernel.elf " QEMU_ARGUMENT+=" -kernel ../bin/kernel/kernel.elf -append \"${KERNEL_CMDLINE}\" "
elif [ ${ARCH} == "riscv64" ]; then
QEMU_ARGUMENT+=" -append \"${KERNEL_CMDLINE}\" "
fi fi
fi fi
setup_kernel_init_program() {
if [ ${ARCH} == "x86_64" ]; then
KERNEL_CMDLINE+=" init=/bin/dragonreach "
elif [ ${ARCH} == "riscv64" ]; then
KERNEL_CMDLINE+=" init=/bin/riscv_rust_init "
fi
}
# 设置内核init程序
setup_kernel_init_program
# ps: 下面这条使用tap的方式无法dhcp获取到ip暂时不知道为什么 # 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 " # 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 [ ${BIOS_TYPE} == uefi ] ;then
if [ ${ARCH} == x86_64 ] ;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 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 elif [ ${ARCH} == riscv64 ] ;then
install_riscv_uboot 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 else
echo "不支持的架构: ${ARCH}" echo "不支持的架构: ${ARCH}"
fi fi
else else
# 如果是i386架构或者x86_64架构就直接启动 # 如果是i386架构或者x86_64架构就直接启动
if [ ${ARCH} == x86_64 ] || [ ${ARCH} == i386 ] ;then if [ ${ARCH} == x86_64 ] || [ ${ARCH} == i386 ] ;then
sudo ${QEMU} ${QEMU_ARGUMENT} sh -c "sudo ${QEMU} ${QEMU_ARGUMENT}"
elif [ ${ARCH} == riscv64 ] ;then elif [ ${ARCH} == riscv64 ] ;then
# 如果是riscv64架构就与efi启动一样 # 如果是riscv64架构就与efi启动一样
install_riscv_uboot 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 elif [ ${ARCH} == loongarch64 ] ;then
sudo ${QEMU} ${QEMU_ARGUMENT} sh -c "sudo ${QEMU} ${QEMU_ARGUMENT}"
else else
echo "不支持的架构: ${ARCH}" echo "不支持的架构: ${ARCH}"
fi fi