From 2dbef7859f0af395ccec348f17cf0b79ed56e003 Mon Sep 17 00:00:00 2001 From: GnoCiYeH Date: Mon, 9 Oct 2023 00:28:08 +0800 Subject: [PATCH] =?UTF-8?q?=E5=91=BD=E5=90=8D=E7=AE=A1=E9=81=93=E7=B3=BB?= =?UTF-8?q?=E7=BB=9F=E8=B0=83=E7=94=A8=E4=BB=A5=E5=8F=8A=E6=96=87=E4=BB=B6?= =?UTF-8?q?=E7=B3=BB=E7=BB=9F=E5=85=BC=E5=AE=B9=E7=89=B9=E6=AE=8A=E6=96=87?= =?UTF-8?q?=E4=BB=B6=E7=B1=BB=E5=9E=8B=E7=9A=84=E6=8E=A5=E5=8F=A3=20(#397)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 修复pipe2在读端或写端关闭后还阻塞问题。 * 实现命名管道机制,增加特殊文件类型兼容普通文件系统的接口。 * 普通文件系统能够适配特殊文件(命名管道等) --- .github/workflows/cache-toolchain.yml | 2 + .github/workflows/rustfmt.yml | 10 +- kernel/src/filesystem/fat/fs.rs | 66 ++++++- kernel/src/filesystem/ramfs/mod.rs | 76 +++++++- kernel/src/filesystem/vfs/core.rs | 9 +- kernel/src/filesystem/vfs/file.rs | 14 +- kernel/src/filesystem/vfs/mod.rs | 35 +++- kernel/src/filesystem/vfs/mount.rs | 22 ++- kernel/src/filesystem/vfs/syscall.rs | 44 ++++- kernel/src/syscall/mod.rs | 13 +- user/apps/test_mkfifo/Makefile | 26 +++ user/apps/test_mkfifo/link.lds | 239 ++++++++++++++++++++++++ user/apps/test_mkfifo/main.c | 78 ++++++++ user/dadk/config/relibc-0.1.0.dadk | 2 +- user/dadk/config/test_mkfifo-0.1.0.dadk | 33 ++++ 15 files changed, 649 insertions(+), 20 deletions(-) create mode 100644 user/apps/test_mkfifo/Makefile create mode 100644 user/apps/test_mkfifo/link.lds create mode 100644 user/apps/test_mkfifo/main.c create mode 100644 user/dadk/config/test_mkfifo-0.1.0.dadk diff --git a/.github/workflows/cache-toolchain.yml b/.github/workflows/cache-toolchain.yml index 1c1c658a..dec8dcee 100644 --- a/.github/workflows/cache-toolchain.yml +++ b/.github/workflows/cache-toolchain.yml @@ -45,6 +45,8 @@ jobs: sudo sh -c "apt update && apt install -y llvm-dev libclang-dev clang gcc-multilib libssl-dev pkg-config" cargo install cargo-binutils rustup toolchain install nightly + rustup toolchain install nightly-2023-01-21-x86_64-unknown-linux-gnu + rustup toolchain install nightly-2023-08-15-x86_64-unknown-linux-gnu rustup default nightly rustup component add rust-src rustup component add llvm-tools-preview diff --git a/.github/workflows/rustfmt.yml b/.github/workflows/rustfmt.yml index 0cb6e848..01c8e044 100644 --- a/.github/workflows/rustfmt.yml +++ b/.github/workflows/rustfmt.yml @@ -1,6 +1,14 @@ name: Rust format check -on: [push, pull_request] +on: + workflow_run: + workflows: [Build Check] + types: + - completed + + push: + + pull_request: jobs: # ensure the toolchain is cached diff --git a/kernel/src/filesystem/fat/fs.rs b/kernel/src/filesystem/fat/fs.rs index 2cad039c..b8a09267 100644 --- a/kernel/src/filesystem/fat/fs.rs +++ b/kernel/src/filesystem/fat/fs.rs @@ -1,4 +1,5 @@ #![allow(dead_code)] +use core::intrinsics::unlikely; use core::{any::Any, fmt::Debug}; use alloc::{ @@ -8,6 +9,8 @@ use alloc::{ vec::Vec, }; +use crate::filesystem::vfs::SpecialNodeData; +use crate::ipc::pipe::LockedPipeInode; use crate::{ driver::base::block::{block_device::LBA_SIZE, disk_info::Partition, SeekFrom}, filesystem::vfs::{ @@ -25,6 +28,7 @@ use crate::{ time::TimeSpec, }; +use super::entry::FATFile; use super::{ bpb::{BiosParameterBlock, FATType}, entry::{FATDir, FATDirEntry, FATDirIter, FATEntry}, @@ -102,6 +106,9 @@ pub struct FATInode { /// 根据不同的Inode类型,创建不同的私有字段 inode_type: FATDirEntry, + + /// 若该节点是特殊文件节点,该字段则为真正的文件节点 + special_node: Option, } impl FATInode { @@ -196,6 +203,7 @@ impl LockedFATInode { gid: 0, raw_dev: 0, }, + special_node: None, }))); inode.0.lock().self_ref = Arc::downgrade(&inode); @@ -315,6 +323,7 @@ impl FATFileSystem { gid: 0, raw_dev: 0, }, + special_node: None, }))); let result: Arc = Arc::new(FATFileSystem { @@ -1565,7 +1574,15 @@ impl IndexNode for LockedFATInode { // 对目标inode上锁,以防更改 let target_guard: SpinLockGuard = target.0.lock(); // 先从缓存删除 - guard.children.remove(&name.to_uppercase()); + let nod = guard.children.remove(&name.to_uppercase()); + + // 若删除缓存中为管道的文件,则不需要再到磁盘删除 + if let Some(_) = nod { + let file_type = target_guard.metadata.file_type; + if file_type == FileType::Pipe { + return Ok(()); + } + } let dir = match &guard.inode_type { FATDirEntry::File(_) | FATDirEntry::VolId(_) => { @@ -1663,6 +1680,53 @@ impl IndexNode for LockedFATInode { } } } + + fn mknod( + &self, + filename: &str, + mode: ModeType, + _dev_t: crate::driver::base::device::DeviceNumber, + ) -> Result, SystemError> { + let mut inode = self.0.lock(); + if inode.metadata.file_type != FileType::Dir { + return Err(SystemError::ENOTDIR); + } + + // 判断需要创建的类型 + if unlikely(mode.contains(ModeType::S_IFREG)) { + // 普通文件 + return Ok(self.create(filename, FileType::File, mode)?); + } + + let nod = LockedFATInode::new( + inode.fs.upgrade().unwrap(), + inode.self_ref.clone(), + FATDirEntry::File(FATFile::default()), + ); + + if mode.contains(ModeType::S_IFIFO) { + nod.0.lock().metadata.file_type = FileType::Pipe; + // 创建pipe文件 + let pipe_inode = LockedPipeInode::new(); + // 设置special_node + nod.0.lock().special_node = Some(SpecialNodeData::Pipe(pipe_inode)); + } else if mode.contains(ModeType::S_IFBLK) { + nod.0.lock().metadata.file_type = FileType::BlockDevice; + unimplemented!() + } else if mode.contains(ModeType::S_IFCHR) { + nod.0.lock().metadata.file_type = FileType::CharDevice; + unimplemented!() + } + + inode + .children + .insert(String::from(filename).to_uppercase(), nod.clone()); + Ok(nod) + } + + fn special_node(&self) -> Option { + self.0.lock().special_node.clone() + } } impl Default for FATFsInfo { diff --git a/kernel/src/filesystem/ramfs/mod.rs b/kernel/src/filesystem/ramfs/mod.rs index 0342cf73..1094e6dd 100644 --- a/kernel/src/filesystem/ramfs/mod.rs +++ b/kernel/src/filesystem/ramfs/mod.rs @@ -1,4 +1,5 @@ use core::any::Any; +use core::intrinsics::unlikely; use alloc::{ collections::BTreeMap, @@ -9,6 +10,7 @@ use alloc::{ use crate::{ filesystem::vfs::{core::generate_inode_id, FileType}, + ipc::pipe::LockedPipeInode, libs::spinlock::{SpinLock, SpinLockGuard}, syscall::SystemError, time::TimeSpec, @@ -16,7 +18,7 @@ use crate::{ use super::vfs::{ file::FilePrivateData, syscall::ModeType, FileSystem, FsInfo, IndexNode, InodeId, Metadata, - PollStatus, + PollStatus, SpecialNodeData, }; /// RamFS的inode名称的最大长度 @@ -52,6 +54,8 @@ pub struct RamFSInode { metadata: Metadata, /// 指向inode所在的文件系统对象的指针 fs: Weak, + /// 指向特殊节点 + special_node: Option, } impl FileSystem for RamFS { @@ -98,6 +102,7 @@ impl RamFS { raw_dev: 0, }, fs: Weak::default(), + special_node: None, }))); let result: Arc = Arc::new(RamFS { root_inode: root }); @@ -296,6 +301,7 @@ impl IndexNode for LockedRamFSInode { raw_dev: data, }, fs: inode.fs.clone(), + special_node: None, }))); // 初始化inode的自引用的weak指针 @@ -476,4 +482,72 @@ impl IndexNode for LockedRamFSInode { return Ok(keys); } + + fn mknod( + &self, + filename: &str, + mode: ModeType, + _dev_t: crate::driver::base::device::DeviceNumber, + ) -> Result, SystemError> { + let mut inode = self.0.lock(); + if inode.metadata.file_type != FileType::Dir { + return Err(SystemError::ENOTDIR); + } + + // 判断需要创建的类型 + if unlikely(mode.contains(ModeType::S_IFREG)) { + // 普通文件 + return Ok(self.create(filename, FileType::File, mode)?); + } + + let nod = Arc::new(LockedRamFSInode(SpinLock::new(RamFSInode { + parent: inode.self_ref.clone(), + self_ref: Weak::default(), + children: BTreeMap::new(), + data: Vec::new(), + metadata: Metadata { + dev_id: 0, + inode_id: generate_inode_id(), + size: 0, + blk_size: 0, + blocks: 0, + atime: TimeSpec::default(), + mtime: TimeSpec::default(), + ctime: TimeSpec::default(), + file_type: FileType::Pipe, + mode: mode, + nlinks: 1, + uid: 0, + gid: 0, + raw_dev: 0, + }, + fs: inode.fs.clone(), + special_node: None, + }))); + + nod.0.lock().self_ref = Arc::downgrade(&nod); + + if mode.contains(ModeType::S_IFIFO) { + nod.0.lock().metadata.file_type = FileType::Pipe; + // 创建pipe文件 + let pipe_inode = LockedPipeInode::new(); + // 设置special_node + nod.0.lock().special_node = Some(SpecialNodeData::Pipe(pipe_inode)); + } else if mode.contains(ModeType::S_IFBLK) { + nod.0.lock().metadata.file_type = FileType::BlockDevice; + unimplemented!() + } else if mode.contains(ModeType::S_IFCHR) { + nod.0.lock().metadata.file_type = FileType::CharDevice; + unimplemented!() + } + + inode + .children + .insert(String::from(filename).to_uppercase(), nod.clone()); + Ok(nod) + } + + fn special_node(&self) -> Option { + return self.0.lock().special_node.clone(); + } } diff --git a/kernel/src/filesystem/vfs/core.rs b/kernel/src/filesystem/vfs/core.rs index 904b9784..53ccdce0 100644 --- a/kernel/src/filesystem/vfs/core.rs +++ b/kernel/src/filesystem/vfs/core.rs @@ -15,12 +15,11 @@ use crate::{ sysfs::sysfs_init, vfs::{mount::MountFS, syscall::ModeType, AtomicInodeId, FileSystem, FileType}, }, - include::bindings::bindings::PAGE_4K_SIZE, kdebug, kerror, kinfo, syscall::SystemError, }; -use super::{file::FileMode, utils::rsplit_path, IndexNode, InodeId}; +use super::{file::FileMode, utils::rsplit_path, IndexNode, InodeId, MAX_PATHLEN}; /// @brief 原子地生成新的Inode号。 /// 请注意,所有的inode号都需要通过该函数来生成.全局的inode号,除了以下两个特殊的以外,都是唯一的 @@ -177,7 +176,7 @@ pub fn mount_root_fs() -> Result<(), SystemError> { /// @brief 创建文件/文件夹 pub fn do_mkdir(path: &str, _mode: FileMode) -> Result { // 文件名过长 - if path.len() > PAGE_4K_SIZE as usize { + if path.len() > MAX_PATHLEN as usize { return Err(SystemError::ENAMETOOLONG); } @@ -209,7 +208,7 @@ pub fn do_mkdir(path: &str, _mode: FileMode) -> Result { /// @brief 删除文件夹 pub fn do_remove_dir(path: &str) -> Result { // 文件名过长 - if path.len() > PAGE_4K_SIZE as usize { + if path.len() > MAX_PATHLEN as usize { return Err(SystemError::ENAMETOOLONG); } @@ -245,7 +244,7 @@ pub fn do_remove_dir(path: &str) -> Result { /// @brief 删除文件 pub fn do_unlink_at(path: &str, _mode: FileMode) -> Result { // 文件名过长 - if path.len() > PAGE_4K_SIZE as usize { + if path.len() > MAX_PATHLEN as usize { return Err(SystemError::ENAMETOOLONG); } diff --git a/kernel/src/filesystem/vfs/file.rs b/kernel/src/filesystem/vfs/file.rs index e56aec28..7df623b4 100644 --- a/kernel/src/filesystem/vfs/file.rs +++ b/kernel/src/filesystem/vfs/file.rs @@ -15,7 +15,7 @@ use crate::{ syscall::SystemError, }; -use super::{Dirent, FileType, IndexNode, InodeId, Metadata}; +use super::{Dirent, FileType, IndexNode, InodeId, Metadata, SpecialNodeData}; /// 文件私有信息的枚举类型 #[derive(Debug, Clone)] @@ -115,7 +115,17 @@ impl File { /// @param inode 文件对象对应的inode /// @param mode 文件的打开模式 pub fn new(inode: Arc, mode: FileMode) -> Result { - let file_type: FileType = inode.metadata()?.file_type; + let mut inode = inode; + let file_type = inode.metadata()?.file_type; + match file_type { + FileType::Pipe => { + if let Some(SpecialNodeData::Pipe(pipe_inode)) = inode.special_node() { + inode = pipe_inode; + } + } + _ => {} + } + let mut f = File { inode, offset: 0, diff --git a/kernel/src/filesystem/vfs/mod.rs b/kernel/src/filesystem/vfs/mod.rs index a6bbf483..689cc387 100644 --- a/kernel/src/filesystem/vfs/mod.rs +++ b/kernel/src/filesystem/vfs/mod.rs @@ -11,7 +11,13 @@ use ::core::{any::Any, fmt::Debug, sync::atomic::AtomicUsize}; use alloc::{string::String, sync::Arc, vec::Vec}; -use crate::{libs::casting::DowncastArc, syscall::SystemError, time::TimeSpec}; +use crate::{ + driver::base::{block::block_device::BlockDevice, char::CharDevice, device::DeviceNumber}, + ipc::pipe::LockedPipeInode, + libs::casting::DowncastArc, + syscall::SystemError, + time::TimeSpec, +}; use self::{core::generate_inode_id, file::FileMode, syscall::ModeType}; pub use self::{core::ROOT_INODE, file::FilePrivateData, mount::MountFS}; @@ -41,6 +47,16 @@ pub enum FileType { Socket, } +#[derive(Debug, Clone)] +pub enum SpecialNodeData { + /// 管道文件 + Pipe(Arc), + /// 字符设备 + CharDevice(Arc), + /// 块设备 + BlockDevice(Arc), +} + /* these are defined by POSIX and also present in glibc's dirent.h */ /// 完整含义请见 http://www.gnu.org/software/libc/manual/html_node/Directory-Entries.html pub const DT_UNKNOWN: u16 = 0; @@ -338,6 +354,23 @@ pub trait IndexNode: Any + Sync + Send + Debug { fn sync(&self) -> Result<(), SystemError> { return Ok(()); } + + /// ## 创建一个特殊文件节点 + /// - _filename: 文件名 + /// - _mode: 权限信息 + fn mknod( + &self, + _filename: &str, + _mode: ModeType, + _dev_t: DeviceNumber, + ) -> Result, SystemError> { + return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP); + } + + /// ## 返回特殊文件的inode + fn special_node(&self) -> Option { + None + } } impl DowncastArc for dyn IndexNode { diff --git a/kernel/src/filesystem/vfs/mount.rs b/kernel/src/filesystem/vfs/mount.rs index 47843115..5ac8c025 100644 --- a/kernel/src/filesystem/vfs/mount.rs +++ b/kernel/src/filesystem/vfs/mount.rs @@ -8,7 +8,7 @@ use alloc::{ sync::{Arc, Weak}, }; -use crate::{libs::spinlock::SpinLock, syscall::SystemError}; +use crate::{driver::base::device::DeviceNumber, libs::spinlock::SpinLock, syscall::SystemError}; use super::{ file::FileMode, syscall::ModeType, FilePrivateData, FileSystem, FileType, IndexNode, InodeId, @@ -348,6 +348,26 @@ impl IndexNode for MountFSInode { .insert(metadata.inode_id, new_mount_fs.clone()); return Ok(new_mount_fs); } + + #[inline] + fn mknod( + &self, + filename: &str, + mode: ModeType, + dev_t: DeviceNumber, + ) -> Result, SystemError> { + return Ok(MountFSInode { + inner_inode: self.inner_inode.mknod(filename, mode, dev_t)?, + mount_fs: self.mount_fs.clone(), + self_ref: Weak::default(), + } + .wrap()); + } + + #[inline] + fn special_node(&self) -> Option { + self.inner_inode.special_node() + } } impl FileSystem for MountFS { diff --git a/kernel/src/filesystem/vfs/syscall.rs b/kernel/src/filesystem/vfs/syscall.rs index 9c383817..5dd46d93 100644 --- a/kernel/src/filesystem/vfs/syscall.rs +++ b/kernel/src/filesystem/vfs/syscall.rs @@ -1,3 +1,5 @@ +use core::ffi::CStr; + use alloc::{ string::{String, ToString}, sync::Arc, @@ -5,14 +7,14 @@ use alloc::{ }; use crate::{ - driver::base::block::SeekFrom, + driver::base::{block::SeekFrom, device::DeviceNumber}, filesystem::vfs::file::FileDescriptorVec, - include::bindings::bindings::{verify_area, AT_REMOVEDIR, PAGE_4K_SIZE, PROC_MAX_FD_NUM}, + include::bindings::bindings::{verify_area, AT_REMOVEDIR, PROC_MAX_FD_NUM}, kerror, libs::rwlock::RwLockWriteGuard, mm::VirtAddr, process::ProcessManager, - syscall::{Syscall, SystemError}, + syscall::{user_access::UserBufferReader, Syscall, SystemError}, time::TimeSpec, }; @@ -21,7 +23,7 @@ use super::{ fcntl::{FcntlCommand, FD_CLOEXEC}, file::{File, FileMode}, utils::rsplit_path, - Dirent, FileType, IndexNode, ROOT_INODE, + Dirent, FileType, IndexNode, MAX_PATHLEN, ROOT_INODE, }; pub const SEEK_SET: u32 = 0; @@ -137,7 +139,7 @@ impl Syscall { // kdebug!("open: path: {}, mode: {:?}", path, mode); // 文件名过长 - if path.len() > PAGE_4K_SIZE as usize { + if path.len() > MAX_PATHLEN as usize { return Err(SystemError::ENAMETOOLONG); } @@ -698,6 +700,38 @@ impl Syscall { } return Ok(0); } + + pub fn mknod( + path_ptr: *const i8, + mode: ModeType, + dev_t: DeviceNumber, + ) -> Result { + // 安全检验 + let len = unsafe { CStr::from_ptr(path_ptr).to_bytes().len() }; + let user_buffer = UserBufferReader::new(path_ptr, len, true)?; + let buf = user_buffer.read_from_user::(0)?; + let path = core::str::from_utf8(buf).map_err(|_| SystemError::EINVAL)?; + + // 文件名过长 + if path.len() > MAX_PATHLEN as usize { + return Err(SystemError::ENAMETOOLONG); + } + + let inode: Result, SystemError> = ROOT_INODE().lookup(path); + + if inode.is_ok() { + return Err(SystemError::EEXIST); + } + + let (filename, parent_path) = rsplit_path(path); + + // 查找父目录 + let parent_inode: Arc = ROOT_INODE().lookup(parent_path.unwrap_or("/"))?; + // 创建nod + parent_inode.mknod(filename, mode, dev_t)?; + + return Ok(0); + } } #[repr(C)] #[derive(Debug, Clone, Copy)] diff --git a/kernel/src/syscall/mod.rs b/kernel/src/syscall/mod.rs index 1c1bafd0..b3bec251 100644 --- a/kernel/src/syscall/mod.rs +++ b/kernel/src/syscall/mod.rs @@ -7,11 +7,11 @@ use num_traits::{FromPrimitive, ToPrimitive}; use crate::{ arch::{cpu::cpu_reset, interrupt::TrapFrame, MMArch}, - driver::base::block::SeekFrom, + driver::base::{block::SeekFrom, device::DeviceNumber}, filesystem::vfs::{ fcntl::FcntlCommand, file::FileMode, - syscall::{PosixKstat, SEEK_CUR, SEEK_END, SEEK_MAX, SEEK_SET}, + syscall::{ModeType, PosixKstat, SEEK_CUR, SEEK_END, SEEK_MAX, SEEK_SET}, MAX_PATHLEN, }, include::bindings::bindings::{PAGE_2M_SIZE, PAGE_4K_SIZE}, @@ -375,6 +375,7 @@ pub const SYS_GETPGID: usize = 50; pub const SYS_FCNTL: usize = 51; pub const SYS_FTRUNCATE: usize = 52; +pub const SYS_MKNOD: usize = 53; #[derive(Debug)] pub struct Syscall; @@ -973,6 +974,14 @@ impl Syscall { res } + SYS_MKNOD => { + let path = args[0]; + let flags = args[1]; + let dev_t = args[2]; + let flags: ModeType = ModeType::from_bits_truncate(flags as u32); + Self::mknod(path as *const i8, flags, DeviceNumber::from(dev_t)) + } + _ => panic!("Unsupported syscall ID: {}", syscall_num), }; diff --git a/user/apps/test_mkfifo/Makefile b/user/apps/test_mkfifo/Makefile new file mode 100644 index 00000000..a2a39cb4 --- /dev/null +++ b/user/apps/test_mkfifo/Makefile @@ -0,0 +1,26 @@ +CC=$(DragonOS_GCC)/x86_64-elf-gcc +LD=ld +OBJCOPY=objcopy +# 修改这里,把它改为你的relibc的sysroot路径 +RELIBC_OPT=$(DADK_BUILD_CACHE_DIR_RELIBC_0_1_0) +CFLAGS=-I $(RELIBC_OPT)/include -D__dragonos__ + +tmp_output_dir=$(ROOT_PATH)/bin/tmp/user +output_dir=$(DADK_BUILD_CACHE_DIR_TEST_MKFIFO_0_1_0) + +LIBC_OBJS:=$(shell find $(RELIBC_OPT)/lib -name "*.o" | sort ) +LIBC_OBJS+=$(RELIBC_OPT)/lib/libc.a + +all: main.o + mkdir -p $(tmp_output_dir) + + $(LD) -b elf64-x86-64 -z muldefs -o $(tmp_output_dir)/test_mkfifo $(shell find . -name "*.o") $(LIBC_OBJS) -T link.lds + + $(OBJCOPY) -I elf64-x86-64 -R ".eh_frame" -R ".comment" -O elf64-x86-64 $(tmp_output_dir)/test_mkfifo $(output_dir)/test_mkfifo.elf + + mv $(output_dir)/test_mkfifo.elf $(output_dir)/test_mkfifo +main.o: main.c + $(CC) $(CFLAGS) -c main.c -o main.o + +clean: + rm -f *.o \ No newline at end of file diff --git a/user/apps/test_mkfifo/link.lds b/user/apps/test_mkfifo/link.lds new file mode 100644 index 00000000..1f2e57e4 --- /dev/null +++ b/user/apps/test_mkfifo/link.lds @@ -0,0 +1,239 @@ +/* Script for -z combreloc */ +/* Copyright (C) 2014-2020 Free Software Foundation, Inc. + Copying and distribution of this script, with or without modification, + are permitted in any medium without royalty provided the copyright + notice and this notice are preserved. */ +OUTPUT_FORMAT("elf64-x86-64", "elf64-x86-64", + "elf64-x86-64") +OUTPUT_ARCH(i386:x86-64) +ENTRY(_start) + +SECTIONS +{ + /* Read-only sections, merged into text segment: */ + PROVIDE (__executable_start = SEGMENT_START("text-segment", 0x400000)); . = SEGMENT_START("text-segment", 0x20000000) + SIZEOF_HEADERS; + .interp : { *(.interp) } + .note.gnu.build-id : { *(.note.gnu.build-id) } + .hash : { *(.hash) } + .gnu.hash : { *(.gnu.hash) } + .dynsym : { *(.dynsym) } + .dynstr : { *(.dynstr) } + .gnu.version : { *(.gnu.version) } + .gnu.version_d : { *(.gnu.version_d) } + .gnu.version_r : { *(.gnu.version_r) } + .rela.dyn : + { + *(.rela.init) + *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*) + *(.rela.fini) + *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*) + *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*) + *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*) + *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*) + *(.rela.ctors) + *(.rela.dtors) + *(.rela.got) + *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*) + *(.rela.ldata .rela.ldata.* .rela.gnu.linkonce.l.*) + *(.rela.lbss .rela.lbss.* .rela.gnu.linkonce.lb.*) + *(.rela.lrodata .rela.lrodata.* .rela.gnu.linkonce.lr.*) + *(.rela.ifunc) + } + .rela.plt : + { + *(.rela.plt) + PROVIDE_HIDDEN (__rela_iplt_start = .); + *(.rela.iplt) + PROVIDE_HIDDEN (__rela_iplt_end = .); + } + . = ALIGN(CONSTANT (MAXPAGESIZE)); + .init : + { + KEEP (*(SORT_NONE(.init))) + } + .plt : { *(.plt) *(.iplt) } +.plt.got : { *(.plt.got) } +.plt.sec : { *(.plt.sec) } + .text : + { + *(.text.unlikely .text.*_unlikely .text.unlikely.*) + *(.text.exit .text.exit.*) + *(.text.startup .text.startup.*) + *(.text.hot .text.hot.*) + *(.text .stub .text.* .gnu.linkonce.t.*) + /* .gnu.warning sections are handled specially by elf.em. */ + *(.gnu.warning) + } + .fini : + { + KEEP (*(SORT_NONE(.fini))) + } + PROVIDE (__etext = .); + PROVIDE (_etext = .); + PROVIDE (etext = .); + . = ALIGN(CONSTANT (MAXPAGESIZE)); + /* Adjust the address for the rodata segment. We want to adjust up to + the same address within the page on the next page up. */ + . = SEGMENT_START("rodata-segment", ALIGN(CONSTANT (MAXPAGESIZE)) + (. & (CONSTANT (MAXPAGESIZE) - 1))); + .rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) } + .rodata1 : { *(.rodata1) } + .eh_frame_hdr : { *(.eh_frame_hdr) *(.eh_frame_entry .eh_frame_entry.*) } + .eh_frame : ONLY_IF_RO { KEEP (*(.eh_frame)) *(.eh_frame.*) } + .gcc_except_table : ONLY_IF_RO { *(.gcc_except_table .gcc_except_table.*) } + .gnu_extab : ONLY_IF_RO { *(.gnu_extab*) } + /* These sections are generated by the Sun/Oracle C++ compiler. */ + .exception_ranges : ONLY_IF_RO { *(.exception_ranges*) } + /* Adjust the address for the data segment. We want to adjust up to + the same address within the page on the next page up. */ + . = DATA_SEGMENT_ALIGN (CONSTANT (MAXPAGESIZE), CONSTANT (COMMONPAGESIZE)); + /* Exception handling */ + .eh_frame : ONLY_IF_RW { KEEP (*(.eh_frame)) *(.eh_frame.*) } + .gnu_extab : ONLY_IF_RW { *(.gnu_extab) } + .gcc_except_table : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) } + .exception_ranges : ONLY_IF_RW { *(.exception_ranges*) } + /* Thread Local Storage sections */ + .tdata : + { + PROVIDE_HIDDEN (__tdata_start = .); + *(.tdata .tdata.* .gnu.linkonce.td.*) + } + .tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) } + .preinit_array : + { + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP (*(.preinit_array)) + PROVIDE_HIDDEN (__preinit_array_end = .); + } + .init_array : + { + PROVIDE_HIDDEN (__init_array_start = .); + KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*))) + KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors)) + PROVIDE_HIDDEN (__init_array_end = .); + } + .fini_array : + { + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*))) + KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors)) + PROVIDE_HIDDEN (__fini_array_end = .); + } + .ctors : + { + /* gcc uses crtbegin.o to find the start of + the constructors, so we make sure it is + first. Because this is a wildcard, it + doesn't matter if the user does not + actually link against crtbegin.o; the + linker won't look for a file to match a + wildcard. The wildcard also means that it + doesn't matter which directory crtbegin.o + is in. */ + KEEP (*crtbegin.o(.ctors)) + KEEP (*crtbegin?.o(.ctors)) + /* We don't want to include the .ctor section from + the crtend.o file until after the sorted ctors. + The .ctor section from the crtend file contains the + end of ctors marker and it must be last */ + KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + } + .dtors : + { + KEEP (*crtbegin.o(.dtors)) + KEEP (*crtbegin?.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + } + .jcr : { KEEP (*(.jcr)) } + .data.rel.ro : { *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) *(.data.rel.ro .data.rel.ro.* .gnu.linkonce.d.rel.ro.*) } + .dynamic : { *(.dynamic) } + .got : { *(.got) *(.igot) } + . = DATA_SEGMENT_RELRO_END (SIZEOF (.got.plt) >= 24 ? 24 : 0, .); + .got.plt : { *(.got.plt) *(.igot.plt) } + .data : + { + *(.data .data.* .gnu.linkonce.d.*) + SORT(CONSTRUCTORS) + } + .data1 : { *(.data1) } + _edata = .; PROVIDE (edata = .); + . = .; + __bss_start = .; + .bss : + { + *(.dynbss) + *(.bss .bss.* .gnu.linkonce.b.*) + *(COMMON) + /* Align here to ensure that the .bss section occupies space up to + _end. Align after .bss to ensure correct alignment even if the + .bss section disappears because there are no input sections. + FIXME: Why do we need it? When there is no .bss section, we do not + pad the .data section. */ + . = ALIGN(. != 0 ? 64 / 8 : 1); + } + .lbss : + { + *(.dynlbss) + *(.lbss .lbss.* .gnu.linkonce.lb.*) + *(LARGE_COMMON) + } + . = ALIGN(64 / 8); + . = SEGMENT_START("ldata-segment", .); + .lrodata ALIGN(CONSTANT (MAXPAGESIZE)) + (. & (CONSTANT (MAXPAGESIZE) - 1)) : + { + *(.lrodata .lrodata.* .gnu.linkonce.lr.*) + } + .ldata ALIGN(CONSTANT (MAXPAGESIZE)) + (. & (CONSTANT (MAXPAGESIZE) - 1)) : + { + *(.ldata .ldata.* .gnu.linkonce.l.*) + . = ALIGN(. != 0 ? 64 / 8 : 1); + } + . = ALIGN(64 / 8); + _end = .; PROVIDE (end = .); + . = DATA_SEGMENT_END (.); + /* Stabs debugging sections. */ + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + .gnu.build.attributes : { *(.gnu.build.attributes .gnu.build.attributes.*) } + /* DWARF debug sections. + Symbols in the DWARF debugging sections are relative to the beginning + of the section so we begin them at 0. */ + /* DWARF 1 */ + .debug 0 : { *(.debug) } + .line 0 : { *(.line) } + /* GNU DWARF 1 extensions */ + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_sfnames 0 : { *(.debug_sfnames) } + /* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + /* DWARF 2 */ + .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line .debug_line.* .debug_line_end) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + /* SGI/MIPS DWARF 2 extensions */ + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } + /* DWARF 3 */ + .debug_pubtypes 0 : { *(.debug_pubtypes) } + .debug_ranges 0 : { *(.debug_ranges) } + /* DWARF Extension. */ + .debug_macro 0 : { *(.debug_macro) } + .debug_addr 0 : { *(.debug_addr) } + .gnu.attributes 0 : { KEEP (*(.gnu.attributes)) } + /DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) *(.gnu.lto_*) } +} diff --git a/user/apps/test_mkfifo/main.c b/user/apps/test_mkfifo/main.c new file mode 100644 index 00000000..3efe8079 --- /dev/null +++ b/user/apps/test_mkfifo/main.c @@ -0,0 +1,78 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#define BUFFER_SIZE 256 +#define PIPE_NAME "/bin/fifo" + +int main() +{ + pid_t pid; + int pipe_fd; + char buffer[BUFFER_SIZE]; + int bytes_read; + int status; + + // 创建命名管道 + mkfifo(PIPE_NAME, 0666); + + // 创建子进程 + pid = fork(); + + if (pid < 0) + { + fprintf(stderr, "Fork failed\n"); + return 1; + } + else if (pid == 0) + { + // 子进程 + + // 打开管道以供读取 + pipe_fd = open(PIPE_NAME, O_RDONLY); + + // 从管道中读取数据 + bytes_read = read(pipe_fd, buffer, BUFFER_SIZE); + if (bytes_read > 0) + { + printf("Child process received message: %s\n", buffer); + } + + // 关闭管道文件描述符 + close(pipe_fd); + + // 删除命名管道 + unlink(PIPE_NAME); + + exit(0); + } + else + { + // 父进程 + + // 打开管道以供写入 + pipe_fd = open(PIPE_NAME, O_WRONLY); + + // 向管道写入数据 + const char *message = "Hello from parent process"; + write(pipe_fd, message, strlen(message) + 1); + + // 关闭管道文件描述符 + close(pipe_fd); + + // 等待子进程结束 + waitpid(pid, &status, 0); + + if (WIFEXITED(status)) + { + printf("Child process exited with status: %d\n", WEXITSTATUS(status)); + } + } + + return 0; +} \ No newline at end of file diff --git a/user/dadk/config/relibc-0.1.0.dadk b/user/dadk/config/relibc-0.1.0.dadk index e88de99c..9bdca94d 100644 --- a/user/dadk/config/relibc-0.1.0.dadk +++ b/user/dadk/config/relibc-0.1.0.dadk @@ -6,7 +6,7 @@ "BuildFromSource": { "Git": { "url": "https://git.mirrors.dragonos.org/DragonOS-Community/relibc.git", - "revision": "26536e7fcd" + "revision": "66739c1b10" } } }, diff --git a/user/dadk/config/test_mkfifo-0.1.0.dadk b/user/dadk/config/test_mkfifo-0.1.0.dadk new file mode 100644 index 00000000..59f4187f --- /dev/null +++ b/user/dadk/config/test_mkfifo-0.1.0.dadk @@ -0,0 +1,33 @@ +{ + "name": "test_mkfifo", + "version": "0.1.0", + "description": "一个用来测试mkfifo能够正常运行的app", + "task_type": { + "BuildFromSource": { + "Local": { + "path": "apps/test_mkfifo" + } + } + }, + "depends": [ + { + "name": "relibc", + "version": "0.1.0" + } + ], + "build": { + "build_command": "make" + }, + "install": { + "in_dragonos_path": "/bin" + }, + "clean": { + "clean_command": "make clean" + }, + "envs": [ + { + "key": "__dragonos__", + "value": "__dragonos__" + } + ] +}