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