xref: /DragonOS/kernel/src/ipc/pipe.rs (revision 876cb89ecf7c1bf1646bfc392efcbafacad2262f)
1f678331aShanjiezhou use crate::{
2f678331aShanjiezhou     arch::{sched::sched, CurrentIrqArch},
3f678331aShanjiezhou     exception::InterruptArch,
4f678331aShanjiezhou     filesystem::vfs::{
56b4e7a29SLoGin         core::generate_inode_id, file::FileMode, syscall::ModeType, FilePrivateData, FileSystem,
66b4e7a29SLoGin         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 
19*876cb89eSGnoCiYeH #[derive(Debug, Clone)]
20*876cb89eSGnoCiYeH pub struct PipeFsPrivateData {
21*876cb89eSGnoCiYeH     mode: FileMode,
22*876cb89eSGnoCiYeH }
23*876cb89eSGnoCiYeH 
24*876cb89eSGnoCiYeH impl PipeFsPrivateData {
25*876cb89eSGnoCiYeH     pub fn new(mode: FileMode) -> Self {
26*876cb89eSGnoCiYeH         return PipeFsPrivateData { mode: mode };
27*876cb89eSGnoCiYeH     }
28*876cb89eSGnoCiYeH }
29*876cb89eSGnoCiYeH 
30f678331aShanjiezhou /// @brief 管道文件i节点(锁)
31f678331aShanjiezhou #[derive(Debug)]
32f678331aShanjiezhou pub struct LockedPipeInode(SpinLock<InnerPipeInode>);
33f678331aShanjiezhou 
34f678331aShanjiezhou /// @brief 管道文件i节点(无锁)
35f678331aShanjiezhou #[derive(Debug)]
36f678331aShanjiezhou pub struct InnerPipeInode {
37f678331aShanjiezhou     self_ref: Weak<LockedPipeInode>,
38f678331aShanjiezhou     valid_cnt: i32,
39f678331aShanjiezhou     read_pos: i32,
40f678331aShanjiezhou     write_pos: i32,
41f678331aShanjiezhou     read_wait_queue: WaitQueue,
42f678331aShanjiezhou     write_wait_queue: WaitQueue,
43f678331aShanjiezhou     data: [u8; PIPE_BUFF_SIZE],
44f678331aShanjiezhou     /// INode 元数据
45f678331aShanjiezhou     metadata: Metadata,
46*876cb89eSGnoCiYeH     reader: u32,
47*876cb89eSGnoCiYeH     writer: u32,
48f678331aShanjiezhou }
49f678331aShanjiezhou 
50f678331aShanjiezhou impl LockedPipeInode {
51*876cb89eSGnoCiYeH     pub fn new() -> Arc<Self> {
52f678331aShanjiezhou         let inner = InnerPipeInode {
53f678331aShanjiezhou             self_ref: Weak::default(),
54f678331aShanjiezhou             valid_cnt: 0,
55f678331aShanjiezhou             read_pos: 0,
56f678331aShanjiezhou             write_pos: 0,
57f678331aShanjiezhou             read_wait_queue: WaitQueue::INIT,
58f678331aShanjiezhou             write_wait_queue: WaitQueue::INIT,
59f678331aShanjiezhou             data: [0; PIPE_BUFF_SIZE],
60f678331aShanjiezhou 
61f678331aShanjiezhou             metadata: Metadata {
62f678331aShanjiezhou                 dev_id: 0,
63f678331aShanjiezhou                 inode_id: generate_inode_id(),
6422c9db31Shanjiezhou                 size: PIPE_BUFF_SIZE as i64,
65f678331aShanjiezhou                 blk_size: 0,
66f678331aShanjiezhou                 blocks: 0,
67f678331aShanjiezhou                 atime: TimeSpec::default(),
68f678331aShanjiezhou                 mtime: TimeSpec::default(),
69f678331aShanjiezhou                 ctime: TimeSpec::default(),
70f678331aShanjiezhou                 file_type: FileType::Pipe,
716b4e7a29SLoGin                 mode: ModeType::from_bits_truncate(0o666),
72f678331aShanjiezhou                 nlinks: 1,
73f678331aShanjiezhou                 uid: 0,
74f678331aShanjiezhou                 gid: 0,
75f678331aShanjiezhou                 raw_dev: 0,
76f678331aShanjiezhou             },
77*876cb89eSGnoCiYeH             reader: 0,
78*876cb89eSGnoCiYeH             writer: 0,
79f678331aShanjiezhou         };
80f678331aShanjiezhou         let result = Arc::new(Self(SpinLock::new(inner)));
81f678331aShanjiezhou         let mut guard = result.0.lock();
82f678331aShanjiezhou         guard.self_ref = Arc::downgrade(&result);
83f678331aShanjiezhou         // 释放锁
84f678331aShanjiezhou         drop(guard); //这一步其实不需要,只要离开作用域,guard生命周期结束,自会解锁
85f678331aShanjiezhou         return result;
86f678331aShanjiezhou     }
87f678331aShanjiezhou }
88f678331aShanjiezhou 
89f678331aShanjiezhou impl IndexNode for LockedPipeInode {
90f678331aShanjiezhou     fn read_at(
91f678331aShanjiezhou         &self,
92f678331aShanjiezhou         _offset: usize,
93f678331aShanjiezhou         len: usize,
94f678331aShanjiezhou         buf: &mut [u8],
95*876cb89eSGnoCiYeH         data: &mut FilePrivateData,
96f678331aShanjiezhou     ) -> Result<usize, crate::syscall::SystemError> {
97*876cb89eSGnoCiYeH         // 获取mode
98*876cb89eSGnoCiYeH         let mode: FileMode;
99*876cb89eSGnoCiYeH         if let FilePrivateData::Pipefs(pdata) = data {
100*876cb89eSGnoCiYeH             mode = pdata.mode;
101*876cb89eSGnoCiYeH         } else {
102*876cb89eSGnoCiYeH             return Err(SystemError::EBADF);
103*876cb89eSGnoCiYeH         }
104*876cb89eSGnoCiYeH 
105f678331aShanjiezhou         if buf.len() < len {
106f678331aShanjiezhou             return Err(SystemError::EINVAL);
107f678331aShanjiezhou         }
108f678331aShanjiezhou         // 加锁
109f678331aShanjiezhou         let mut inode = self.0.lock();
110f678331aShanjiezhou 
111f678331aShanjiezhou         // 如果管道里面没有数据,则唤醒写端,
112f678331aShanjiezhou         while inode.valid_cnt == 0 {
113*876cb89eSGnoCiYeH             // 如果当前管道写者数为0,则返回EOF
114*876cb89eSGnoCiYeH             if inode.writer == 0 {
115*876cb89eSGnoCiYeH                 return Ok(0);
116*876cb89eSGnoCiYeH             }
117*876cb89eSGnoCiYeH 
1181496ba7bSLoGin             inode
1191496ba7bSLoGin                 .write_wait_queue
1201496ba7bSLoGin                 .wakeup(Some(ProcessState::Blocked(true)));
1211496ba7bSLoGin 
12222c9db31Shanjiezhou             // 如果为非阻塞管道,直接返回错误
123*876cb89eSGnoCiYeH             if mode.contains(FileMode::O_NONBLOCK) {
12422c9db31Shanjiezhou                 drop(inode);
12522c9db31Shanjiezhou                 return Err(SystemError::EAGAIN_OR_EWOULDBLOCK);
12622c9db31Shanjiezhou             }
1271496ba7bSLoGin 
12822c9db31Shanjiezhou             // 否则在读等待队列中睡眠,并释放锁
129f678331aShanjiezhou             unsafe {
130f678331aShanjiezhou                 let irq_guard = CurrentIrqArch::save_and_disable_irq();
131f678331aShanjiezhou                 inode.read_wait_queue.sleep_without_schedule();
132f678331aShanjiezhou                 drop(inode);
133f678331aShanjiezhou 
134f678331aShanjiezhou                 drop(irq_guard);
135f678331aShanjiezhou             }
136f678331aShanjiezhou             sched();
137f678331aShanjiezhou             inode = self.0.lock();
138f678331aShanjiezhou         }
139f678331aShanjiezhou 
140f678331aShanjiezhou         let mut num = inode.valid_cnt as usize;
141f678331aShanjiezhou         //决定要输出的字节
142f678331aShanjiezhou         let start = inode.read_pos as usize;
143f678331aShanjiezhou         //如果读端希望读取的字节数大于有效字节数,则输出有效字节
144f678331aShanjiezhou         let mut end = (inode.valid_cnt as usize + inode.read_pos as usize) % PIPE_BUFF_SIZE;
145f678331aShanjiezhou         //如果读端希望读取的字节数少于有效字节数,则输出希望读取的字节
146f678331aShanjiezhou         if len < inode.valid_cnt as usize {
147f678331aShanjiezhou             end = (len + inode.read_pos as usize) % PIPE_BUFF_SIZE;
148f678331aShanjiezhou             num = len;
149f678331aShanjiezhou         }
150f678331aShanjiezhou 
151f678331aShanjiezhou         // 从管道拷贝数据到用户的缓冲区
152f678331aShanjiezhou 
153f678331aShanjiezhou         if end < start {
154f678331aShanjiezhou             buf[0..(PIPE_BUFF_SIZE - start)].copy_from_slice(&inode.data[start..PIPE_BUFF_SIZE]);
155f678331aShanjiezhou             buf[(PIPE_BUFF_SIZE - start)..num].copy_from_slice(&inode.data[0..end]);
156f678331aShanjiezhou         } else {
157f678331aShanjiezhou             buf[0..num].copy_from_slice(&inode.data[start..end]);
158f678331aShanjiezhou         }
159f678331aShanjiezhou 
160f678331aShanjiezhou         //更新读位置以及valid_cnt
161f678331aShanjiezhou         inode.read_pos = (inode.read_pos + num as i32) % PIPE_BUFF_SIZE as i32;
162f678331aShanjiezhou         inode.valid_cnt -= num as i32;
163f678331aShanjiezhou 
164f678331aShanjiezhou         //读完后解锁并唤醒等待在写等待队列中的进程
1651496ba7bSLoGin         inode
1661496ba7bSLoGin             .write_wait_queue
1671496ba7bSLoGin             .wakeup(Some(ProcessState::Blocked(true)));
168f678331aShanjiezhou         //返回读取的字节数
169f678331aShanjiezhou         return Ok(num);
170f678331aShanjiezhou     }
171f678331aShanjiezhou 
172f678331aShanjiezhou     fn open(
173f678331aShanjiezhou         &self,
174*876cb89eSGnoCiYeH         data: &mut FilePrivateData,
175*876cb89eSGnoCiYeH         mode: &crate::filesystem::vfs::file::FileMode,
176f678331aShanjiezhou     ) -> Result<(), SystemError> {
177*876cb89eSGnoCiYeH         let mut guard = self.0.lock();
178*876cb89eSGnoCiYeH         // 不能以读写方式打开管道
179*876cb89eSGnoCiYeH         if mode.contains(FileMode::O_RDWR) {
180*876cb89eSGnoCiYeH             return Err(SystemError::EACCES);
181*876cb89eSGnoCiYeH         }
182*876cb89eSGnoCiYeH         if mode.contains(FileMode::O_RDONLY) {
183*876cb89eSGnoCiYeH             guard.reader += 1;
184*876cb89eSGnoCiYeH         }
185*876cb89eSGnoCiYeH         if mode.contains(FileMode::O_WRONLY) {
186*876cb89eSGnoCiYeH             guard.writer += 1;
187*876cb89eSGnoCiYeH         }
188*876cb89eSGnoCiYeH 
189*876cb89eSGnoCiYeH         // 设置mode
190*876cb89eSGnoCiYeH         *data = FilePrivateData::Pipefs(PipeFsPrivateData { mode: *mode });
191*876cb89eSGnoCiYeH 
192f678331aShanjiezhou         return Ok(());
193f678331aShanjiezhou     }
194f678331aShanjiezhou 
195f678331aShanjiezhou     fn metadata(&self) -> Result<crate::filesystem::vfs::Metadata, SystemError> {
196f678331aShanjiezhou         let inode = self.0.lock();
197f678331aShanjiezhou         let mut metadata = inode.metadata.clone();
198f678331aShanjiezhou         metadata.size = inode.data.len() as i64;
199f678331aShanjiezhou 
200f678331aShanjiezhou         return Ok(metadata);
201f678331aShanjiezhou     }
202f678331aShanjiezhou 
203*876cb89eSGnoCiYeH     fn close(&self, data: &mut FilePrivateData) -> Result<(), SystemError> {
204*876cb89eSGnoCiYeH         let mode: FileMode;
205*876cb89eSGnoCiYeH         if let FilePrivateData::Pipefs(pipe_data) = data {
206*876cb89eSGnoCiYeH             mode = pipe_data.mode;
207*876cb89eSGnoCiYeH         } else {
208*876cb89eSGnoCiYeH             return Err(SystemError::EBADF);
209*876cb89eSGnoCiYeH         }
210*876cb89eSGnoCiYeH         let mut guard = self.0.lock();
211*876cb89eSGnoCiYeH 
212*876cb89eSGnoCiYeH         // 写端关闭
213*876cb89eSGnoCiYeH         if mode.contains(FileMode::O_WRONLY) {
214*876cb89eSGnoCiYeH             assert!(guard.writer > 0);
215*876cb89eSGnoCiYeH             guard.writer -= 1;
216*876cb89eSGnoCiYeH             // 如果已经没有写端了,则唤醒读端
217*876cb89eSGnoCiYeH             if guard.writer == 0 {
218*876cb89eSGnoCiYeH                 guard
219*876cb89eSGnoCiYeH                     .read_wait_queue
220*876cb89eSGnoCiYeH                     .wakeup_all(Some(ProcessState::Blocked(true)));
221*876cb89eSGnoCiYeH             }
222*876cb89eSGnoCiYeH         }
223*876cb89eSGnoCiYeH 
224*876cb89eSGnoCiYeH         // 读端关闭
225*876cb89eSGnoCiYeH         if mode.contains(FileMode::O_RDONLY) {
226*876cb89eSGnoCiYeH             assert!(guard.reader > 0);
227*876cb89eSGnoCiYeH             guard.reader -= 1;
228*876cb89eSGnoCiYeH             // 如果已经没有写端了,则唤醒读端
229*876cb89eSGnoCiYeH             if guard.reader == 0 {
230*876cb89eSGnoCiYeH                 guard
231*876cb89eSGnoCiYeH                     .write_wait_queue
232*876cb89eSGnoCiYeH                     .wakeup_all(Some(ProcessState::Blocked(true)));
233*876cb89eSGnoCiYeH             }
234*876cb89eSGnoCiYeH         }
235*876cb89eSGnoCiYeH 
236f678331aShanjiezhou         return Ok(());
237f678331aShanjiezhou     }
238f678331aShanjiezhou 
239f678331aShanjiezhou     fn write_at(
240f678331aShanjiezhou         &self,
241f678331aShanjiezhou         _offset: usize,
242f678331aShanjiezhou         len: usize,
243f678331aShanjiezhou         buf: &[u8],
244*876cb89eSGnoCiYeH         data: &mut FilePrivateData,
245f678331aShanjiezhou     ) -> Result<usize, crate::syscall::SystemError> {
246*876cb89eSGnoCiYeH         // 获取mode
247*876cb89eSGnoCiYeH         let mode: FileMode;
248*876cb89eSGnoCiYeH         if let FilePrivateData::Pipefs(pdata) = data {
249*876cb89eSGnoCiYeH             mode = pdata.mode;
250*876cb89eSGnoCiYeH         } else {
251*876cb89eSGnoCiYeH             return Err(SystemError::EBADF);
252*876cb89eSGnoCiYeH         }
253*876cb89eSGnoCiYeH 
254f678331aShanjiezhou         if buf.len() < len || len > PIPE_BUFF_SIZE {
255f678331aShanjiezhou             return Err(SystemError::EINVAL);
256f678331aShanjiezhou         }
257f678331aShanjiezhou         // 加锁
258f678331aShanjiezhou 
259f678331aShanjiezhou         let mut inode = self.0.lock();
260f678331aShanjiezhou 
261*876cb89eSGnoCiYeH         // TODO: 如果已经没有读端存在了,则向写端进程发送SIGPIPE信号
262*876cb89eSGnoCiYeH         if inode.reader == 0 {}
263*876cb89eSGnoCiYeH 
264f678331aShanjiezhou         // 如果管道空间不够
265f678331aShanjiezhou 
266f678331aShanjiezhou         while len + inode.valid_cnt as usize > PIPE_BUFF_SIZE {
267f678331aShanjiezhou             // 唤醒读端
2681496ba7bSLoGin             inode
2691496ba7bSLoGin                 .read_wait_queue
2701496ba7bSLoGin                 .wakeup(Some(ProcessState::Blocked(true)));
2711496ba7bSLoGin 
27222c9db31Shanjiezhou             // 如果为非阻塞管道,直接返回错误
273*876cb89eSGnoCiYeH             if mode.contains(FileMode::O_NONBLOCK) {
27422c9db31Shanjiezhou                 drop(inode);
27522c9db31Shanjiezhou                 return Err(SystemError::ENOMEM);
27622c9db31Shanjiezhou             }
2771496ba7bSLoGin 
278f678331aShanjiezhou             // 解锁并睡眠
279f678331aShanjiezhou             unsafe {
280f678331aShanjiezhou                 let irq_guard = CurrentIrqArch::save_and_disable_irq();
281f678331aShanjiezhou                 inode.write_wait_queue.sleep_without_schedule();
282f678331aShanjiezhou                 drop(inode);
283f678331aShanjiezhou                 drop(irq_guard);
284f678331aShanjiezhou             }
285f678331aShanjiezhou             sched();
286f678331aShanjiezhou             inode = self.0.lock();
287f678331aShanjiezhou         }
288f678331aShanjiezhou 
289f678331aShanjiezhou         // 决定要输入的字节
290f678331aShanjiezhou         let start = inode.write_pos as usize;
291f678331aShanjiezhou         let end = (inode.write_pos as usize + len) % PIPE_BUFF_SIZE;
292f678331aShanjiezhou         // 从用户的缓冲区拷贝数据到管道
293f678331aShanjiezhou 
294f678331aShanjiezhou         if end < start {
295f678331aShanjiezhou             inode.data[start..PIPE_BUFF_SIZE].copy_from_slice(&buf[0..(PIPE_BUFF_SIZE - start)]);
296f678331aShanjiezhou             inode.data[0..end].copy_from_slice(&buf[(PIPE_BUFF_SIZE - start)..len]);
297f678331aShanjiezhou         } else {
298f678331aShanjiezhou             inode.data[start..end].copy_from_slice(&buf[0..len]);
299f678331aShanjiezhou         }
300f678331aShanjiezhou         // 更新写位置以及valid_cnt
301f678331aShanjiezhou         inode.write_pos = (inode.write_pos + len as i32) % PIPE_BUFF_SIZE as i32;
302f678331aShanjiezhou         inode.valid_cnt += len as i32;
303f678331aShanjiezhou 
304f678331aShanjiezhou         // 读完后解锁并唤醒等待在读等待队列中的进程
3051496ba7bSLoGin         inode
3061496ba7bSLoGin             .read_wait_queue
3071496ba7bSLoGin             .wakeup(Some(ProcessState::Blocked(true)));
308f678331aShanjiezhou         // 返回写入的字节数
309f678331aShanjiezhou         return Ok(len);
310f678331aShanjiezhou     }
311f678331aShanjiezhou 
312f678331aShanjiezhou     fn poll(&self) -> Result<PollStatus, crate::syscall::SystemError> {
313f678331aShanjiezhou         return Ok(PollStatus::READ | PollStatus::WRITE);
314f678331aShanjiezhou     }
315f678331aShanjiezhou 
316f678331aShanjiezhou     fn as_any_ref(&self) -> &dyn core::any::Any {
317f678331aShanjiezhou         self
318f678331aShanjiezhou     }
319f678331aShanjiezhou 
320f678331aShanjiezhou     fn get_entry_name_and_metadata(
321f678331aShanjiezhou         &self,
322f678331aShanjiezhou         ino: crate::filesystem::vfs::InodeId,
323f678331aShanjiezhou     ) -> Result<(alloc::string::String, crate::filesystem::vfs::Metadata), SystemError> {
324f678331aShanjiezhou         // 如果有条件,请在文件系统中使用高效的方式实现本接口,而不是依赖这个低效率的默认实现。
325f678331aShanjiezhou         let name = self.get_entry_name(ino)?;
326f678331aShanjiezhou         let entry = self.find(&name)?;
327f678331aShanjiezhou         return Ok((name, entry.metadata()?));
328f678331aShanjiezhou     }
329f678331aShanjiezhou 
330f678331aShanjiezhou     fn fs(&self) -> Arc<(dyn FileSystem)> {
331f678331aShanjiezhou         todo!()
332f678331aShanjiezhou     }
333f678331aShanjiezhou 
334f678331aShanjiezhou     fn list(&self) -> Result<alloc::vec::Vec<alloc::string::String>, SystemError> {
335f678331aShanjiezhou         return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP);
336f678331aShanjiezhou     }
337f678331aShanjiezhou }
338