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, 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 132 inode.read_wait_queue.sleep_without_schedule(); 133 drop(inode); 134 135 drop(irq_guard); 136 } 137 sched(); 138 inode = self.0.lock(); 139 } 140 141 let mut num = inode.valid_cnt as usize; 142 //决定要输出的字节 143 let start = inode.read_pos as usize; 144 //如果读端希望读取的字节数大于有效字节数,则输出有效字节 145 let mut end = (inode.valid_cnt as usize + inode.read_pos as usize) % PIPE_BUFF_SIZE; 146 //如果读端希望读取的字节数少于有效字节数,则输出希望读取的字节 147 if len < inode.valid_cnt as usize { 148 end = (len + inode.read_pos as usize) % PIPE_BUFF_SIZE; 149 num = len; 150 } 151 152 // 从管道拷贝数据到用户的缓冲区 153 154 if end < start { 155 buf[0..(PIPE_BUFF_SIZE - start)].copy_from_slice(&inode.data[start..PIPE_BUFF_SIZE]); 156 buf[(PIPE_BUFF_SIZE - start)..num].copy_from_slice(&inode.data[0..end]); 157 } else { 158 buf[0..num].copy_from_slice(&inode.data[start..end]); 159 } 160 161 //更新读位置以及valid_cnt 162 inode.read_pos = (inode.read_pos + num as i32) % PIPE_BUFF_SIZE as i32; 163 inode.valid_cnt -= num as i32; 164 165 //读完后解锁并唤醒等待在写等待队列中的进程 166 inode 167 .write_wait_queue 168 .wakeup(Some(ProcessState::Blocked(true))); 169 //返回读取的字节数 170 return Ok(num); 171 } 172 173 fn open( 174 &self, 175 data: &mut FilePrivateData, 176 mode: &crate::filesystem::vfs::file::FileMode, 177 ) -> Result<(), SystemError> { 178 let mut guard = self.0.lock(); 179 // 不能以读写方式打开管道 180 if mode.contains(FileMode::O_RDWR) { 181 return Err(SystemError::EACCES); 182 } 183 if mode.contains(FileMode::O_RDONLY) { 184 guard.reader += 1; 185 } 186 if mode.contains(FileMode::O_WRONLY) { 187 guard.writer += 1; 188 } 189 190 // 设置mode 191 *data = FilePrivateData::Pipefs(PipeFsPrivateData { mode: *mode }); 192 193 return Ok(()); 194 } 195 196 fn metadata(&self) -> Result<crate::filesystem::vfs::Metadata, SystemError> { 197 let inode = self.0.lock(); 198 let mut metadata = inode.metadata.clone(); 199 metadata.size = inode.data.len() as i64; 200 201 return Ok(metadata); 202 } 203 204 fn close(&self, data: &mut FilePrivateData) -> Result<(), SystemError> { 205 let mode: FileMode; 206 if let FilePrivateData::Pipefs(pipe_data) = data { 207 mode = pipe_data.mode; 208 } else { 209 return Err(SystemError::EBADF); 210 } 211 let mut guard = self.0.lock(); 212 213 // 写端关闭 214 if mode.contains(FileMode::O_WRONLY) { 215 assert!(guard.writer > 0); 216 guard.writer -= 1; 217 // 如果已经没有写端了,则唤醒读端 218 if guard.writer == 0 { 219 guard 220 .read_wait_queue 221 .wakeup_all(Some(ProcessState::Blocked(true))); 222 } 223 } 224 225 // 读端关闭 226 if mode.contains(FileMode::O_RDONLY) { 227 assert!(guard.reader > 0); 228 guard.reader -= 1; 229 // 如果已经没有写端了,则唤醒读端 230 if guard.reader == 0 { 231 guard 232 .write_wait_queue 233 .wakeup_all(Some(ProcessState::Blocked(true))); 234 } 235 } 236 237 return Ok(()); 238 } 239 240 fn write_at( 241 &self, 242 _offset: usize, 243 len: usize, 244 buf: &[u8], 245 data: &mut FilePrivateData, 246 ) -> Result<usize, crate::syscall::SystemError> { 247 // 获取mode 248 let mode: FileMode; 249 if let FilePrivateData::Pipefs(pdata) = data { 250 mode = pdata.mode; 251 } else { 252 return Err(SystemError::EBADF); 253 } 254 255 if buf.len() < len || len > PIPE_BUFF_SIZE { 256 return Err(SystemError::EINVAL); 257 } 258 // 加锁 259 260 let mut inode = self.0.lock(); 261 262 // TODO: 如果已经没有读端存在了,则向写端进程发送SIGPIPE信号 263 if inode.reader == 0 {} 264 265 // 如果管道空间不够 266 267 while len + inode.valid_cnt as usize > PIPE_BUFF_SIZE { 268 // 唤醒读端 269 inode 270 .read_wait_queue 271 .wakeup(Some(ProcessState::Blocked(true))); 272 273 // 如果为非阻塞管道,直接返回错误 274 if mode.contains(FileMode::O_NONBLOCK) { 275 drop(inode); 276 return Err(SystemError::ENOMEM); 277 } 278 279 // 解锁并睡眠 280 unsafe { 281 let irq_guard = CurrentIrqArch::save_and_disable_irq(); 282 inode.write_wait_queue.sleep_without_schedule(); 283 drop(inode); 284 drop(irq_guard); 285 } 286 sched(); 287 inode = self.0.lock(); 288 } 289 290 // 决定要输入的字节 291 let start = inode.write_pos as usize; 292 let end = (inode.write_pos as usize + len) % PIPE_BUFF_SIZE; 293 // 从用户的缓冲区拷贝数据到管道 294 295 if end < start { 296 inode.data[start..PIPE_BUFF_SIZE].copy_from_slice(&buf[0..(PIPE_BUFF_SIZE - start)]); 297 inode.data[0..end].copy_from_slice(&buf[(PIPE_BUFF_SIZE - start)..len]); 298 } else { 299 inode.data[start..end].copy_from_slice(&buf[0..len]); 300 } 301 // 更新写位置以及valid_cnt 302 inode.write_pos = (inode.write_pos + len as i32) % PIPE_BUFF_SIZE as i32; 303 inode.valid_cnt += len as i32; 304 305 // 读完后解锁并唤醒等待在读等待队列中的进程 306 inode 307 .read_wait_queue 308 .wakeup(Some(ProcessState::Blocked(true))); 309 // 返回写入的字节数 310 return Ok(len); 311 } 312 313 fn as_any_ref(&self) -> &dyn core::any::Any { 314 self 315 } 316 317 fn get_entry_name_and_metadata( 318 &self, 319 ino: crate::filesystem::vfs::InodeId, 320 ) -> Result<(alloc::string::String, crate::filesystem::vfs::Metadata), SystemError> { 321 // 如果有条件,请在文件系统中使用高效的方式实现本接口,而不是依赖这个低效率的默认实现。 322 let name = self.get_entry_name(ino)?; 323 let entry = self.find(&name)?; 324 return Ok((name, entry.metadata()?)); 325 } 326 327 fn fs(&self) -> Arc<(dyn FileSystem)> { 328 todo!() 329 } 330 331 fn list(&self) -> Result<alloc::vec::Vec<alloc::string::String>, SystemError> { 332 return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP); 333 } 334 } 335