修正pipe逻辑,将pipe接入epoll。 (#478)

This commit is contained in:
GnoCiYeH
2023-12-27 15:02:29 +08:00
committed by GitHub
parent 0d6cf65aa1
commit 5e948c5650
8 changed files with 201 additions and 89 deletions

View File

@ -6,11 +6,15 @@ use crate::{
FileType, IndexNode, Metadata,
},
libs::{spinlock::SpinLock, wait_queue::WaitQueue},
net::event_poll::{EPollEventType, EPollItem, EventPoll},
process::ProcessState,
time::TimeSpec,
};
use alloc::sync::{Arc, Weak};
use alloc::{
collections::LinkedList,
sync::{Arc, Weak},
};
use system_error::SystemError;
/// 我们设定pipe_buff的总大小为1024字节
@ -25,6 +29,10 @@ impl PipeFsPrivateData {
pub fn new(mode: FileMode) -> Self {
return PipeFsPrivateData { mode: mode };
}
pub fn set_mode(&mut self, mode: FileMode) {
self.mode = mode;
}
}
/// @brief 管道文件i节点(锁)
@ -35,6 +43,7 @@ pub struct LockedPipeInode(SpinLock<InnerPipeInode>);
#[derive(Debug)]
pub struct InnerPipeInode {
self_ref: Weak<LockedPipeInode>,
/// 管道内可读的数据数
valid_cnt: i32,
read_pos: i32,
write_pos: i32,
@ -45,6 +54,50 @@ pub struct InnerPipeInode {
metadata: Metadata,
reader: u32,
writer: u32,
epitems: SpinLock<LinkedList<Arc<EPollItem>>>,
}
impl InnerPipeInode {
pub fn poll(&self, private_data: &FilePrivateData) -> Result<usize, SystemError> {
let mut events = EPollEventType::empty();
let mode = if let FilePrivateData::Pipefs(PipeFsPrivateData { mode }) = private_data {
mode
} else {
return Err(SystemError::EBADFD);
};
if mode.contains(FileMode::O_RDONLY) {
if self.valid_cnt != 0 {
// 有数据可读
events.insert(EPollEventType::EPOLLIN & EPollEventType::EPOLLRDNORM);
}
// 没有写者
if self.writer == 0 {
events.insert(EPollEventType::EPOLLHUP)
}
}
if mode.contains(FileMode::O_WRONLY) {
// 管道内数据未满
if self.valid_cnt as usize != PIPE_BUFF_SIZE {
events.insert(EPollEventType::EPOLLIN & EPollEventType::EPOLLWRNORM);
}
// 没有读者
if self.reader == 0 {
events.insert(EPollEventType::EPOLLERR);
}
}
Ok(events.bits() as usize)
}
pub fn add_epoll(&mut self, epitem: Arc<EPollItem>) -> Result<(), SystemError> {
self.epitems.lock().push_back(epitem);
Ok(())
}
}
impl LockedPipeInode {
@ -76,6 +129,7 @@ impl LockedPipeInode {
},
reader: 0,
writer: 0,
epitems: SpinLock::new(LinkedList::new()),
};
let result = Arc::new(Self(SpinLock::new(inner)));
let mut guard = result.0.lock();
@ -84,6 +138,10 @@ impl LockedPipeInode {
drop(guard); //这一步其实不需要只要离开作用域guard生命周期结束自会解锁
return result;
}
pub fn inner(&self) -> &SpinLock<InnerPipeInode> {
&self.0
}
}
impl IndexNode for LockedPipeInode {
@ -162,10 +220,22 @@ impl IndexNode for LockedPipeInode {
inode.read_pos = (inode.read_pos + num as i32) % PIPE_BUFF_SIZE as i32;
inode.valid_cnt -= num as i32;
// 读完以后如果未读完,则唤醒下一个读者
if inode.valid_cnt > 0 {
inode
.read_wait_queue
.wakeup(Some(ProcessState::Blocked(true)));
}
//读完后解锁并唤醒等待在写等待队列中的进程
inode
.write_wait_queue
.wakeup(Some(ProcessState::Blocked(true)));
let pollflag = EPollEventType::from_bits_truncate(inode.poll(&data)? as u32);
// 唤醒epoll中等待的进程
EventPoll::wakeup_epoll(&mut inode.epitems, pollflag)?;
//返回读取的字节数
return Ok(num);
}
@ -302,10 +372,22 @@ impl IndexNode for LockedPipeInode {
inode.write_pos = (inode.write_pos + len as i32) % PIPE_BUFF_SIZE as i32;
inode.valid_cnt += len as i32;
// 写完后还有位置,则唤醒下一个写者
if (inode.valid_cnt as usize) < PIPE_BUFF_SIZE {
inode
.write_wait_queue
.wakeup(Some(ProcessState::Blocked(true)));
}
// 读完后解锁并唤醒等待在读等待队列中的进程
inode
.read_wait_queue
.wakeup(Some(ProcessState::Blocked(true)));
let pollflag = EPollEventType::from_bits_truncate(inode.poll(&data)? as u32);
// 唤醒epoll中等待的进程
EventPoll::wakeup_epoll(&mut inode.epitems, pollflag)?;
// 返回写入的字节数
return Ok(len);
}
@ -331,4 +413,8 @@ impl IndexNode for LockedPipeInode {
fn list(&self) -> Result<alloc::vec::Vec<alloc::string::String>, SystemError> {
return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP);
}
fn poll(&self, private_data: &FilePrivateData) -> Result<usize, SystemError> {
return self.0.lock().poll(private_data);
}
}

