Browse Source

修复pipe2在读端或写端关闭后还阻塞问题 (#396)

* 修复pipe2在读端或写端关闭后还阻塞问题。

* update

* update

* 修改cloexec

---------

Co-authored-by: longjin <[email protected]>
GnoCiYeH 1 year ago
parent
commit
876cb89ecf

+ 1 - 0
kernel/src/arch/x86_64/process/syscall.rs

@@ -111,6 +111,7 @@ impl Syscall {
         //     "tmp_rs_execve: done, load_result.entry_point()={:?}",
         //     "tmp_rs_execve: done, load_result.entry_point()={:?}",
         //     load_result.entry_point()
         //     load_result.entry_point()
         // );
         // );
+
         return Ok(());
         return Ok(());
     }
     }
 }
 }

+ 1 - 1
kernel/src/driver/pci/pci_irq.rs

@@ -12,7 +12,7 @@ use crate::arch::{PciArch, TraitPciArch};
 use crate::include::bindings::bindings::{
 use crate::include::bindings::bindings::{
     c_irq_install, c_irq_uninstall, pt_regs, ul, EAGAIN, EINVAL,
     c_irq_install, c_irq_uninstall, pt_regs, ul, EAGAIN, EINVAL,
 };
 };
-use crate::kdebug;
+
 use crate::libs::volatile::{volread, volwrite, Volatile, VolatileReadable, VolatileWritable};
 use crate::libs::volatile::{volread, volwrite, Volatile, VolatileReadable, VolatileWritable};
 
 
 /// MSIX表的一项
 /// MSIX表的一项

+ 53 - 0
kernel/src/filesystem/vfs/file.rs

@@ -8,6 +8,7 @@ use crate::{
         tty::TtyFilePrivateData,
         tty::TtyFilePrivateData,
     },
     },
     filesystem::procfs::ProcfsFilePrivateData,
     filesystem::procfs::ProcfsFilePrivateData,
+    ipc::pipe::PipeFsPrivateData,
     kerror,
     kerror,
     libs::spinlock::SpinLock,
     libs::spinlock::SpinLock,
     process::ProcessManager,
     process::ProcessManager,
@@ -19,6 +20,8 @@ use super::{Dirent, FileType, IndexNode, InodeId, Metadata};
 /// 文件私有信息的枚举类型
 /// 文件私有信息的枚举类型
 #[derive(Debug, Clone)]
 #[derive(Debug, Clone)]
 pub enum FilePrivateData {
 pub enum FilePrivateData {
+    /// 管道文件私有信息
+    Pipefs(PipeFsPrivateData),
     /// procfs文件私有信息
     /// procfs文件私有信息
     Procfs(ProcfsFilePrivateData),
     Procfs(ProcfsFilePrivateData),
     /// 设备文件的私有信息
     /// 设备文件的私有信息
@@ -513,4 +516,54 @@ impl FileDescriptorVec {
         assert!(Arc::strong_count(&file) == 1);
         assert!(Arc::strong_count(&file) == 1);
         return Ok(());
         return Ok(());
     }
     }
+
+    pub fn iter(&self) -> FileDescriptorIterator {
+        return FileDescriptorIterator::new(self);
+    }
+
+    pub fn close_on_exec(&mut self) {
+        for i in 0..FileDescriptorVec::PROCESS_MAX_FD {
+            if let Some(file) = &self.fds[i] {
+                let to_drop = file.lock().close_on_exec();
+                if to_drop {
+                    let r = self.drop_fd(i as i32);
+                    if let Err(r) = r {
+                        kerror!(
+                            "Failed to close file: pid = {:?}, fd = {}, error = {:?}",
+                            ProcessManager::current_pcb().pid(),
+                            i,
+                            r
+                        );
+                    }
+                }
+            }
+        }
+    }
+}
+
+#[derive(Debug)]
+pub struct FileDescriptorIterator<'a> {
+    fds: &'a FileDescriptorVec,
+    index: usize,
+}
+
+impl<'a> FileDescriptorIterator<'a> {
+    pub fn new(fds: &'a FileDescriptorVec) -> Self {
+        return Self { fds, index: 0 };
+    }
+}
+
+impl<'a> Iterator for FileDescriptorIterator<'a> {
+    type Item = (i32, Arc<SpinLock<File>>);
+
+    fn next(&mut self) -> Option<Self::Item> {
+        while self.index < FileDescriptorVec::PROCESS_MAX_FD {
+            let fd = self.index as i32;
+            self.index += 1;
+            if let Some(file) = self.fds.get_file_by_fd(fd) {
+                return Some((fd, file));
+            }
+        }
+        return None;
+    }
 }
 }

