命名管道系统调用以及文件系统兼容特殊文件类型的接口 (#397)

* 修复pipe2在读端或写端关闭后还阻塞问题。

* 实现命名管道机制,增加特殊文件类型兼容普通文件系统的接口。

* 普通文件系统能够适配特殊文件(命名管道等)
This commit is contained in:
GnoCiYeH 2023-10-09 00:28:08 +08:00 committed by GitHub
parent 34e6d6c80f
commit 2dbef7859f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 649 additions and 20 deletions

View File

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

View File

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

View File

@ -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<SpecialNodeData>,
}
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<FATFileSystem> = Arc::new(FATFileSystem {
@ -1565,7 +1574,15 @@ impl IndexNode for LockedFATInode {
// 对目标inode上锁以防更改
let target_guard: SpinLockGuard<FATInode> = 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<Arc<dyn IndexNode>, 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<SpecialNodeData> {
self.0.lock().special_node.clone()
}
}
impl Default for FATFsInfo {

View File

@ -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<RamFS>,
/// 指向特殊节点
special_node: Option<SpecialNodeData>,
}
impl FileSystem for RamFS {
@ -98,6 +102,7 @@ impl RamFS {
raw_dev: 0,
},
fs: Weak::default(),
special_node: None,
})));
let result: Arc<RamFS> = 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<Arc<dyn IndexNode>, 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<super::vfs::SpecialNodeData> {
return self.0.lock().special_node.clone();
}
}

View File

@ -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<u64, SystemError> {
// 文件名过长
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<u64, SystemError> {
/// @brief 删除文件夹
pub fn do_remove_dir(path: &str) -> Result<u64, SystemError> {
// 文件名过长
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<u64, SystemError> {
/// @brief 删除文件
pub fn do_unlink_at(path: &str, _mode: FileMode) -> Result<u64, SystemError> {
// 文件名过长
if path.len() > PAGE_4K_SIZE as usize {
if path.len() > MAX_PATHLEN as usize {
return Err(SystemError::ENAMETOOLONG);
}

View File

@ -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<dyn IndexNode>, mode: FileMode) -> Result<Self, SystemError> {
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,

View File

@ -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<LockedPipeInode>),
/// 字符设备
CharDevice(Arc<dyn CharDevice>),
/// 块设备
BlockDevice(Arc<dyn BlockDevice>),
}
/* 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<Arc<dyn IndexNode>, SystemError> {
return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP);
}
/// ## 返回特殊文件的inode
fn special_node(&self) -> Option<SpecialNodeData> {
None
}
}
impl DowncastArc for dyn IndexNode {

View File

@ -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<Arc<dyn IndexNode>, 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<super::SpecialNodeData> {
self.inner_inode.special_node()
}
}
impl FileSystem for MountFS {

View File

@ -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<usize, SystemError> {
// 安全检验
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::<u8>(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<Arc<dyn IndexNode>, SystemError> = ROOT_INODE().lookup(path);
if inode.is_ok() {
return Err(SystemError::EEXIST);
}
let (filename, parent_path) = rsplit_path(path);
// 查找父目录
let parent_inode: Arc<dyn IndexNode> = ROOT_INODE().lookup(parent_path.unwrap_or("/"))?;
// 创建nod
parent_inode.mknod(filename, mode, dev_t)?;
return Ok(0);
}
}
#[repr(C)]
#[derive(Debug, Clone, Copy)]

View File

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

View File

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

View File

@ -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_*) }
}

View File

@ -0,0 +1,78 @@
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <sys/wait.h>
#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;
}

View File

@ -6,7 +6,7 @@
"BuildFromSource": {
"Git": {
"url": "https://git.mirrors.dragonos.org/DragonOS-Community/relibc.git",
"revision": "26536e7fcd"
"revision": "66739c1b10"
}
}
},

View File

@ -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__"
}
]
}