1 use crate::{ 2 arch::{sched::sched, CurrentIrqArch}, 3 exception::InterruptArch, 4 filesystem::vfs::{ 5 core::generate_inode_id, file::FileMode, syscall::ModeType, FilePrivateData, FileSystem, 6 FileType, IndexNode, Metadata, PollStatus, 7 }, 8 libs::{spinlock::SpinLock, wait_queue::WaitQueue}, 9 process::ProcessState, 10 syscall::SystemError, 11 time::TimeSpec, 12 }; 13 14 use alloc::sync::{Arc, Weak}; 15 16 /// 我们设定pipe_buff的总大小为1024字节 17 const PIPE_BUFF_SIZE: usize = 1024; 18 19 /// @brief 管道文件i节点(锁) 20 #[derive(Debug)] 21 pub struct LockedPipeInode(SpinLock<InnerPipeInode>); 22 23 /// @brief 管道文件i节点(无锁) 24 #[derive(Debug)] 25 pub struct InnerPipeInode { 26 self_ref: Weak<LockedPipeInode>, 27 valid_cnt: i32, 28 read_pos: i32, 29 write_pos: i32, 30 read_wait_queue: WaitQueue, 31 write_wait_queue: WaitQueue, 32 data: [u8; PIPE_BUFF_SIZE], 33 /// INode 元数据 34 metadata: Metadata, 35 flags: FileMode, 36 } 37 38 impl LockedPipeInode { 39 pub fn new(flags: FileMode) -> Arc<Self> { 40 let inner = InnerPipeInode { 41 self_ref: Weak::default(), 42 valid_cnt: 0, 43 read_pos: 0, 44 write_pos: 0, 45 read_wait_queue: WaitQueue::INIT, 46 write_wait_queue: WaitQueue::INIT, 47 data: [0; PIPE_BUFF_SIZE], 48 49 metadata: Metadata { 50 dev_id: 0, 51 inode_id: generate_inode_id(), 52 size: PIPE_BUFF_SIZE as i64, 53 blk_size: 0, 54 blocks: 0, 55 atime: TimeSpec::default(), 56 mtime: TimeSpec::default(), 57 ctime: TimeSpec::default(), 58 file_type: FileType::Pipe, 59 mode: ModeType::from_bits_truncate(0o666), 60 nlinks: 1, 61 uid: 0, 62 gid: 0, 63 raw_dev: 0, 64 }, 65 flags, 66 }; 67 let result = Arc::new(Self(SpinLock::new(inner))); 68 let mut guard = result.0.lock(); 69 guard.self_ref = Arc::downgrade(&result); 70 // 释放锁 71 drop(guard); //这一步其实不需要,只要离开作用域,guard生命周期结束,自会解锁 72 return result; 73 } 74 } 75 76 impl IndexNode for LockedPipeInode { 77 fn read_at( 78 &self, 79 _offset: usize, 80 len: usize, 81 buf: &mut [u8], 82 _data: &mut FilePrivateData, 83 ) -> Result<usize, crate::syscall::SystemError> { 84 if buf.len() < len { 85 return Err(SystemError::EINVAL); 86 } 87 // 加锁 88 let mut inode = self.0.lock(); 89 90 // 如果管道里面没有数据,则唤醒写端, 91 while inode.valid_cnt == 0 { 92 inode 93 .write_wait_queue 94 .wakeup(Some(ProcessState::Blocked(true))); 95 96 // 如果为非阻塞管道,直接返回错误 97 if inode.flags.contains(FileMode::O_NONBLOCK) { 98 drop(inode); 99 return Err(SystemError::EAGAIN_OR_EWOULDBLOCK); 100 } 101 102 // 否则在读等待队列中睡眠,并释放锁 103 unsafe { 104 let irq_guard = CurrentIrqArch::save_and_disable_irq(); 105 inode.read_wait_queue.sleep_without_schedule(); 106 drop(inode); 107 108 drop(irq_guard); 109 } 110 sched(); 111 inode = self.0.lock(); 112 } 113 114 let mut num = inode.valid_cnt as usize; 115 //决定要输出的字节 116 let start = inode.read_pos as usize; 117 //如果读端希望读取的字节数大于有效字节数,则输出有效字节 118 let mut end = (inode.valid_cnt as usize + inode.read_pos as usize) % PIPE_BUFF_SIZE; 119 //如果读端希望读取的字节数少于有效字节数,则输出希望读取的字节 120 if len < inode.valid_cnt as usize { 121 end = (len + inode.read_pos as usize) % PIPE_BUFF_SIZE; 122 num = len; 123 } 124 125 // 从管道拷贝数据到用户的缓冲区 126 127 if end < start { 128 buf[0..(PIPE_BUFF_SIZE - start)].copy_from_slice(&inode.data[start..PIPE_BUFF_SIZE]); 129 buf[(PIPE_BUFF_SIZE - start)..num].copy_from_slice(&inode.data[0..end]); 130 } else { 131 buf[0..num].copy_from_slice(&inode.data[start..end]); 132 } 133 134 //更新读位置以及valid_cnt 135 inode.read_pos = (inode.read_pos + num as i32) % PIPE_BUFF_SIZE as i32; 136 inode.valid_cnt -= num as i32; 137 138 //读完后解锁并唤醒等待在写等待队列中的进程 139 inode 140 .write_wait_queue 141 .wakeup(Some(ProcessState::Blocked(true))); 142 //返回读取的字节数 143 return Ok(num); 144 } 145 146 fn open( 147 &self, 148 _data: &mut FilePrivateData, 149 _mode: &crate::filesystem::vfs::file::FileMode, 150 ) -> Result<(), SystemError> { 151 return Ok(()); 152 } 153 154 fn metadata(&self) -> Result<crate::filesystem::vfs::Metadata, SystemError> { 155 let inode = self.0.lock(); 156 let mut metadata = inode.metadata.clone(); 157 metadata.size = inode.data.len() as i64; 158 159 return Ok(metadata); 160 } 161 162 fn close(&self, _data: &mut FilePrivateData) -> Result<(), SystemError> { 163 return Ok(()); 164 } 165 166 fn write_at( 167 &self, 168 _offset: usize, 169 len: usize, 170 buf: &[u8], 171 _data: &mut FilePrivateData, 172 ) -> Result<usize, crate::syscall::SystemError> { 173 if buf.len() < len || len > PIPE_BUFF_SIZE { 174 return Err(SystemError::EINVAL); 175 } 176 // 加锁 177 178 let mut inode = self.0.lock(); 179 180 // 如果管道空间不够 181 182 while len + inode.valid_cnt as usize > PIPE_BUFF_SIZE { 183 // 唤醒读端 184 inode 185 .read_wait_queue 186 .wakeup(Some(ProcessState::Blocked(true))); 187 188 // 如果为非阻塞管道,直接返回错误 189 if inode.flags.contains(FileMode::O_NONBLOCK) { 190 drop(inode); 191 return Err(SystemError::ENOMEM); 192 } 193 194 // 解锁并睡眠 195 unsafe { 196 let irq_guard = CurrentIrqArch::save_and_disable_irq(); 197 inode.write_wait_queue.sleep_without_schedule(); 198 drop(inode); 199 drop(irq_guard); 200 } 201 sched(); 202 inode = self.0.lock(); 203 } 204 205 // 决定要输入的字节 206 let start = inode.write_pos as usize; 207 let end = (inode.write_pos as usize + len) % PIPE_BUFF_SIZE; 208 // 从用户的缓冲区拷贝数据到管道 209 210 if end < start { 211 inode.data[start..PIPE_BUFF_SIZE].copy_from_slice(&buf[0..(PIPE_BUFF_SIZE - start)]); 212 inode.data[0..end].copy_from_slice(&buf[(PIPE_BUFF_SIZE - start)..len]); 213 } else { 214 inode.data[start..end].copy_from_slice(&buf[0..len]); 215 } 216 // 更新写位置以及valid_cnt 217 inode.write_pos = (inode.write_pos + len as i32) % PIPE_BUFF_SIZE as i32; 218 inode.valid_cnt += len as i32; 219 220 // 读完后解锁并唤醒等待在读等待队列中的进程 221 inode 222 .read_wait_queue 223 .wakeup(Some(ProcessState::Blocked(true))); 224 // 返回写入的字节数 225 return Ok(len); 226 } 227 228 fn poll(&self) -> Result<PollStatus, crate::syscall::SystemError> { 229 return Ok(PollStatus::READ | PollStatus::WRITE); 230 } 231 232 fn as_any_ref(&self) -> &dyn core::any::Any { 233 self 234 } 235 236 fn get_entry_name_and_metadata( 237 &self, 238 ino: crate::filesystem::vfs::InodeId, 239 ) -> Result<(alloc::string::String, crate::filesystem::vfs::Metadata), SystemError> { 240 // 如果有条件,请在文件系统中使用高效的方式实现本接口,而不是依赖这个低效率的默认实现。 241 let name = self.get_entry_name(ino)?; 242 let entry = self.find(&name)?; 243 return Ok((name, entry.metadata()?)); 244 } 245 246 fn fs(&self) -> Arc<(dyn FileSystem)> { 247 todo!() 248 } 249 250 fn list(&self) -> Result<alloc::vec::Vec<alloc::string::String>, SystemError> { 251 return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP); 252 } 253 } 254