|
@@ -16,6 +16,17 @@ use alloc::sync::{Arc, Weak};
|
|
|
/// 我们设定pipe_buff的总大小为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节点(锁)
|
|
|
#[derive(Debug)]
|
|
|
pub struct LockedPipeInode(SpinLock<InnerPipeInode>);
|
|
@@ -32,11 +43,12 @@ pub struct InnerPipeInode {
|
|
|
data: [u8; PIPE_BUFF_SIZE],
|
|
|
/// INode 元数据
|
|
|
metadata: Metadata,
|
|
|
- flags: FileMode,
|
|
|
+ reader: u32,
|
|
|
+ writer: u32,
|
|
|
}
|
|
|
|
|
|
impl LockedPipeInode {
|
|
|
- pub fn new(flags: FileMode) -> Arc<Self> {
|
|
|
+ pub fn new() -> Arc<Self> {
|
|
|
let inner = InnerPipeInode {
|
|
|
self_ref: Weak::default(),
|
|
|
valid_cnt: 0,
|
|
@@ -62,7 +74,8 @@ impl LockedPipeInode {
|
|
|
gid: 0,
|
|
|
raw_dev: 0,
|
|
|
},
|
|
|
- flags,
|
|
|
+ reader: 0,
|
|
|
+ writer: 0,
|
|
|
};
|
|
|
let result = Arc::new(Self(SpinLock::new(inner)));
|
|
|
let mut guard = result.0.lock();
|
|
@@ -79,8 +92,16 @@ impl IndexNode for LockedPipeInode {
|
|
|
_offset: usize,
|
|
|
len: usize,
|
|
|
buf: &mut [u8],
|
|
|
- _data: &mut FilePrivateData,
|
|
|
+ data: &mut FilePrivateData,
|
|
|
) -> 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 {
|
|
|
return Err(SystemError::EINVAL);
|
|
|
}
|
|
@@ -89,12 +110,17 @@ impl IndexNode for LockedPipeInode {
|
|
|
|
|
|
// 如果管道里面没有数据,则唤醒写端,
|
|
|
while inode.valid_cnt == 0 {
|
|
|
+ // 如果当前管道写者数为0,则返回EOF
|
|
|
+ if inode.writer == 0 {
|
|
|
+ return Ok(0);
|
|
|
+ }
|
|
|
+
|
|
|
inode
|
|
|
.write_wait_queue
|
|
|
.wakeup(Some(ProcessState::Blocked(true)));
|
|
|
|
|
|
// 如果为非阻塞管道,直接返回错误
|
|
|
- if inode.flags.contains(FileMode::O_NONBLOCK) {
|
|
|
+ if mode.contains(FileMode::O_NONBLOCK) {
|
|
|
drop(inode);
|
|
|
return Err(SystemError::EAGAIN_OR_EWOULDBLOCK);
|
|
|
}
|
|
@@ -145,9 +171,24 @@ impl IndexNode for LockedPipeInode {
|
|
|
|
|
|
fn open(
|
|
|
&self,
|
|
|
- _data: &mut FilePrivateData,
|
|
|
- _mode: &crate::filesystem::vfs::file::FileMode,
|
|
|
+ data: &mut FilePrivateData,
|
|
|
+ mode: &crate::filesystem::vfs::file::FileMode,
|
|
|
) -> 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(());
|
|
|
}
|
|
|
|
|
@@ -159,7 +200,39 @@ impl IndexNode for LockedPipeInode {
|
|
|
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(());
|
|
|
}
|
|
|
|
|
@@ -168,8 +241,16 @@ impl IndexNode for LockedPipeInode {
|
|
|
_offset: usize,
|
|
|
len: usize,
|
|
|
buf: &[u8],
|
|
|
- _data: &mut FilePrivateData,
|
|
|
+ data: &mut FilePrivateData,
|
|
|
) -> 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 {
|
|
|
return Err(SystemError::EINVAL);
|
|
|
}
|
|
@@ -177,6 +258,9 @@ impl IndexNode for LockedPipeInode {
|
|
|
|
|
|
let mut inode = self.0.lock();
|
|
|
|
|
|
+ // TODO: 如果已经没有读端存在了,则向写端进程发送SIGPIPE信号
|
|
|
+ if inode.reader == 0 {}
|
|
|
+
|
|
|
// 如果管道空间不够
|
|
|
|
|
|
while len + inode.valid_cnt as usize > PIPE_BUFF_SIZE {
|
|
@@ -186,7 +270,7 @@ impl IndexNode for LockedPipeInode {
|
|
|
.wakeup(Some(ProcessState::Blocked(true)));
|
|
|
|
|
|
// 如果为非阻塞管道,直接返回错误
|
|
|
- if inode.flags.contains(FileMode::O_NONBLOCK) {
|
|
|
+ if mode.contains(FileMode::O_NONBLOCK) {
|
|
|
drop(inode);
|
|
|
return Err(SystemError::ENOMEM);
|
|
|
}
|