xref: /DragonOS/kernel/src/ipc/pipe.rs (revision 6b4e7a2972cc06663754c0e35a0e541987006fa4)
1f678331aShanjiezhou use crate::{
2f678331aShanjiezhou     arch::{sched::sched, CurrentIrqArch},
3f678331aShanjiezhou     exception::InterruptArch,
4f678331aShanjiezhou     filesystem::vfs::{
5*6b4e7a29SLoGin         core::generate_inode_id, file::FileMode, syscall::ModeType, FilePrivateData, FileSystem,
6*6b4e7a29SLoGin         FileType, IndexNode, Metadata, PollStatus,
7f678331aShanjiezhou     },
8f678331aShanjiezhou     libs::{spinlock::SpinLock, wait_queue::WaitQueue},
91496ba7bSLoGin     process::ProcessState,
10f678331aShanjiezhou     syscall::SystemError,
11f678331aShanjiezhou     time::TimeSpec,
12f678331aShanjiezhou };
13f678331aShanjiezhou 
14f678331aShanjiezhou use alloc::sync::{Arc, Weak};
15f678331aShanjiezhou 
16f678331aShanjiezhou /// 我们设定pipe_buff的总大小为1024字节
17f678331aShanjiezhou const PIPE_BUFF_SIZE: usize = 1024;
18f678331aShanjiezhou 
19f678331aShanjiezhou /// @brief 管道文件i节点(锁)
20f678331aShanjiezhou #[derive(Debug)]
21f678331aShanjiezhou pub struct LockedPipeInode(SpinLock<InnerPipeInode>);
22f678331aShanjiezhou 
23f678331aShanjiezhou /// @brief 管道文件i节点(无锁)
24f678331aShanjiezhou #[derive(Debug)]
25f678331aShanjiezhou pub struct InnerPipeInode {
26f678331aShanjiezhou     self_ref: Weak<LockedPipeInode>,
27f678331aShanjiezhou     valid_cnt: i32,
28f678331aShanjiezhou     read_pos: i32,
29f678331aShanjiezhou     write_pos: i32,
30f678331aShanjiezhou     read_wait_queue: WaitQueue,
31f678331aShanjiezhou     write_wait_queue: WaitQueue,
32f678331aShanjiezhou     data: [u8; PIPE_BUFF_SIZE],
33f678331aShanjiezhou     /// INode 元数据
34f678331aShanjiezhou     metadata: Metadata,
3522c9db31Shanjiezhou     flags: FileMode,
36f678331aShanjiezhou }
37f678331aShanjiezhou 
38f678331aShanjiezhou impl LockedPipeInode {
3922c9db31Shanjiezhou     pub fn new(flags: FileMode) -> Arc<Self> {
40f678331aShanjiezhou         let inner = InnerPipeInode {
41f678331aShanjiezhou             self_ref: Weak::default(),
42f678331aShanjiezhou             valid_cnt: 0,
43f678331aShanjiezhou             read_pos: 0,
44f678331aShanjiezhou             write_pos: 0,
45f678331aShanjiezhou             read_wait_queue: WaitQueue::INIT,
46f678331aShanjiezhou             write_wait_queue: WaitQueue::INIT,
47f678331aShanjiezhou             data: [0; PIPE_BUFF_SIZE],
48f678331aShanjiezhou 
49f678331aShanjiezhou             metadata: Metadata {
50f678331aShanjiezhou                 dev_id: 0,
51f678331aShanjiezhou                 inode_id: generate_inode_id(),
5222c9db31Shanjiezhou                 size: PIPE_BUFF_SIZE as i64,
53f678331aShanjiezhou                 blk_size: 0,
54f678331aShanjiezhou                 blocks: 0,
55f678331aShanjiezhou                 atime: TimeSpec::default(),
56f678331aShanjiezhou                 mtime: TimeSpec::default(),
57f678331aShanjiezhou                 ctime: TimeSpec::default(),
58f678331aShanjiezhou                 file_type: FileType::Pipe,
59*6b4e7a29SLoGin                 mode: ModeType::from_bits_truncate(0o666),
60f678331aShanjiezhou                 nlinks: 1,
61f678331aShanjiezhou                 uid: 0,
62f678331aShanjiezhou                 gid: 0,
63f678331aShanjiezhou                 raw_dev: 0,
64f678331aShanjiezhou             },
6522c9db31Shanjiezhou             flags,
66f678331aShanjiezhou         };
67f678331aShanjiezhou         let result = Arc::new(Self(SpinLock::new(inner)));
68f678331aShanjiezhou         let mut guard = result.0.lock();
69f678331aShanjiezhou         guard.self_ref = Arc::downgrade(&result);
70f678331aShanjiezhou         // 释放锁
71f678331aShanjiezhou         drop(guard); //这一步其实不需要,只要离开作用域,guard生命周期结束,自会解锁
72f678331aShanjiezhou         return result;
73f678331aShanjiezhou     }
74f678331aShanjiezhou }
75f678331aShanjiezhou 
76f678331aShanjiezhou impl IndexNode for LockedPipeInode {
77f678331aShanjiezhou     fn read_at(
78f678331aShanjiezhou         &self,
79f678331aShanjiezhou         _offset: usize,
80f678331aShanjiezhou         len: usize,
81f678331aShanjiezhou         buf: &mut [u8],
82f678331aShanjiezhou         _data: &mut FilePrivateData,
83f678331aShanjiezhou     ) -> Result<usize, crate::syscall::SystemError> {
84f678331aShanjiezhou         if buf.len() < len {
85f678331aShanjiezhou             return Err(SystemError::EINVAL);
86f678331aShanjiezhou         }
87f678331aShanjiezhou         // 加锁
88f678331aShanjiezhou         let mut inode = self.0.lock();
89f678331aShanjiezhou 
90f678331aShanjiezhou         // 如果管道里面没有数据,则唤醒写端,
91f678331aShanjiezhou         while inode.valid_cnt == 0 {
921496ba7bSLoGin             inode
931496ba7bSLoGin                 .write_wait_queue
941496ba7bSLoGin                 .wakeup(Some(ProcessState::Blocked(true)));
951496ba7bSLoGin 
9622c9db31Shanjiezhou             // 如果为非阻塞管道,直接返回错误
9722c9db31Shanjiezhou             if inode.flags.contains(FileMode::O_NONBLOCK) {
9822c9db31Shanjiezhou                 drop(inode);
9922c9db31Shanjiezhou                 return Err(SystemError::EAGAIN_OR_EWOULDBLOCK);
10022c9db31Shanjiezhou             }
1011496ba7bSLoGin 
10222c9db31Shanjiezhou             // 否则在读等待队列中睡眠,并释放锁
103f678331aShanjiezhou             unsafe {
104f678331aShanjiezhou                 let irq_guard = CurrentIrqArch::save_and_disable_irq();
105f678331aShanjiezhou                 inode.read_wait_queue.sleep_without_schedule();
106f678331aShanjiezhou                 drop(inode);
107f678331aShanjiezhou 
108f678331aShanjiezhou                 drop(irq_guard);
109f678331aShanjiezhou             }
110f678331aShanjiezhou             sched();
111f678331aShanjiezhou             inode = self.0.lock();
112f678331aShanjiezhou         }
113f678331aShanjiezhou 
114f678331aShanjiezhou         let mut num = inode.valid_cnt as usize;
115f678331aShanjiezhou         //决定要输出的字节
116f678331aShanjiezhou         let start = inode.read_pos as usize;
117f678331aShanjiezhou         //如果读端希望读取的字节数大于有效字节数,则输出有效字节
118f678331aShanjiezhou         let mut end = (inode.valid_cnt as usize + inode.read_pos as usize) % PIPE_BUFF_SIZE;
119f678331aShanjiezhou         //如果读端希望读取的字节数少于有效字节数,则输出希望读取的字节
120f678331aShanjiezhou         if len < inode.valid_cnt as usize {
121f678331aShanjiezhou             end = (len + inode.read_pos as usize) % PIPE_BUFF_SIZE;
122f678331aShanjiezhou             num = len;
123f678331aShanjiezhou         }
124f678331aShanjiezhou 
125f678331aShanjiezhou         // 从管道拷贝数据到用户的缓冲区
126f678331aShanjiezhou 
127f678331aShanjiezhou         if end < start {
128f678331aShanjiezhou             buf[0..(PIPE_BUFF_SIZE - start)].copy_from_slice(&inode.data[start..PIPE_BUFF_SIZE]);
129f678331aShanjiezhou             buf[(PIPE_BUFF_SIZE - start)..num].copy_from_slice(&inode.data[0..end]);
130f678331aShanjiezhou         } else {
131f678331aShanjiezhou             buf[0..num].copy_from_slice(&inode.data[start..end]);
132f678331aShanjiezhou         }
133f678331aShanjiezhou 
134f678331aShanjiezhou         //更新读位置以及valid_cnt
135f678331aShanjiezhou         inode.read_pos = (inode.read_pos + num as i32) % PIPE_BUFF_SIZE as i32;
136f678331aShanjiezhou         inode.valid_cnt -= num as i32;
137f678331aShanjiezhou 
138f678331aShanjiezhou         //读完后解锁并唤醒等待在写等待队列中的进程
1391496ba7bSLoGin         inode
1401496ba7bSLoGin             .write_wait_queue
1411496ba7bSLoGin             .wakeup(Some(ProcessState::Blocked(true)));
142f678331aShanjiezhou         //返回读取的字节数
143f678331aShanjiezhou         return Ok(num);
144f678331aShanjiezhou     }
145f678331aShanjiezhou 
146f678331aShanjiezhou     fn open(
147f678331aShanjiezhou         &self,
148f678331aShanjiezhou         _data: &mut FilePrivateData,
149f678331aShanjiezhou         _mode: &crate::filesystem::vfs::file::FileMode,
150f678331aShanjiezhou     ) -> Result<(), SystemError> {
151f678331aShanjiezhou         return Ok(());
152f678331aShanjiezhou     }
153f678331aShanjiezhou 
154f678331aShanjiezhou     fn metadata(&self) -> Result<crate::filesystem::vfs::Metadata, SystemError> {
155f678331aShanjiezhou         let inode = self.0.lock();
156f678331aShanjiezhou         let mut metadata = inode.metadata.clone();
157f678331aShanjiezhou         metadata.size = inode.data.len() as i64;
158f678331aShanjiezhou 
159f678331aShanjiezhou         return Ok(metadata);
160f678331aShanjiezhou     }
161f678331aShanjiezhou 
162f678331aShanjiezhou     fn close(&self, _data: &mut FilePrivateData) -> Result<(), SystemError> {
163f678331aShanjiezhou         return Ok(());
164f678331aShanjiezhou     }
165f678331aShanjiezhou 
166f678331aShanjiezhou     fn write_at(
167f678331aShanjiezhou         &self,
168f678331aShanjiezhou         _offset: usize,
169f678331aShanjiezhou         len: usize,
170f678331aShanjiezhou         buf: &[u8],
171f678331aShanjiezhou         _data: &mut FilePrivateData,
172f678331aShanjiezhou     ) -> Result<usize, crate::syscall::SystemError> {
173f678331aShanjiezhou         if buf.len() < len || len > PIPE_BUFF_SIZE {
174f678331aShanjiezhou             return Err(SystemError::EINVAL);
175f678331aShanjiezhou         }
176f678331aShanjiezhou         // 加锁
177f678331aShanjiezhou 
178f678331aShanjiezhou         let mut inode = self.0.lock();
179f678331aShanjiezhou 
180f678331aShanjiezhou         // 如果管道空间不够
181f678331aShanjiezhou 
182f678331aShanjiezhou         while len + inode.valid_cnt as usize > PIPE_BUFF_SIZE {
183f678331aShanjiezhou             // 唤醒读端
1841496ba7bSLoGin             inode
1851496ba7bSLoGin                 .read_wait_queue
1861496ba7bSLoGin                 .wakeup(Some(ProcessState::Blocked(true)));
1871496ba7bSLoGin 
18822c9db31Shanjiezhou             // 如果为非阻塞管道,直接返回错误
18922c9db31Shanjiezhou             if inode.flags.contains(FileMode::O_NONBLOCK) {
19022c9db31Shanjiezhou                 drop(inode);
19122c9db31Shanjiezhou                 return Err(SystemError::ENOMEM);
19222c9db31Shanjiezhou             }
1931496ba7bSLoGin 
194f678331aShanjiezhou             // 解锁并睡眠
195f678331aShanjiezhou             unsafe {
196f678331aShanjiezhou                 let irq_guard = CurrentIrqArch::save_and_disable_irq();
197f678331aShanjiezhou                 inode.write_wait_queue.sleep_without_schedule();
198f678331aShanjiezhou                 drop(inode);
199f678331aShanjiezhou                 drop(irq_guard);
200f678331aShanjiezhou             }
201f678331aShanjiezhou             sched();
202f678331aShanjiezhou             inode = self.0.lock();
203f678331aShanjiezhou         }
204f678331aShanjiezhou 
205f678331aShanjiezhou         // 决定要输入的字节
206f678331aShanjiezhou         let start = inode.write_pos as usize;
207f678331aShanjiezhou         let end = (inode.write_pos as usize + len) % PIPE_BUFF_SIZE;
208f678331aShanjiezhou         // 从用户的缓冲区拷贝数据到管道
209f678331aShanjiezhou 
210f678331aShanjiezhou         if end < start {
211f678331aShanjiezhou             inode.data[start..PIPE_BUFF_SIZE].copy_from_slice(&buf[0..(PIPE_BUFF_SIZE - start)]);
212f678331aShanjiezhou             inode.data[0..end].copy_from_slice(&buf[(PIPE_BUFF_SIZE - start)..len]);
213f678331aShanjiezhou         } else {
214f678331aShanjiezhou             inode.data[start..end].copy_from_slice(&buf[0..len]);
215f678331aShanjiezhou         }
216f678331aShanjiezhou         // 更新写位置以及valid_cnt
217f678331aShanjiezhou         inode.write_pos = (inode.write_pos + len as i32) % PIPE_BUFF_SIZE as i32;
218f678331aShanjiezhou         inode.valid_cnt += len as i32;
219f678331aShanjiezhou 
220f678331aShanjiezhou         // 读完后解锁并唤醒等待在读等待队列中的进程
2211496ba7bSLoGin         inode
2221496ba7bSLoGin             .read_wait_queue
2231496ba7bSLoGin             .wakeup(Some(ProcessState::Blocked(true)));
224f678331aShanjiezhou         // 返回写入的字节数
225f678331aShanjiezhou         return Ok(len);
226f678331aShanjiezhou     }
227f678331aShanjiezhou 
228f678331aShanjiezhou     fn poll(&self) -> Result<PollStatus, crate::syscall::SystemError> {
229f678331aShanjiezhou         return Ok(PollStatus::READ | PollStatus::WRITE);
230f678331aShanjiezhou     }
231f678331aShanjiezhou 
232f678331aShanjiezhou     fn as_any_ref(&self) -> &dyn core::any::Any {
233f678331aShanjiezhou         self
234f678331aShanjiezhou     }
235f678331aShanjiezhou 
236f678331aShanjiezhou     fn get_entry_name_and_metadata(
237f678331aShanjiezhou         &self,
238f678331aShanjiezhou         ino: crate::filesystem::vfs::InodeId,
239f678331aShanjiezhou     ) -> Result<(alloc::string::String, crate::filesystem::vfs::Metadata), SystemError> {
240f678331aShanjiezhou         // 如果有条件,请在文件系统中使用高效的方式实现本接口,而不是依赖这个低效率的默认实现。
241f678331aShanjiezhou         let name = self.get_entry_name(ino)?;
242f678331aShanjiezhou         let entry = self.find(&name)?;
243f678331aShanjiezhou         return Ok((name, entry.metadata()?));
244f678331aShanjiezhou     }
245f678331aShanjiezhou 
246f678331aShanjiezhou     fn fs(&self) -> Arc<(dyn FileSystem)> {
247f678331aShanjiezhou         todo!()
248f678331aShanjiezhou     }
249f678331aShanjiezhou 
250f678331aShanjiezhou     fn list(&self) -> Result<alloc::vec::Vec<alloc::string::String>, SystemError> {
251f678331aShanjiezhou         return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP);
252f678331aShanjiezhou     }
253f678331aShanjiezhou }
254