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 #[derive(Debug, Clone)] 20 pub struct PipeFsPrivateData { 21 mode: FileMode, 22 } 23 24 impl PipeFsPrivateData { 25 pub fn new(mode: FileMode) -> Self { 26 return PipeFsPrivateData { mode: mode }; 27 } 28 } 29 30 /// @brief 管道文件i节点(锁) 31 #[derive(Debug)] 32 pub struct LockedPipeInode(SpinLock<InnerPipeInode>); 33 34 /// @brief 管道文件i节点(无锁) 35 #[derive(Debug)] 36 pub struct InnerPipeInode { 37 self_ref: Weak<LockedPipeInode>, 38 valid_cnt: i32, 39 read_pos: i32, 40 write_pos: i32, 41 read_wait_queue: WaitQueue, 42 write_wait_queue: WaitQueue, 43 data: [u8; PIPE_BUFF_SIZE], 44 /// INode 元数据 45 metadata: Metadata, 46 reader: u32, 47 writer: u32, 48 } 49 50 impl LockedPipeInode { 51 pub fn new() -> Arc<Self> { 52 let inner = InnerPipeInode { 53 self_ref: Weak::default(), 54 valid_cnt: 0, 55 read_pos: 0, 56 write_pos: 0, 57 read_wait_queue: WaitQueue::INIT, 58 write_wait_queue: WaitQueue::INIT, 59 data: [0; PIPE_BUFF_SIZE], 60 61 metadata: Metadata { 62 dev_id: 0, 63 inode_id: generate_inode_id(), 64 size: PIPE_BUFF_SIZE as i64, 65 blk_size: 0, 66 blocks: 0, 67 atime: TimeSpec::default(), 68 mtime: TimeSpec::default(), 69 ctime: TimeSpec::default(), 70 file_type: FileType::Pipe, 71 mode: ModeType::from_bits_truncate(0o666), 72 nlinks: 1, 73 uid: 0, 74 gid: 0, 75 raw_dev: 0, 76 }, 77 reader: 0, 78 writer: 0, 79 }; 80 let result = Arc::new(Self(SpinLock::new(inner))); 81 let mut guard = result.0.lock(); 82 guard.self_ref = Arc::downgrade(&result); 83 // 释放锁 84 drop(guard); //这一步其实不需要,只要离开作用域,guard生命周期结束,自会解锁 85 return result; 86 } 87 } 88 89 impl IndexNode for LockedPipeInode { 90 fn read_at( 91 &self, 92 _offset: usize, 93 len: usize, 94 buf: &mut [u8], 95 data: &mut FilePrivateData, 96 ) -> Result<usize, crate::syscall::SystemError> { 97 // 获取mode 98 let mode: FileMode; 99 if let FilePrivateData::Pipefs(pdata) = data { 100 mode = pdata.mode; 101 } else { 102 return Err(SystemError::EBADF); 103 } 104 105 if buf.len() < len { 106 return Err(SystemError::EINVAL); 107 } 108 // 加锁 109 let mut inode = self.0.lock(); 110 111 // 如果管道里面没有数据,则唤醒写端, 112 while inode.valid_cnt == 0 { 113 // 如果当前管道写者数为0,则返回EOF 114 if inode.writer == 0 { 115 return Ok(0); 116 } 117 118 inode 119 .write_wait_queue 120 .wakeup(Some(ProcessState::Blocked(true))); 121 122 // 如果为非阻塞管道,直接返回错误 123 if mode.contains(FileMode::O_NONBLOCK) { 124 drop(inode); 125 return Err(SystemError::EAGAIN_OR_EWOULDBLOCK); 126 } 127 128 // 否则在读等待队列中睡眠,并释放锁 129 unsafe { 130 let irq_guard = CurrentIrqArch::save_and_disable_irq(); 131 inode.read_wait_queue.sleep_without_schedule(); 132 drop(inode); 133 134 drop(irq_guard); 135 } 136 sched(); 137 inode = self.0.lock(); 138 } 139 140 let mut num = inode.valid_cnt as usize; 141 //决定要输出的字节 142 let start = inode.read_pos as usize; 143 //如果读端希望读取的字节数大于有效字节数,则输出有效字节 144 let mut end = (inode.valid_cnt as usize + inode.read_pos as usize) % PIPE_BUFF_SIZE; 145 //如果读端希望读取的字节数少于有效字节数,则输出希望读取的字节 146 if len < inode.valid_cnt as usize { 147 end = (len + inode.read_pos as usize) % PIPE_BUFF_SIZE; 148 num = len; 149 } 150 151 // 从管道拷贝数据到用户的缓冲区 152 153 if end < start { 154 buf[0..(PIPE_BUFF_SIZE - start)].copy_from_slice(&inode.data[start..PIPE_BUFF_SIZE]); 155 buf[(PIPE_BUFF_SIZE - start)..num].copy_from_slice(&inode.data[0..end]); 156 } else { 157 buf[0..num].copy_from_slice(&inode.data[start..end]); 158 } 159 160 //更新读位置以及valid_cnt 161 inode.read_pos = (inode.read_pos + num as i32) % PIPE_BUFF_SIZE as i32; 162 inode.valid_cnt -= num as i32; 163 164 //读完后解锁并唤醒等待在写等待队列中的进程 165 inode 166 .write_wait_queue 167 .wakeup(Some(ProcessState::Blocked(true))); 168 //返回读取的字节数 169 return Ok(num); 170 } 171 172 fn open( 173 &self, 174 data: &mut FilePrivateData, 175 mode: &crate::filesystem::vfs::file::FileMode, 176 ) -> Result<(), SystemError> { 177 let mut guard = self.0.lock(); 178 // 不能以读写方式打开管道 179 if mode.contains(FileMode::O_RDWR) { 180 return Err(SystemError::EACCES); 181 } 182 if mode.contains(FileMode::O_RDONLY) { 183 guard.reader += 1; 184 } 185 if mode.contains(FileMode::O_WRONLY) { 186 guard.writer += 1; 187 } 188 189 // 设置mode 190 *data = FilePrivateData::Pipefs(PipeFsPrivateData { mode: *mode }); 191 192 return Ok(()); 193 } 194 195 fn metadata(&self) -> Result<crate::filesystem::vfs::Metadata, SystemError> { 196 let inode = self.0.lock(); 197 let mut metadata = inode.metadata.clone(); 198 metadata.size = inode.data.len() as i64; 199 200 return Ok(metadata); 201 } 202 203 fn close(&self, data: &mut FilePrivateData) -> Result<(), SystemError> { 204 let mode: FileMode; 205 if let FilePrivateData::Pipefs(pipe_data) = data { 206 mode = pipe_data.mode; 207 } else { 208 return Err(SystemError::EBADF); 209 } 210 let mut guard = self.0.lock(); 211 212 // 写端关闭 213 if mode.contains(FileMode::O_WRONLY) { 214 assert!(guard.writer > 0); 215 guard.writer -= 1; 216 // 如果已经没有写端了,则唤醒读端 217 if guard.writer == 0 { 218 guard 219 .read_wait_queue 220 .wakeup_all(Some(ProcessState::Blocked(true))); 221 } 222 } 223 224 // 读端关闭 225 if mode.contains(FileMode::O_RDONLY) { 226 assert!(guard.reader > 0); 227 guard.reader -= 1; 228 // 如果已经没有写端了,则唤醒读端 229 if guard.reader == 0 { 230 guard 231 .write_wait_queue 232 .wakeup_all(Some(ProcessState::Blocked(true))); 233 } 234 } 235 236 return Ok(()); 237 } 238 239 fn write_at( 240 &self, 241 _offset: usize, 242 len: usize, 243 buf: &[u8], 244 data: &mut FilePrivateData, 245 ) -> Result<usize, crate::syscall::SystemError> { 246 // 获取mode 247 let mode: FileMode; 248 if let FilePrivateData::Pipefs(pdata) = data { 249 mode = pdata.mode; 250 } else { 251 return Err(SystemError::EBADF); 252 } 253 254 if buf.len() < len || len > PIPE_BUFF_SIZE { 255 return Err(SystemError::EINVAL); 256 } 257 // 加锁 258 259 let mut inode = self.0.lock(); 260 261 // TODO: 如果已经没有读端存在了,则向写端进程发送SIGPIPE信号 262 if inode.reader == 0 {} 263 264 // 如果管道空间不够 265 266 while len + inode.valid_cnt as usize > PIPE_BUFF_SIZE { 267 // 唤醒读端 268 inode 269 .read_wait_queue 270 .wakeup(Some(ProcessState::Blocked(true))); 271 272 // 如果为非阻塞管道,直接返回错误 273 if mode.contains(FileMode::O_NONBLOCK) { 274 drop(inode); 275 return Err(SystemError::ENOMEM); 276 } 277 278 // 解锁并睡眠 279 unsafe { 280 let irq_guard = CurrentIrqArch::save_and_disable_irq(); 281 inode.write_wait_queue.sleep_without_schedule(); 282 drop(inode); 283 drop(irq_guard); 284 } 285 sched(); 286 inode = self.0.lock(); 287 } 288 289 // 决定要输入的字节 290 let start = inode.write_pos as usize; 291 let end = (inode.write_pos as usize + len) % PIPE_BUFF_SIZE; 292 // 从用户的缓冲区拷贝数据到管道 293 294 if end < start { 295 inode.data[start..PIPE_BUFF_SIZE].copy_from_slice(&buf[0..(PIPE_BUFF_SIZE - start)]); 296 inode.data[0..end].copy_from_slice(&buf[(PIPE_BUFF_SIZE - start)..len]); 297 } else { 298 inode.data[start..end].copy_from_slice(&buf[0..len]); 299 } 300 // 更新写位置以及valid_cnt 301 inode.write_pos = (inode.write_pos + len as i32) % PIPE_BUFF_SIZE as i32; 302 inode.valid_cnt += len as i32; 303 304 // 读完后解锁并唤醒等待在读等待队列中的进程 305 inode 306 .read_wait_queue 307 .wakeup(Some(ProcessState::Blocked(true))); 308 // 返回写入的字节数 309 return Ok(len); 310 } 311 312 fn poll(&self) -> Result<PollStatus, crate::syscall::SystemError> { 313 return Ok(PollStatus::READ | PollStatus::WRITE); 314 } 315 316 fn as_any_ref(&self) -> &dyn core::any::Any { 317 self 318 } 319 320 fn get_entry_name_and_metadata( 321 &self, 322 ino: crate::filesystem::vfs::InodeId, 323 ) -> Result<(alloc::string::String, crate::filesystem::vfs::Metadata), SystemError> { 324 // 如果有条件,请在文件系统中使用高效的方式实现本接口,而不是依赖这个低效率的默认实现。 325 let name = self.get_entry_name(ino)?; 326 let entry = self.find(&name)?; 327 return Ok((name, entry.metadata()?)); 328 } 329 330 fn fs(&self) -> Arc<(dyn FileSystem)> { 331 todo!() 332 } 333 334 fn list(&self) -> Result<alloc::vec::Vec<alloc::string::String>, SystemError> { 335 return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP); 336 } 337 } 338