+ 94 - 10
kernel/src/ipc/pipe.rs

@@ -16,6 +16,17 @@ use alloc::sync::{Arc, Weak};
 /// 我们设定pipe_buff的总大小为1024字节
 /// 我们设定pipe_buff的总大小为1024字节
 const PIPE_BUFF_SIZE: usize = 1024;
 const PIPE_BUFF_SIZE: usize = 1024;
 
 
+#[derive(Debug, Clone)]
+pub struct PipeFsPrivateData {
+    mode: FileMode,
+}
+
+impl PipeFsPrivateData {
+    pub fn new(mode: FileMode) -> Self {
+        return PipeFsPrivateData { mode: mode };
+    }
+}
+
 /// @brief 管道文件i节点(锁)
 /// @brief 管道文件i节点(锁)
 #[derive(Debug)]
 #[derive(Debug)]
 pub struct LockedPipeInode(SpinLock<InnerPipeInode>);
 pub struct LockedPipeInode(SpinLock<InnerPipeInode>);
@@ -32,11 +43,12 @@ pub struct InnerPipeInode {
     data: [u8; PIPE_BUFF_SIZE],
     data: [u8; PIPE_BUFF_SIZE],
     /// INode 元数据
     /// INode 元数据
     metadata: Metadata,
     metadata: Metadata,
-    flags: FileMode,
+    reader: u32,
+    writer: u32,
 }
 }
 
 
 impl LockedPipeInode {
 impl LockedPipeInode {
-    pub fn new(flags: FileMode) -> Arc<Self> {
+    pub fn new() -> Arc<Self> {
         let inner = InnerPipeInode {
         let inner = InnerPipeInode {
             self_ref: Weak::default(),
             self_ref: Weak::default(),
             valid_cnt: 0,
             valid_cnt: 0,
@@ -62,7 +74,8 @@ impl LockedPipeInode {
                 gid: 0,
                 gid: 0,
                 raw_dev: 0,
                 raw_dev: 0,
             },
             },
-            flags,
+            reader: 0,
+            writer: 0,
         };
         };
         let result = Arc::new(Self(SpinLock::new(inner)));
         let result = Arc::new(Self(SpinLock::new(inner)));
         let mut guard = result.0.lock();
         let mut guard = result.0.lock();
@@ -79,8 +92,16 @@ impl IndexNode for LockedPipeInode {
         _offset: usize,
         _offset: usize,
         len: usize,
         len: usize,
         buf: &mut [u8],
         buf: &mut [u8],
-        _data: &mut FilePrivateData,
+        data: &mut FilePrivateData,
     ) -> Result<usize, crate::syscall::SystemError> {
     ) -> Result<usize, crate::syscall::SystemError> {
+        // 获取mode
+        let mode: FileMode;
+        if let FilePrivateData::Pipefs(pdata) = data {
+            mode = pdata.mode;
+        } else {
+            return Err(SystemError::EBADF);
+        }
+
         if buf.len() < len {
         if buf.len() < len {
             return Err(SystemError::EINVAL);
             return Err(SystemError::EINVAL);
         }
         }
@@ -89,12 +110,17 @@ impl IndexNode for LockedPipeInode {
 
 
         // 如果管道里面没有数据,则唤醒写端,
         // 如果管道里面没有数据,则唤醒写端,
         while inode.valid_cnt == 0 {
         while inode.valid_cnt == 0 {
+            // 如果当前管道写者数为0,则返回EOF
+            if inode.writer == 0 {
+                return Ok(0);
+            }
+
             inode
             inode
                 .write_wait_queue
                 .write_wait_queue
                 .wakeup(Some(ProcessState::Blocked(true)));
                 .wakeup(Some(ProcessState::Blocked(true)));
 
 
             // 如果为非阻塞管道,直接返回错误
             // 如果为非阻塞管道,直接返回错误
-            if inode.flags.contains(FileMode::O_NONBLOCK) {
+            if mode.contains(FileMode::O_NONBLOCK) {
                 drop(inode);
                 drop(inode);
                 return Err(SystemError::EAGAIN_OR_EWOULDBLOCK);
                 return Err(SystemError::EAGAIN_OR_EWOULDBLOCK);
             }
             }
@@ -145,9 +171,24 @@ impl IndexNode for LockedPipeInode {
 
 
     fn open(
     fn open(
         &self,
         &self,
-        _data: &mut FilePrivateData,
-        _mode: &crate::filesystem::vfs::file::FileMode,
+        data: &mut FilePrivateData,
+        mode: &crate::filesystem::vfs::file::FileMode,
     ) -> Result<(), SystemError> {
     ) -> Result<(), SystemError> {
+        let mut guard = self.0.lock();
+        // 不能以读写方式打开管道
+        if mode.contains(FileMode::O_RDWR) {
+            return Err(SystemError::EACCES);
+        }
+        if mode.contains(FileMode::O_RDONLY) {
+            guard.reader += 1;
+        }
+        if mode.contains(FileMode::O_WRONLY) {
+            guard.writer += 1;
+        }
+
+        // 设置mode
+        *data = FilePrivateData::Pipefs(PipeFsPrivateData { mode: *mode });
+
         return Ok(());
         return Ok(());
     }
     }
 
 
@@ -159,7 +200,39 @@ impl IndexNode for LockedPipeInode {
         return Ok(metadata);
         return Ok(metadata);
     }
     }
 
 
-    fn close(&self, _data: &mut FilePrivateData) -> Result<(), SystemError> {
+    fn close(&self, data: &mut FilePrivateData) -> Result<(), SystemError> {
+        let mode: FileMode;
+        if let FilePrivateData::Pipefs(pipe_data) = data {
+            mode = pipe_data.mode;
+        } else {
+            return Err(SystemError::EBADF);
+        }
+        let mut guard = self.0.lock();
+
+        // 写端关闭
+        if mode.contains(FileMode::O_WRONLY) {
+            assert!(guard.writer > 0);
+            guard.writer -= 1;
+            // 如果已经没有写端了,则唤醒读端
+            if guard.writer == 0 {
+                guard
+                    .read_wait_queue
+                    .wakeup_all(Some(ProcessState::Blocked(true)));
+            }
+        }
+
+        // 读端关闭
+        if mode.contains(FileMode::O_RDONLY) {
+            assert!(guard.reader > 0);
+            guard.reader -= 1;
+            // 如果已经没有写端了,则唤醒读端
+            if guard.reader == 0 {
+                guard
+                    .write_wait_queue
+                    .wakeup_all(Some(ProcessState::Blocked(true)));
+            }
+        }
+
         return Ok(());
         return Ok(());
     }
     }
 
 
@@ -168,8 +241,16 @@ impl IndexNode for LockedPipeInode {
         _offset: usize,
         _offset: usize,
         len: usize,
         len: usize,
         buf: &[u8],
         buf: &[u8],
-        _data: &mut FilePrivateData,
+        data: &mut FilePrivateData,
     ) -> Result<usize, crate::syscall::SystemError> {
     ) -> Result<usize, crate::syscall::SystemError> {
+        // 获取mode
+        let mode: FileMode;
+        if let FilePrivateData::Pipefs(pdata) = data {
+            mode = pdata.mode;
+        } else {
+            return Err(SystemError::EBADF);
+        }
+
         if buf.len() < len || len > PIPE_BUFF_SIZE {
         if buf.len() < len || len > PIPE_BUFF_SIZE {
             return Err(SystemError::EINVAL);
             return Err(SystemError::EINVAL);
         }
         }
@@ -177,6 +258,9 @@ impl IndexNode for LockedPipeInode {
 
 
         let mut inode = self.0.lock();
         let mut inode = self.0.lock();
 
 
+        // TODO: 如果已经没有读端存在了,则向写端进程发送SIGPIPE信号
+        if inode.reader == 0 {}
+
         // 如果管道空间不够
         // 如果管道空间不够
 
 
         while len + inode.valid_cnt as usize > PIPE_BUFF_SIZE {
         while len + inode.valid_cnt as usize > PIPE_BUFF_SIZE {
@@ -186,7 +270,7 @@ impl IndexNode for LockedPipeInode {
                 .wakeup(Some(ProcessState::Blocked(true)));
                 .wakeup(Some(ProcessState::Blocked(true)));
 
 
             // 如果为非阻塞管道,直接返回错误
             // 如果为非阻塞管道,直接返回错误
-            if inode.flags.contains(FileMode::O_NONBLOCK) {
+            if mode.contains(FileMode::O_NONBLOCK) {
                 drop(inode);
                 drop(inode);
                 return Err(SystemError::ENOMEM);
                 return Err(SystemError::ENOMEM);
             }
             }

+ 10 - 3
kernel/src/ipc/syscall.rs

@@ -1,12 +1,15 @@
 use core::ffi::c_int;
 use core::ffi::c_int;
 
 
 use crate::{
 use crate::{
-    filesystem::vfs::file::{File, FileMode},
+    filesystem::vfs::{
+        file::{File, FileMode},
+        FilePrivateData,
+    },
     process::{Pid, ProcessManager},
     process::{Pid, ProcessManager},
     syscall::{user_access::UserBufferWriter, Syscall, SystemError},
     syscall::{user_access::UserBufferWriter, Syscall, SystemError},
 };
 };
 
 
-use super::pipe::LockedPipeInode;
+use super::pipe::{LockedPipeInode, PipeFsPrivateData};
 
 
 impl Syscall {
 impl Syscall {
     /// # 创建带参数的匿名管道
     /// # 创建带参数的匿名管道
@@ -23,9 +26,13 @@ impl Syscall {
             let mut user_buffer =
             let mut user_buffer =
                 UserBufferWriter::new(fd, core::mem::size_of::<[c_int; 2]>(), true)?;
                 UserBufferWriter::new(fd, core::mem::size_of::<[c_int; 2]>(), true)?;
             let fd = user_buffer.buffer::<i32>(0)?;
             let fd = user_buffer.buffer::<i32>(0)?;
-            let pipe_ptr = LockedPipeInode::new(flags);
+            let pipe_ptr = LockedPipeInode::new();
             let mut read_file = File::new(pipe_ptr.clone(), FileMode::O_RDONLY)?;
             let mut read_file = File::new(pipe_ptr.clone(), FileMode::O_RDONLY)?;
+            read_file.private_data =
+                FilePrivateData::Pipefs(PipeFsPrivateData::new(FileMode::O_RDONLY));
             let mut write_file = File::new(pipe_ptr.clone(), FileMode::O_WRONLY)?;
             let mut write_file = File::new(pipe_ptr.clone(), FileMode::O_WRONLY)?;
+            write_file.private_data =
+                FilePrivateData::Pipefs(PipeFsPrivateData::new(FileMode::O_WRONLY));
             if flags.contains(FileMode::O_CLOEXEC) {
             if flags.contains(FileMode::O_CLOEXEC) {
                 read_file.set_close_on_exec(true);
                 read_file.set_close_on_exec(true);
                 write_file.set_close_on_exec(true);
                 write_file.set_close_on_exec(true);

+ 7 - 1
kernel/src/process/syscall.rs

@@ -61,7 +61,13 @@ impl Syscall {
             .basic_mut()
             .basic_mut()
             .set_name(ProcessControlBlock::generate_name(&path, &argv));
             .set_name(ProcessControlBlock::generate_name(&path, &argv));
 
 
-        return Self::do_execve(path, argv, envp, frame);
+        Self::do_execve(path, argv, envp, frame)?;
+
+        // 关闭设置了O_CLOEXEC的文件描述符
+        let fd_table = ProcessManager::current_pcb().fd_table();
+        fd_table.write().close_on_exec();
+
+        return Ok(());
     }
     }
 
 
     pub fn wait4(
     pub fn wait4(