xref: /DragonOS/kernel/src/ipc/pipe.rs (revision f110d330d5493f383067b4e82ebbfb72f40457b2)
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