mirror of
https://github.com/DragonOS-Community/DragonOS.git
synced 2025-06-18 20:36:31 +00:00
Patch pipe2 (#364)
This commit is contained in:
@ -2,8 +2,8 @@ use crate::{
|
||||
arch::{sched::sched, CurrentIrqArch},
|
||||
exception::InterruptArch,
|
||||
filesystem::vfs::{
|
||||
core::generate_inode_id, FilePrivateData, FileSystem, FileType, IndexNode, Metadata,
|
||||
PollStatus,
|
||||
core::generate_inode_id, file::FileMode, FilePrivateData, FileSystem, FileType, IndexNode,
|
||||
Metadata, PollStatus,
|
||||
},
|
||||
include::bindings::bindings::PROC_INTERRUPTIBLE,
|
||||
libs::{spinlock::SpinLock, wait_queue::WaitQueue},
|
||||
@ -32,10 +32,11 @@ pub struct InnerPipeInode {
|
||||
data: [u8; PIPE_BUFF_SIZE],
|
||||
/// INode 元数据
|
||||
metadata: Metadata,
|
||||
flags: FileMode,
|
||||
}
|
||||
|
||||
impl LockedPipeInode {
|
||||
pub fn new() -> Arc<Self> {
|
||||
pub fn new(flags: FileMode) -> Arc<Self> {
|
||||
let inner = InnerPipeInode {
|
||||
self_ref: Weak::default(),
|
||||
valid_cnt: 0,
|
||||
@ -48,7 +49,7 @@ impl LockedPipeInode {
|
||||
metadata: Metadata {
|
||||
dev_id: 0,
|
||||
inode_id: generate_inode_id(),
|
||||
size: 0,
|
||||
size: PIPE_BUFF_SIZE as i64,
|
||||
blk_size: 0,
|
||||
blocks: 0,
|
||||
atime: TimeSpec::default(),
|
||||
@ -61,6 +62,7 @@ impl LockedPipeInode {
|
||||
gid: 0,
|
||||
raw_dev: 0,
|
||||
},
|
||||
flags,
|
||||
};
|
||||
let result = Arc::new(Self(SpinLock::new(inner)));
|
||||
let mut guard = result.0.lock();
|
||||
@ -85,11 +87,15 @@ impl IndexNode for LockedPipeInode {
|
||||
// 加锁
|
||||
let mut inode = self.0.lock();
|
||||
|
||||
//如果管道里面没有数据,则唤醒写端,
|
||||
// 如果管道里面没有数据,则唤醒写端,
|
||||
while inode.valid_cnt == 0 {
|
||||
inode.write_wait_queue.wakeup(PROC_INTERRUPTIBLE.into());
|
||||
|
||||
// 在读等待队列中睡眠,并释放锁
|
||||
// 如果为非阻塞管道,直接返回错误
|
||||
if inode.flags.contains(FileMode::O_NONBLOCK) {
|
||||
drop(inode);
|
||||
return Err(SystemError::EAGAIN_OR_EWOULDBLOCK);
|
||||
}
|
||||
// 否则在读等待队列中睡眠,并释放锁
|
||||
unsafe {
|
||||
let irq_guard = CurrentIrqArch::save_and_disable_irq();
|
||||
inode.read_wait_queue.sleep_without_schedule();
|
||||
@ -170,6 +176,11 @@ impl IndexNode for LockedPipeInode {
|
||||
while len + inode.valid_cnt as usize > PIPE_BUFF_SIZE {
|
||||
// 唤醒读端
|
||||
inode.read_wait_queue.wakeup(PROC_INTERRUPTIBLE.into());
|
||||
// 如果为非阻塞管道,直接返回错误
|
||||
if inode.flags.contains(FileMode::O_NONBLOCK) {
|
||||
drop(inode);
|
||||
return Err(SystemError::ENOMEM);
|
||||
}
|
||||
// 解锁并睡眠
|
||||
unsafe {
|
||||
let irq_guard = CurrentIrqArch::save_and_disable_irq();
|
||||
|
@ -8,7 +8,7 @@ use crate::{
|
||||
filesystem::vfs::file::{File, FileMode},
|
||||
include::bindings::bindings::{pid_t, verify_area, NULL},
|
||||
kwarn,
|
||||
syscall::{Syscall, SystemError},
|
||||
syscall::{user_access::UserBufferWriter, Syscall, SystemError},
|
||||
};
|
||||
|
||||
use super::{
|
||||
@ -22,25 +22,37 @@ use super::{
|
||||
};
|
||||
|
||||
impl Syscall {
|
||||
/// # 创建匿名管道
|
||||
/// # 创建带参数的匿名管道
|
||||
///
|
||||
/// ## 参数
|
||||
///
|
||||
/// - `fd`: 用于返回文件描述符的数组
|
||||
pub fn pipe(fd: &mut [i32]) -> Result<usize, SystemError> {
|
||||
let pipe_ptr = LockedPipeInode::new();
|
||||
let read_file = File::new(pipe_ptr.clone(), FileMode::O_RDONLY)?;
|
||||
let write_file = File::new(pipe_ptr.clone(), FileMode::O_WRONLY)?;
|
||||
/// - `flags`:设置管道的参数
|
||||
pub fn pipe2(fd: *mut i32, flags: FileMode) -> Result<usize, SystemError> {
|
||||
if flags.contains(FileMode::O_NONBLOCK)
|
||||
|| flags.contains(FileMode::O_CLOEXEC)
|
||||
|| flags.contains(FileMode::O_RDONLY)
|
||||
{
|
||||
let mut user_buffer =
|
||||
UserBufferWriter::new(fd, core::mem::size_of::<[c_int; 2]>(), true)?;
|
||||
let fd = user_buffer.buffer::<i32>(0)?;
|
||||
let pipe_ptr = LockedPipeInode::new(flags);
|
||||
let mut read_file = File::new(pipe_ptr.clone(), FileMode::O_RDONLY)?;
|
||||
let mut write_file = File::new(pipe_ptr.clone(), FileMode::O_WRONLY)?;
|
||||
if flags.contains(FileMode::O_CLOEXEC) {
|
||||
read_file.set_close_on_exec(true);
|
||||
write_file.set_close_on_exec(true);
|
||||
}
|
||||
let read_fd = current_pcb().alloc_fd(read_file, None)?;
|
||||
let write_fd = current_pcb().alloc_fd(write_file, None)?;
|
||||
|
||||
let read_fd = current_pcb().alloc_fd(read_file, None)?;
|
||||
let write_fd = current_pcb().alloc_fd(write_file, None)?;
|
||||
|
||||
fd[0] = read_fd;
|
||||
fd[1] = write_fd;
|
||||
|
||||
return Ok(0);
|
||||
fd[0] = read_fd;
|
||||
fd[1] = write_fd;
|
||||
Ok(0)
|
||||
} else {
|
||||
Err(SystemError::EINVAL)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn kill(pid: pid_t, sig: c_int) -> Result<usize, SystemError> {
|
||||
let sig = SignalNumber::from(sig);
|
||||
if sig == SignalNumber::INVALID {
|
||||
|
@ -652,13 +652,13 @@ impl Syscall {
|
||||
|
||||
SYS_CLOCK => Self::clock(),
|
||||
SYS_PIPE => {
|
||||
let pipefd = args[0] as *mut c_int;
|
||||
match UserBufferWriter::new(pipefd, core::mem::size_of::<[c_int; 2]>(), from_user) {
|
||||
Err(e) => Err(e),
|
||||
Ok(mut user_buffer) => match user_buffer.buffer::<i32>(0) {
|
||||
Err(e) => Err(e),
|
||||
Ok(pipefd) => Self::pipe(pipefd),
|
||||
},
|
||||
let pipefd: *mut i32 = args[0] as *mut c_int;
|
||||
let arg1 = args[1];
|
||||
if pipefd.is_null() {
|
||||
Err(SystemError::EFAULT)
|
||||
} else {
|
||||
let flags = FileMode::from_bits_truncate(arg1 as u32);
|
||||
Self::pipe2(pipefd, flags)
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user