mirror of
https://github.com/DragonOS-Community/DragonOS.git
synced 2025-06-11 04:56:48 +00:00
修复pipe2在读端或写端关闭后还阻塞问题 (#396)
* 修复pipe2在读端或写端关闭后还阻塞问题。 * update * update * 修改cloexec --------- Co-authored-by: longjin <longjin@RinGoTek.cn>
This commit is contained in:
parent
fba5623183
commit
876cb89ecf
@ -111,6 +111,7 @@ impl Syscall {
|
|||||||
// "tmp_rs_execve: done, load_result.entry_point()={:?}",
|
// "tmp_rs_execve: done, load_result.entry_point()={:?}",
|
||||||
// load_result.entry_point()
|
// load_result.entry_point()
|
||||||
// );
|
// );
|
||||||
|
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,7 @@ use crate::arch::{PciArch, TraitPciArch};
|
|||||||
use crate::include::bindings::bindings::{
|
use crate::include::bindings::bindings::{
|
||||||
c_irq_install, c_irq_uninstall, pt_regs, ul, EAGAIN, EINVAL,
|
c_irq_install, c_irq_uninstall, pt_regs, ul, EAGAIN, EINVAL,
|
||||||
};
|
};
|
||||||
use crate::kdebug;
|
|
||||||
use crate::libs::volatile::{volread, volwrite, Volatile, VolatileReadable, VolatileWritable};
|
use crate::libs::volatile::{volread, volwrite, Volatile, VolatileReadable, VolatileWritable};
|
||||||
|
|
||||||
/// MSIX表的一项
|
/// MSIX表的一项
|
||||||
|
@ -8,6 +8,7 @@ use crate::{
|
|||||||
tty::TtyFilePrivateData,
|
tty::TtyFilePrivateData,
|
||||||
},
|
},
|
||||||
filesystem::procfs::ProcfsFilePrivateData,
|
filesystem::procfs::ProcfsFilePrivateData,
|
||||||
|
ipc::pipe::PipeFsPrivateData,
|
||||||
kerror,
|
kerror,
|
||||||
libs::spinlock::SpinLock,
|
libs::spinlock::SpinLock,
|
||||||
process::ProcessManager,
|
process::ProcessManager,
|
||||||
@ -19,6 +20,8 @@ use super::{Dirent, FileType, IndexNode, InodeId, Metadata};
|
|||||||
/// 文件私有信息的枚举类型
|
/// 文件私有信息的枚举类型
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum FilePrivateData {
|
pub enum FilePrivateData {
|
||||||
|
/// 管道文件私有信息
|
||||||
|
Pipefs(PipeFsPrivateData),
|
||||||
/// procfs文件私有信息
|
/// procfs文件私有信息
|
||||||
Procfs(ProcfsFilePrivateData),
|
Procfs(ProcfsFilePrivateData),
|
||||||
/// 设备文件的私有信息
|
/// 设备文件的私有信息
|
||||||
@ -513,4 +516,54 @@ impl FileDescriptorVec {
|
|||||||
assert!(Arc::strong_count(&file) == 1);
|
assert!(Arc::strong_count(&file) == 1);
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn iter(&self) -> FileDescriptorIterator {
|
||||||
|
return FileDescriptorIterator::new(self);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn close_on_exec(&mut self) {
|
||||||
|
for i in 0..FileDescriptorVec::PROCESS_MAX_FD {
|
||||||
|
if let Some(file) = &self.fds[i] {
|
||||||
|
let to_drop = file.lock().close_on_exec();
|
||||||
|
if to_drop {
|
||||||
|
let r = self.drop_fd(i as i32);
|
||||||
|
if let Err(r) = r {
|
||||||
|
kerror!(
|
||||||
|
"Failed to close file: pid = {:?}, fd = {}, error = {:?}",
|
||||||
|
ProcessManager::current_pcb().pid(),
|
||||||
|
i,
|
||||||
|
r
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct FileDescriptorIterator<'a> {
|
||||||
|
fds: &'a FileDescriptorVec,
|
||||||
|
index: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> FileDescriptorIterator<'a> {
|
||||||
|
pub fn new(fds: &'a FileDescriptorVec) -> Self {
|
||||||
|
return Self { fds, index: 0 };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Iterator for FileDescriptorIterator<'a> {
|
||||||
|
type Item = (i32, Arc<SpinLock<File>>);
|
||||||
|
|
||||||
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
|
while self.index < FileDescriptorVec::PROCESS_MAX_FD {
|
||||||
|
let fd = self.index as i32;
|
||||||
|
self.index += 1;
|
||||||
|
if let Some(file) = self.fds.get_file_by_fd(fd) {
|
||||||
|
return Some((fd, file));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return None;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,6 +16,17 @@ use alloc::sync::{Arc, Weak};
|
|||||||
/// 我们设定pipe_buff的总大小为1024字节
|
/// 我们设定pipe_buff的总大小为1024字节
|
||||||
const PIPE_BUFF_SIZE: usize = 1024;
|
const PIPE_BUFF_SIZE: usize = 1024;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct PipeFsPrivateData {
|
||||||
|
mode: FileMode,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PipeFsPrivateData {
|
||||||
|
pub fn new(mode: FileMode) -> Self {
|
||||||
|
return PipeFsPrivateData { mode: mode };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// @brief 管道文件i节点(锁)
|
/// @brief 管道文件i节点(锁)
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct LockedPipeInode(SpinLock<InnerPipeInode>);
|
pub struct LockedPipeInode(SpinLock<InnerPipeInode>);
|
||||||
@ -32,11 +43,12 @@ pub struct InnerPipeInode {
|
|||||||
data: [u8; PIPE_BUFF_SIZE],
|
data: [u8; PIPE_BUFF_SIZE],
|
||||||
/// INode 元数据
|
/// INode 元数据
|
||||||
metadata: Metadata,
|
metadata: Metadata,
|
||||||
flags: FileMode,
|
reader: u32,
|
||||||
|
writer: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LockedPipeInode {
|
impl LockedPipeInode {
|
||||||
pub fn new(flags: FileMode) -> Arc<Self> {
|
pub fn new() -> Arc<Self> {
|
||||||
let inner = InnerPipeInode {
|
let inner = InnerPipeInode {
|
||||||
self_ref: Weak::default(),
|
self_ref: Weak::default(),
|
||||||
valid_cnt: 0,
|
valid_cnt: 0,
|
||||||
@ -62,7 +74,8 @@ impl LockedPipeInode {
|
|||||||
gid: 0,
|
gid: 0,
|
||||||
raw_dev: 0,
|
raw_dev: 0,
|
||||||
},
|
},
|
||||||
flags,
|
reader: 0,
|
||||||
|
writer: 0,
|
||||||
};
|
};
|
||||||
let result = Arc::new(Self(SpinLock::new(inner)));
|
let result = Arc::new(Self(SpinLock::new(inner)));
|
||||||
let mut guard = result.0.lock();
|
let mut guard = result.0.lock();
|
||||||
@ -79,8 +92,16 @@ impl IndexNode for LockedPipeInode {
|
|||||||
_offset: usize,
|
_offset: usize,
|
||||||
len: usize,
|
len: usize,
|
||||||
buf: &mut [u8],
|
buf: &mut [u8],
|
||||||
_data: &mut FilePrivateData,
|
data: &mut FilePrivateData,
|
||||||
) -> Result<usize, crate::syscall::SystemError> {
|
) -> Result<usize, crate::syscall::SystemError> {
|
||||||
|
// 获取mode
|
||||||
|
let mode: FileMode;
|
||||||
|
if let FilePrivateData::Pipefs(pdata) = data {
|
||||||
|
mode = pdata.mode;
|
||||||
|
} else {
|
||||||
|
return Err(SystemError::EBADF);
|
||||||
|
}
|
||||||
|
|
||||||
if buf.len() < len {
|
if buf.len() < len {
|
||||||
return Err(SystemError::EINVAL);
|
return Err(SystemError::EINVAL);
|
||||||
}
|
}
|
||||||
@ -89,12 +110,17 @@ impl IndexNode for LockedPipeInode {
|
|||||||
|
|
||||||
// 如果管道里面没有数据,则唤醒写端,
|
// 如果管道里面没有数据,则唤醒写端,
|
||||||
while inode.valid_cnt == 0 {
|
while inode.valid_cnt == 0 {
|
||||||
|
// 如果当前管道写者数为0,则返回EOF
|
||||||
|
if inode.writer == 0 {
|
||||||
|
return Ok(0);
|
||||||
|
}
|
||||||
|
|
||||||
inode
|
inode
|
||||||
.write_wait_queue
|
.write_wait_queue
|
||||||
.wakeup(Some(ProcessState::Blocked(true)));
|
.wakeup(Some(ProcessState::Blocked(true)));
|
||||||
|
|
||||||
// 如果为非阻塞管道,直接返回错误
|
// 如果为非阻塞管道,直接返回错误
|
||||||
if inode.flags.contains(FileMode::O_NONBLOCK) {
|
if mode.contains(FileMode::O_NONBLOCK) {
|
||||||
drop(inode);
|
drop(inode);
|
||||||
return Err(SystemError::EAGAIN_OR_EWOULDBLOCK);
|
return Err(SystemError::EAGAIN_OR_EWOULDBLOCK);
|
||||||
}
|
}
|
||||||
@ -145,9 +171,24 @@ impl IndexNode for LockedPipeInode {
|
|||||||
|
|
||||||
fn open(
|
fn open(
|
||||||
&self,
|
&self,
|
||||||
_data: &mut FilePrivateData,
|
data: &mut FilePrivateData,
|
||||||
_mode: &crate::filesystem::vfs::file::FileMode,
|
mode: &crate::filesystem::vfs::file::FileMode,
|
||||||
) -> Result<(), SystemError> {
|
) -> Result<(), SystemError> {
|
||||||
|
let mut guard = self.0.lock();
|
||||||
|
// 不能以读写方式打开管道
|
||||||
|
if mode.contains(FileMode::O_RDWR) {
|
||||||
|
return Err(SystemError::EACCES);
|
||||||
|
}
|
||||||
|
if mode.contains(FileMode::O_RDONLY) {
|
||||||
|
guard.reader += 1;
|
||||||
|
}
|
||||||
|
if mode.contains(FileMode::O_WRONLY) {
|
||||||
|
guard.writer += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 设置mode
|
||||||
|
*data = FilePrivateData::Pipefs(PipeFsPrivateData { mode: *mode });
|
||||||
|
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -159,7 +200,39 @@ impl IndexNode for LockedPipeInode {
|
|||||||
return Ok(metadata);
|
return Ok(metadata);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn close(&self, _data: &mut FilePrivateData) -> Result<(), SystemError> {
|
fn close(&self, data: &mut FilePrivateData) -> Result<(), SystemError> {
|
||||||
|
let mode: FileMode;
|
||||||
|
if let FilePrivateData::Pipefs(pipe_data) = data {
|
||||||
|
mode = pipe_data.mode;
|
||||||
|
} else {
|
||||||
|
return Err(SystemError::EBADF);
|
||||||
|
}
|
||||||
|
let mut guard = self.0.lock();
|
||||||
|
|
||||||
|
// 写端关闭
|
||||||
|
if mode.contains(FileMode::O_WRONLY) {
|
||||||
|
assert!(guard.writer > 0);
|
||||||
|
guard.writer -= 1;
|
||||||
|
// 如果已经没有写端了,则唤醒读端
|
||||||
|
if guard.writer == 0 {
|
||||||
|
guard
|
||||||
|
.read_wait_queue
|
||||||
|
.wakeup_all(Some(ProcessState::Blocked(true)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 读端关闭
|
||||||
|
if mode.contains(FileMode::O_RDONLY) {
|
||||||
|
assert!(guard.reader > 0);
|
||||||
|
guard.reader -= 1;
|
||||||
|
// 如果已经没有写端了,则唤醒读端
|
||||||
|
if guard.reader == 0 {
|
||||||
|
guard
|
||||||
|
.write_wait_queue
|
||||||
|
.wakeup_all(Some(ProcessState::Blocked(true)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -168,8 +241,16 @@ impl IndexNode for LockedPipeInode {
|
|||||||
_offset: usize,
|
_offset: usize,
|
||||||
len: usize,
|
len: usize,
|
||||||
buf: &[u8],
|
buf: &[u8],
|
||||||
_data: &mut FilePrivateData,
|
data: &mut FilePrivateData,
|
||||||
) -> Result<usize, crate::syscall::SystemError> {
|
) -> Result<usize, crate::syscall::SystemError> {
|
||||||
|
// 获取mode
|
||||||
|
let mode: FileMode;
|
||||||
|
if let FilePrivateData::Pipefs(pdata) = data {
|
||||||
|
mode = pdata.mode;
|
||||||
|
} else {
|
||||||
|
return Err(SystemError::EBADF);
|
||||||
|
}
|
||||||
|
|
||||||
if buf.len() < len || len > PIPE_BUFF_SIZE {
|
if buf.len() < len || len > PIPE_BUFF_SIZE {
|
||||||
return Err(SystemError::EINVAL);
|
return Err(SystemError::EINVAL);
|
||||||
}
|
}
|
||||||
@ -177,6 +258,9 @@ impl IndexNode for LockedPipeInode {
|
|||||||
|
|
||||||
let mut inode = self.0.lock();
|
let mut inode = self.0.lock();
|
||||||
|
|
||||||
|
// TODO: 如果已经没有读端存在了,则向写端进程发送SIGPIPE信号
|
||||||
|
if inode.reader == 0 {}
|
||||||
|
|
||||||
// 如果管道空间不够
|
// 如果管道空间不够
|
||||||
|
|
||||||
while len + inode.valid_cnt as usize > PIPE_BUFF_SIZE {
|
while len + inode.valid_cnt as usize > PIPE_BUFF_SIZE {
|
||||||
@ -186,7 +270,7 @@ impl IndexNode for LockedPipeInode {
|
|||||||
.wakeup(Some(ProcessState::Blocked(true)));
|
.wakeup(Some(ProcessState::Blocked(true)));
|
||||||
|
|
||||||
// 如果为非阻塞管道,直接返回错误
|
// 如果为非阻塞管道,直接返回错误
|
||||||
if inode.flags.contains(FileMode::O_NONBLOCK) {
|
if mode.contains(FileMode::O_NONBLOCK) {
|
||||||
drop(inode);
|
drop(inode);
|
||||||
return Err(SystemError::ENOMEM);
|
return Err(SystemError::ENOMEM);
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,15 @@
|
|||||||
use core::ffi::c_int;
|
use core::ffi::c_int;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
filesystem::vfs::file::{File, FileMode},
|
filesystem::vfs::{
|
||||||
|
file::{File, FileMode},
|
||||||
|
FilePrivateData,
|
||||||
|
},
|
||||||
process::{Pid, ProcessManager},
|
process::{Pid, ProcessManager},
|
||||||
syscall::{user_access::UserBufferWriter, Syscall, SystemError},
|
syscall::{user_access::UserBufferWriter, Syscall, SystemError},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::pipe::LockedPipeInode;
|
use super::pipe::{LockedPipeInode, PipeFsPrivateData};
|
||||||
|
|
||||||
impl Syscall {
|
impl Syscall {
|
||||||
/// # 创建带参数的匿名管道
|
/// # 创建带参数的匿名管道
|
||||||
@ -23,9 +26,13 @@ impl Syscall {
|
|||||||
let mut user_buffer =
|
let mut user_buffer =
|
||||||
UserBufferWriter::new(fd, core::mem::size_of::<[c_int; 2]>(), true)?;
|
UserBufferWriter::new(fd, core::mem::size_of::<[c_int; 2]>(), true)?;
|
||||||
let fd = user_buffer.buffer::<i32>(0)?;
|
let fd = user_buffer.buffer::<i32>(0)?;
|
||||||
let pipe_ptr = LockedPipeInode::new(flags);
|
let pipe_ptr = LockedPipeInode::new();
|
||||||
let mut read_file = File::new(pipe_ptr.clone(), FileMode::O_RDONLY)?;
|
let mut read_file = File::new(pipe_ptr.clone(), FileMode::O_RDONLY)?;
|
||||||
|
read_file.private_data =
|
||||||
|
FilePrivateData::Pipefs(PipeFsPrivateData::new(FileMode::O_RDONLY));
|
||||||
let mut write_file = File::new(pipe_ptr.clone(), FileMode::O_WRONLY)?;
|
let mut write_file = File::new(pipe_ptr.clone(), FileMode::O_WRONLY)?;
|
||||||
|
write_file.private_data =
|
||||||
|
FilePrivateData::Pipefs(PipeFsPrivateData::new(FileMode::O_WRONLY));
|
||||||
if flags.contains(FileMode::O_CLOEXEC) {
|
if flags.contains(FileMode::O_CLOEXEC) {
|
||||||
read_file.set_close_on_exec(true);
|
read_file.set_close_on_exec(true);
|
||||||
write_file.set_close_on_exec(true);
|
write_file.set_close_on_exec(true);
|
||||||
|
@ -61,7 +61,13 @@ impl Syscall {
|
|||||||
.basic_mut()
|
.basic_mut()
|
||||||
.set_name(ProcessControlBlock::generate_name(&path, &argv));
|
.set_name(ProcessControlBlock::generate_name(&path, &argv));
|
||||||
|
|
||||||
return Self::do_execve(path, argv, envp, frame);
|
Self::do_execve(path, argv, envp, frame)?;
|
||||||
|
|
||||||
|
// 关闭设置了O_CLOEXEC的文件描述符
|
||||||
|
let fd_table = ProcessManager::current_pcb().fd_table();
|
||||||
|
fd_table.write().close_on_exec();
|
||||||
|
|
||||||
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn wait4(
|
pub fn wait4(
|
||||||
|
Loading…
x
Reference in New Issue
Block a user