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