View File

@ -33,37 +33,46 @@ impl Syscall {
/// - `fd`: 用于返回文件描述符的数组
/// - `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)
if !flags
.difference(FileMode::O_CLOEXEC | FileMode::O_NONBLOCK | FileMode::O_DIRECT)
.is_empty()
{
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();
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)?;
write_file.private_data =
FilePrivateData::Pipefs(PipeFsPrivateData::new(FileMode::O_WRONLY));
if flags.contains(FileMode::O_CLOEXEC) {
read_file.set_close_on_exec(true);
write_file.set_close_on_exec(true);
}
let fd_table_ptr = ProcessManager::current_pcb().fd_table();
let mut fd_table_guard = fd_table_ptr.write();
let read_fd = fd_table_guard.alloc_fd(read_file, None)?;
let write_fd = fd_table_guard.alloc_fd(write_file, None)?;
drop(fd_table_guard);
fd[0] = read_fd;
fd[1] = write_fd;
Ok(0)
} else {
Err(SystemError::EINVAL)
return Err(SystemError::EINVAL);
}
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();
let mut read_file = File::new(
pipe_ptr.clone(),
FileMode::O_RDONLY | (flags & FileMode::O_NONBLOCK),
)?;
read_file.private_data =
FilePrivateData::Pipefs(PipeFsPrivateData::new(FileMode::O_RDONLY));
let mut write_file = File::new(
pipe_ptr.clone(),
FileMode::O_WRONLY | (flags & (FileMode::O_NONBLOCK | FileMode::O_DIRECT)),
)?;
write_file.private_data = FilePrivateData::Pipefs(PipeFsPrivateData::new(
FileMode::O_WRONLY | (flags & (FileMode::O_NONBLOCK | FileMode::O_DIRECT)),
));
if flags.contains(FileMode::O_CLOEXEC) {
read_file.set_close_on_exec(true);
write_file.set_close_on_exec(true);
}
let fd_table_ptr = ProcessManager::current_pcb().fd_table();
let mut fd_table_guard = fd_table_ptr.write();
let read_fd = fd_table_guard.alloc_fd(read_file, None)?;
let write_fd = fd_table_guard.alloc_fd(write_file, None)?;
drop(fd_table_guard);
fd[0] = read_fd;
fd[1] = write_fd;
Ok(0)
}
pub fn kill(pid: Pid, sig: c_int) -> Result<usize, SystemError> {