diff --git a/kernel/src/arch/x86_64/process/syscall.rs b/kernel/src/arch/x86_64/process/syscall.rs index ee13d8b6..ee2e4f35 100644 --- a/kernel/src/arch/x86_64/process/syscall.rs +++ b/kernel/src/arch/x86_64/process/syscall.rs @@ -111,6 +111,7 @@ impl Syscall { // "tmp_rs_execve: done, load_result.entry_point()={:?}", // load_result.entry_point() // ); + return Ok(()); } } diff --git a/kernel/src/driver/pci/pci_irq.rs b/kernel/src/driver/pci/pci_irq.rs index 6c6d978e..50e8d294 100644 --- a/kernel/src/driver/pci/pci_irq.rs +++ b/kernel/src/driver/pci/pci_irq.rs @@ -12,7 +12,7 @@ use crate::arch::{PciArch, TraitPciArch}; use crate::include::bindings::bindings::{ c_irq_install, c_irq_uninstall, pt_regs, ul, EAGAIN, EINVAL, }; -use crate::kdebug; + use crate::libs::volatile::{volread, volwrite, Volatile, VolatileReadable, VolatileWritable}; /// MSIX表的一项 diff --git a/kernel/src/filesystem/vfs/file.rs b/kernel/src/filesystem/vfs/file.rs index 3c55fe89..68186027 100644 --- a/kernel/src/filesystem/vfs/file.rs +++ b/kernel/src/filesystem/vfs/file.rs @@ -8,6 +8,7 @@ use crate::{ tty::TtyFilePrivateData, }, filesystem::procfs::ProcfsFilePrivateData, + ipc::pipe::PipeFsPrivateData, kerror, libs::spinlock::SpinLock, process::ProcessManager, @@ -19,6 +20,8 @@ use super::{Dirent, FileType, IndexNode, InodeId, Metadata}; /// 文件私有信息的枚举类型 #[derive(Debug, Clone)] pub enum FilePrivateData { + /// 管道文件私有信息 + Pipefs(PipeFsPrivateData), /// procfs文件私有信息 Procfs(ProcfsFilePrivateData), /// 设备文件的私有信息 @@ -513,4 +516,54 @@ impl FileDescriptorVec { assert!(Arc::strong_count(&file) == 1); 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>); + + fn next(&mut self) -> Option { + 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; + } } diff --git a/kernel/src/ipc/pipe.rs b/kernel/src/ipc/pipe.rs index f771bf22..b46b49f7 100644 --- a/kernel/src/ipc/pipe.rs +++ b/kernel/src/ipc/pipe.rs @@ -16,6 +16,17 @@ use alloc::sync::{Arc, Weak}; /// 我们设定pipe_buff的总大小为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节点(锁) #[derive(Debug)] pub struct LockedPipeInode(SpinLock); @@ -32,11 +43,12 @@ pub struct InnerPipeInode { data: [u8; PIPE_BUFF_SIZE], /// INode 元数据 metadata: Metadata, - flags: FileMode, + reader: u32, + writer: u32, } impl LockedPipeInode { - pub fn new(flags: FileMode) -> Arc { + pub fn new() -> Arc { let inner = InnerPipeInode { self_ref: Weak::default(), valid_cnt: 0, @@ -62,7 +74,8 @@ impl LockedPipeInode { gid: 0, raw_dev: 0, }, - flags, + reader: 0, + writer: 0, }; let result = Arc::new(Self(SpinLock::new(inner))); let mut guard = result.0.lock(); @@ -79,8 +92,16 @@ impl IndexNode for LockedPipeInode { _offset: usize, len: usize, buf: &mut [u8], - _data: &mut FilePrivateData, + data: &mut FilePrivateData, ) -> Result { + // 获取mode + let mode: FileMode; + if let FilePrivateData::Pipefs(pdata) = data { + mode = pdata.mode; + } else { + return Err(SystemError::EBADF); + } + if buf.len() < len { return Err(SystemError::EINVAL); } @@ -89,12 +110,17 @@ impl IndexNode for LockedPipeInode { // 如果管道里面没有数据,则唤醒写端, while inode.valid_cnt == 0 { + // 如果当前管道写者数为0,则返回EOF + if inode.writer == 0 { + return Ok(0); + } + inode .write_wait_queue .wakeup(Some(ProcessState::Blocked(true))); // 如果为非阻塞管道,直接返回错误 - if inode.flags.contains(FileMode::O_NONBLOCK) { + if mode.contains(FileMode::O_NONBLOCK) { drop(inode); return Err(SystemError::EAGAIN_OR_EWOULDBLOCK); } @@ -145,9 +171,24 @@ impl IndexNode for LockedPipeInode { fn open( &self, - _data: &mut FilePrivateData, - _mode: &crate::filesystem::vfs::file::FileMode, + data: &mut FilePrivateData, + mode: &crate::filesystem::vfs::file::FileMode, ) -> 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(()); } @@ -159,7 +200,39 @@ impl IndexNode for LockedPipeInode { 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(()); } @@ -168,8 +241,16 @@ impl IndexNode for LockedPipeInode { _offset: usize, len: usize, buf: &[u8], - _data: &mut FilePrivateData, + data: &mut FilePrivateData, ) -> Result { + // 获取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 { return Err(SystemError::EINVAL); } @@ -177,6 +258,9 @@ impl IndexNode for LockedPipeInode { let mut inode = self.0.lock(); + // TODO: 如果已经没有读端存在了,则向写端进程发送SIGPIPE信号 + if inode.reader == 0 {} + // 如果管道空间不够 while len + inode.valid_cnt as usize > PIPE_BUFF_SIZE { @@ -186,7 +270,7 @@ impl IndexNode for LockedPipeInode { .wakeup(Some(ProcessState::Blocked(true))); // 如果为非阻塞管道,直接返回错误 - if inode.flags.contains(FileMode::O_NONBLOCK) { + if mode.contains(FileMode::O_NONBLOCK) { drop(inode); return Err(SystemError::ENOMEM); } diff --git a/kernel/src/ipc/syscall.rs b/kernel/src/ipc/syscall.rs index a73e4b89..5d36addd 100644 --- a/kernel/src/ipc/syscall.rs +++ b/kernel/src/ipc/syscall.rs @@ -1,12 +1,15 @@ use core::ffi::c_int; use crate::{ - filesystem::vfs::file::{File, FileMode}, + filesystem::vfs::{ + file::{File, FileMode}, + FilePrivateData, + }, process::{Pid, ProcessManager}, syscall::{user_access::UserBufferWriter, Syscall, SystemError}, }; -use super::pipe::LockedPipeInode; +use super::pipe::{LockedPipeInode, PipeFsPrivateData}; impl Syscall { /// # 创建带参数的匿名管道 @@ -23,9 +26,13 @@ impl Syscall { let mut user_buffer = UserBufferWriter::new(fd, core::mem::size_of::<[c_int; 2]>(), true)?; let fd = user_buffer.buffer::(0)?; - let pipe_ptr = LockedPipeInode::new(flags); + let pipe_ptr = LockedPipeInode::new(); 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)?; + write_file.private_data = + FilePrivateData::Pipefs(PipeFsPrivateData::new(FileMode::O_WRONLY)); if flags.contains(FileMode::O_CLOEXEC) { read_file.set_close_on_exec(true); write_file.set_close_on_exec(true); diff --git a/kernel/src/process/syscall.rs b/kernel/src/process/syscall.rs index a540f926..08f72160 100644 --- a/kernel/src/process/syscall.rs +++ b/kernel/src/process/syscall.rs @@ -61,7 +61,13 @@ impl Syscall { .basic_mut() .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(