1 use crate::{ 2 arch::{sched::sched, CurrentIrqArch}, 3 exception::InterruptArch, 4 filesystem::vfs::{ 5 core::generate_inode_id, file::FileMode, FilePrivateData, FileSystem, FileType, IndexNode, 6 Metadata, PollStatus, 7 }, 8 include::bindings::bindings::PROC_INTERRUPTIBLE, 9 libs::{spinlock::SpinLock, wait_queue::WaitQueue}, 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: 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.write_wait_queue.wakeup(PROC_INTERRUPTIBLE.into()); 93 // 如果为非阻塞管道,直接返回错误 94 if inode.flags.contains(FileMode::O_NONBLOCK) { 95 drop(inode); 96 return Err(SystemError::EAGAIN_OR_EWOULDBLOCK); 97 } 98 // 否则在读等待队列中睡眠,并释放锁 99 unsafe { 100 let irq_guard = CurrentIrqArch::save_and_disable_irq(); 101 inode.read_wait_queue.sleep_without_schedule(); 102 drop(inode); 103 104 drop(irq_guard); 105 } 106 sched(); 107 inode = self.0.lock(); 108 } 109 110 let mut num = inode.valid_cnt as usize; 111 //决定要输出的字节 112 let start = inode.read_pos as usize; 113 //如果读端希望读取的字节数大于有效字节数,则输出有效字节 114 let mut end = (inode.valid_cnt as usize + inode.read_pos as usize) % PIPE_BUFF_SIZE; 115 //如果读端希望读取的字节数少于有效字节数,则输出希望读取的字节 116 if len < inode.valid_cnt as usize { 117 end = (len + inode.read_pos as usize) % PIPE_BUFF_SIZE; 118 num = len; 119 } 120 121 // 从管道拷贝数据到用户的缓冲区 122 123 if end < start { 124 buf[0..(PIPE_BUFF_SIZE - start)].copy_from_slice(&inode.data[start..PIPE_BUFF_SIZE]); 125 buf[(PIPE_BUFF_SIZE - start)..num].copy_from_slice(&inode.data[0..end]); 126 } else { 127 buf[0..num].copy_from_slice(&inode.data[start..end]); 128 } 129 130 //更新读位置以及valid_cnt 131 inode.read_pos = (inode.read_pos + num as i32) % PIPE_BUFF_SIZE as i32; 132 inode.valid_cnt -= num as i32; 133 134 //读完后解锁并唤醒等待在写等待队列中的进程 135 inode.write_wait_queue.wakeup(PROC_INTERRUPTIBLE.into()); 136 //返回读取的字节数 137 return Ok(num); 138 } 139 140 fn open( 141 &self, 142 _data: &mut FilePrivateData, 143 _mode: &crate::filesystem::vfs::file::FileMode, 144 ) -> Result<(), SystemError> { 145 return Ok(()); 146 } 147 148 fn metadata(&self) -> Result<crate::filesystem::vfs::Metadata, SystemError> { 149 let inode = self.0.lock(); 150 let mut metadata = inode.metadata.clone(); 151 metadata.size = inode.data.len() as i64; 152 153 return Ok(metadata); 154 } 155 156 fn close(&self, _data: &mut FilePrivateData) -> Result<(), SystemError> { 157 return Ok(()); 158 } 159 160 fn write_at( 161 &self, 162 _offset: usize, 163 len: usize, 164 buf: &[u8], 165 _data: &mut FilePrivateData, 166 ) -> Result<usize, crate::syscall::SystemError> { 167 if buf.len() < len || len > PIPE_BUFF_SIZE { 168 return Err(SystemError::EINVAL); 169 } 170 // 加锁 171 172 let mut inode = self.0.lock(); 173 174 // 如果管道空间不够 175 176 while len + inode.valid_cnt as usize > PIPE_BUFF_SIZE { 177 // 唤醒读端 178 inode.read_wait_queue.wakeup(PROC_INTERRUPTIBLE.into()); 179 // 如果为非阻塞管道,直接返回错误 180 if inode.flags.contains(FileMode::O_NONBLOCK) { 181 drop(inode); 182 return Err(SystemError::ENOMEM); 183 } 184 // 解锁并睡眠 185 unsafe { 186 let irq_guard = CurrentIrqArch::save_and_disable_irq(); 187 inode.write_wait_queue.sleep_without_schedule(); 188 drop(inode); 189 drop(irq_guard); 190 } 191 sched(); 192 inode = self.0.lock(); 193 } 194 195 // 决定要输入的字节 196 let start = inode.write_pos as usize; 197 let end = (inode.write_pos as usize + len) % PIPE_BUFF_SIZE; 198 // 从用户的缓冲区拷贝数据到管道 199 200 if end < start { 201 inode.data[start..PIPE_BUFF_SIZE].copy_from_slice(&buf[0..(PIPE_BUFF_SIZE - start)]); 202 inode.data[0..end].copy_from_slice(&buf[(PIPE_BUFF_SIZE - start)..len]); 203 } else { 204 inode.data[start..end].copy_from_slice(&buf[0..len]); 205 } 206 // 更新写位置以及valid_cnt 207 inode.write_pos = (inode.write_pos + len as i32) % PIPE_BUFF_SIZE as i32; 208 inode.valid_cnt += len as i32; 209 210 // 读完后解锁并唤醒等待在读等待队列中的进程 211 inode.read_wait_queue.wakeup(PROC_INTERRUPTIBLE.into()); 212 // 返回写入的字节数 213 return Ok(len); 214 } 215 216 fn poll(&self) -> Result<PollStatus, crate::syscall::SystemError> { 217 return Ok(PollStatus::READ | PollStatus::WRITE); 218 } 219 220 fn as_any_ref(&self) -> &dyn core::any::Any { 221 self 222 } 223 224 fn get_entry_name_and_metadata( 225 &self, 226 ino: crate::filesystem::vfs::InodeId, 227 ) -> Result<(alloc::string::String, crate::filesystem::vfs::Metadata), SystemError> { 228 // 如果有条件,请在文件系统中使用高效的方式实现本接口,而不是依赖这个低效率的默认实现。 229 let name = self.get_entry_name(ino)?; 230 let entry = self.find(&name)?; 231 return Ok((name, entry.metadata()?)); 232 } 233 234 fn fs(&self) -> Arc<(dyn FileSystem)> { 235 todo!() 236 } 237 238 fn list(&self) -> Result<alloc::vec::Vec<alloc::string::String>, SystemError> { 239 return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP); 240 } 241 } 242