From c709f79fdac296d503ad95ac9ef8d4f28307a487 Mon Sep 17 00:00:00 2001 From: GnoCiYeH Date: Sun, 13 Oct 2024 01:10:36 +0800 Subject: [PATCH] =?UTF-8?q?feat(tty):=20=E5=B0=86tty=E8=AE=BE=E5=A4=87?= =?UTF-8?q?=E9=80=82=E9=85=8Depoll=EF=BC=8C=E4=BF=AE=E6=94=B9=E4=B8=B2?= =?UTF-8?q?=E5=8F=A3=E9=83=A8=E5=88=86=E9=97=AE=E9=A2=98=20(#968)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - tty文件适配epoll,使epoll能够监听tty - 修改串口handle_irq,原有每次只读取一个字节会导致:输入left(esc+[+A)被错误解析为(esc)+([)+(A)三个字符 - 为串口加上vcdata用于控制输入输出的格式问题(未解决,这个pr捎带) --- .../serial/serial8250/serial8250_pio.rs | 34 +++++++++-- kernel/src/driver/tty/termios.rs | 8 +-- kernel/src/driver/tty/tty_core.rs | 57 +++++++++++++++++- kernel/src/driver/tty/tty_port.rs | 7 ++- kernel/src/driver/tty/virtual_terminal/mod.rs | 51 +--------------- .../tty/virtual_terminal/virtual_console.rs | 19 +++--- kernel/src/filesystem/eventfd.rs | 4 +- kernel/src/filesystem/vfs/mount.rs | 9 +++ kernel/src/ipc/pipe.rs | 4 +- kernel/src/net/event_poll/mod.rs | 59 +++++++++++-------- kernel/src/net/net_core.rs | 2 +- 11 files changed, 148 insertions(+), 106 deletions(-) diff --git a/kernel/src/driver/serial/serial8250/serial8250_pio.rs b/kernel/src/driver/serial/serial8250/serial8250_pio.rs index 0c346369..f5cba86f 100644 --- a/kernel/src/driver/serial/serial8250/serial8250_pio.rs +++ b/kernel/src/driver/serial/serial8250/serial8250_pio.rs @@ -19,12 +19,14 @@ use crate::{ }, serial::{AtomicBaudRate, BaudRate, DivisorFraction, UartPort}, tty::{ + console::ConsoleSwitch, kthread::send_to_tty_refresh_thread, termios::WindowSize, tty_core::{TtyCore, TtyCoreData}, tty_driver::{TtyDriver, TtyDriverManager, TtyOperation}, - virtual_terminal::{vc_manager, VirtConsole}, + virtual_terminal::{vc_manager, virtual_console::VirtualConsoleData, VirtConsole}, }, + video::console::dummycon::dummy_console, }, exception::{ irqdata::IrqHandlerData, @@ -32,7 +34,7 @@ use crate::{ manage::irq_manager, IrqNumber, }, - libs::rwlock::RwLock, + libs::{rwlock::RwLock, spinlock::SpinLock}, }; use system_error::SystemError; @@ -265,9 +267,20 @@ impl UartPort for Serial8250PIOPort { } fn handle_irq(&self) -> Result<(), SystemError> { - if let Some(c) = self.read_one_byte() { - send_to_tty_refresh_thread(&[c]); + let mut buf = [0; 8]; + let mut index = 0; + + // Read up to the size of the buffer + while index < buf.len() { + if let Some(c) = self.read_one_byte() { + buf[index] = c; + index += 1; + } else { + break; // No more bytes to read + } } + + send_to_tty_refresh_thread(&buf[0..index]); Ok(()) } @@ -385,7 +398,18 @@ impl TtyOperation for Serial8250PIOTtyDriverInner { if tty.core().index() >= unsafe { PIO_PORTS.len() } { return Err(SystemError::ENODEV); } - let vc = VirtConsole::new(None); + + *tty.core().window_size_write() = WindowSize::DEFAULT; + let vc_data = Arc::new(SpinLock::new(VirtualConsoleData::new(usize::MAX))); + let mut vc_data_guard = vc_data.lock_irqsave(); + vc_data_guard.set_driver_funcs(Arc::downgrade(&dummy_console()) as Weak); + vc_data_guard.init( + Some(tty.core().window_size().row.into()), + Some(tty.core().window_size().col.into()), + true, + ); + drop(vc_data_guard); + let vc = VirtConsole::new(Some(vc_data)); let vc_index = vc_manager().alloc(vc.clone()).ok_or(SystemError::EBUSY)?; self.do_install(driver, tty, vc.clone()).inspect_err(|_| { vc_manager().free(vc_index); diff --git a/kernel/src/driver/tty/termios.rs b/kernel/src/driver/tty/termios.rs index b219d203..0a0ca4bb 100644 --- a/kernel/src/driver/tty/termios.rs +++ b/kernel/src/driver/tty/termios.rs @@ -2,7 +2,7 @@ use super::tty_ldisc::LineDisciplineType; /// ## 窗口大小 #[repr(C)] -#[derive(Debug, Clone, Copy, PartialEq)] +#[derive(Debug, Clone, Copy, PartialEq, Default)] pub struct WindowSize { /// 行 pub row: u16, @@ -26,12 +26,6 @@ impl WindowSize { } } -impl Default for WindowSize { - fn default() -> Self { - Self::DEFAULT - } -} - #[derive(Debug, Clone, Copy)] pub struct Termios { pub input_mode: InputMode, diff --git a/kernel/src/driver/tty/tty_core.rs b/kernel/src/driver/tty/tty_core.rs index 376de925..d6dc8305 100644 --- a/kernel/src/driver/tty/tty_core.rs +++ b/kernel/src/driver/tty/tty_core.rs @@ -31,7 +31,7 @@ use super::{ TtyLineDiscipline, }, tty_port::TtyPort, - virtual_terminal::{vc_manager, virtual_console::VirtualConsoleData}, + virtual_terminal::{vc_manager, virtual_console::VirtualConsoleData, DrawRegion}, }; #[derive(Debug)] @@ -489,6 +489,61 @@ impl TtyCoreData { pub fn add_epitem(&self, epitem: Arc) { self.epitems.lock().push_back(epitem) } + + pub fn eptiems(&self) -> &SpinLock>> { + &self.epitems + } + + pub fn do_write(&self, buf: &[u8], mut nr: usize) -> Result { + // 关闭中断 + if let Some(vc_data) = self.vc_data() { + let mut vc_data_guard = vc_data.lock_irqsave(); + let mut offset = 0; + + // 这个参数是用来扫描unicode字符的,但是这部分目前未完成,先写着 + let mut rescan = false; + let mut ch: u32 = 0; + + let mut draw = DrawRegion::default(); + + // 首先隐藏光标再写 + vc_data_guard.hide_cursor(); + + while nr != 0 { + if !rescan { + ch = buf[offset] as u32; + offset += 1; + nr -= 1; + } + + let (tc, rescan_last) = vc_data_guard.translate(&mut ch); + if tc.is_none() { + // 表示未转换完成 + continue; + } + + let tc = tc.unwrap(); + rescan = rescan_last; + + if vc_data_guard.is_control(tc, ch) { + vc_data_guard.flush(&mut draw); + vc_data_guard.do_control(ch); + continue; + } + + if !vc_data_guard.console_write_normal(tc, ch, &mut draw) { + continue; + } + } + + vc_data_guard.flush(&mut draw); + + // TODO: notify update + return Ok(offset); + } else { + return Ok(0); + } + } } impl TtyOperation for TtyCore { diff --git a/kernel/src/driver/tty/tty_port.rs b/kernel/src/driver/tty/tty_port.rs index b387343f..d0488132 100644 --- a/kernel/src/driver/tty/tty_port.rs +++ b/kernel/src/driver/tty/tty_port.rs @@ -4,7 +4,10 @@ use alloc::sync::{Arc, Weak}; use kdepends::thingbuf::mpsc; use system_error::SystemError; -use crate::libs::spinlock::{SpinLock, SpinLockGuard}; +use crate::{ + libs::spinlock::{SpinLock, SpinLockGuard}, + net::event_poll::EventPoll, +}; use super::tty_core::TtyCore; @@ -85,6 +88,8 @@ pub trait TtyPort: Sync + Send + Debug { return ld.receive_buf(tty, buf, None, count); } + EventPoll::wakeup_epoll(tty.core().eptiems(), None)?; + ret } } diff --git a/kernel/src/driver/tty/virtual_terminal/mod.rs b/kernel/src/driver/tty/virtual_terminal/mod.rs index 8336591a..31abbfb6 100644 --- a/kernel/src/driver/tty/virtual_terminal/mod.rs +++ b/kernel/src/driver/tty/virtual_terminal/mod.rs @@ -300,55 +300,6 @@ impl TtyConsoleDriverInner { Ok(Self { console }) } - fn do_write(&self, tty: &TtyCoreData, buf: &[u8], mut nr: usize) -> Result { - // 关闭中断 - let vc_data = tty.vc_data().unwrap(); - let mut vc_data_guard = vc_data.lock_irqsave(); - - let mut offset = 0; - - // 这个参数是用来扫描unicode字符的,但是这部分目前未完成,先写着 - let mut rescan = false; - let mut ch: u32 = 0; - - let mut draw = DrawRegion::default(); - - // 首先隐藏光标再写 - vc_data_guard.hide_cursor(); - - while nr != 0 { - if !rescan { - ch = buf[offset] as u32; - offset += 1; - nr -= 1; - } - - let (tc, rescan_last) = vc_data_guard.translate(&mut ch); - if tc.is_none() { - // 表示未转换完成 - continue; - } - - let tc = tc.unwrap(); - rescan = rescan_last; - - if vc_data_guard.is_control(tc, ch) { - vc_data_guard.flush(&mut draw); - vc_data_guard.do_control(ch); - continue; - } - - if !vc_data_guard.console_write_normal(tc, ch, &mut draw) { - continue; - } - } - - vc_data_guard.flush(&mut draw); - - // TODO: notify update - return Ok(offset); - } - fn do_install(&self, tty: Arc, vc: &Arc) -> Result<(), SystemError> { let tty_core = tty.core(); @@ -426,7 +377,7 @@ impl TtyOperation for TtyConsoleDriverInner { // loop {} // } send_to_default_serial8250_port(buf); - let ret = self.do_write(tty, buf, nr); + let ret = tty.do_write(buf, nr); self.flush_chars(tty); ret } diff --git a/kernel/src/driver/tty/virtual_terminal/virtual_console.rs b/kernel/src/driver/tty/virtual_terminal/virtual_console.rs index 3b5630ed..da7cdcd5 100644 --- a/kernel/src/driver/tty/virtual_terminal/virtual_console.rs +++ b/kernel/src/driver/tty/virtual_terminal/virtual_console.rs @@ -206,7 +206,7 @@ impl VirtualConsoleData { } } - pub(super) fn init(&mut self, rows: Option, cols: Option, clear: bool) { + pub fn init(&mut self, rows: Option, cols: Option, clear: bool) { if let Some(rows) = rows { self.rows = rows; } @@ -242,7 +242,7 @@ impl VirtualConsoleData { self.driver_funcs.as_ref().unwrap().upgrade().unwrap() } - pub(super) fn set_driver_funcs(&mut self, func: Weak) { + pub fn set_driver_funcs(&mut self, func: Weak) { self.driver_funcs = Some(func); } @@ -312,7 +312,7 @@ impl VirtualConsoleData { /// /// ### 返回值 /// ### (转换后的字符:i32,是否需要更多的数据才能进行转换:bool) - pub(super) fn translate(&mut self, c: &mut u32) -> (Option, bool) { + pub fn translate(&mut self, c: &mut u32) -> (Option, bool) { if self.vc_state != VirtualConsoleState::ESnormal { // 在控制字符状态下不需要翻译 return (Some(*c), false); @@ -440,7 +440,7 @@ impl VirtualConsoleData { const CTRL_ALWAYS: u32 = 0x0800f501; /// ## 用于判断tc(终端字符)在当前VC下是不是需要显示的控制字符 - pub(super) fn is_control(&self, tc: u32, c: u32) -> bool { + pub fn is_control(&self, tc: u32, c: u32) -> bool { // 当前vc状态机不在正常状态,即在接收特殊字符的状态,则是控制字符 if self.vc_state != VirtualConsoleState::ESnormal { return true; @@ -1257,7 +1257,7 @@ impl VirtualConsoleData { /// ## 处理终端控制字符 #[inline(never)] - pub(super) fn do_control(&mut self, ch: u32) { + pub fn do_control(&mut self, ch: u32) { // 首先检查是否处于 ANSI 控制字符串状态 if self.vc_state.is_ansi_control_string() && (8..=13).contains(&ch) { return; @@ -1534,12 +1534,7 @@ impl VirtualConsoleData { } #[inline(never)] - pub(super) fn console_write_normal( - &mut self, - mut tc: u32, - c: u32, - draw: &mut DrawRegion, - ) -> bool { + pub fn console_write_normal(&mut self, mut tc: u32, c: u32, draw: &mut DrawRegion) -> bool { let mut attr = self.attr; let himask = self.hi_font_mask; let charmask = if himask == 0 { 0xff } else { 0x1ff }; @@ -1753,7 +1748,7 @@ impl VirtualConsoleData { return (self.attr & 0x88) | ((self.attr & 0x70) >> 4) | ((self.attr & 0x07) << 4); } - pub(super) fn flush(&self, draw: &mut DrawRegion) { + pub fn flush(&self, draw: &mut DrawRegion) { if draw.x.is_none() { return; } diff --git a/kernel/src/filesystem/eventfd.rs b/kernel/src/filesystem/eventfd.rs index 5a90ff67..4d0d9a76 100644 --- a/kernel/src/filesystem/eventfd.rs +++ b/kernel/src/filesystem/eventfd.rs @@ -137,7 +137,7 @@ impl IndexNode for EventFdInode { let pollflag = EPollEventType::from_bits_truncate(self.poll(&data)? as u32); // 唤醒epoll中等待的进程 - EventPoll::wakeup_epoll(&self.epitems, pollflag)?; + EventPoll::wakeup_epoll(&self.epitems, Some(pollflag))?; return Ok(8); } @@ -184,7 +184,7 @@ impl IndexNode for EventFdInode { let pollflag = EPollEventType::from_bits_truncate(self.poll(&data)? as u32); // 唤醒epoll中等待的进程 - EventPoll::wakeup_epoll(&self.epitems, pollflag)?; + EventPoll::wakeup_epoll(&self.epitems, Some(pollflag))?; return Ok(8); } diff --git a/kernel/src/filesystem/vfs/mount.rs b/kernel/src/filesystem/vfs/mount.rs index cc479883..c4ab9079 100644 --- a/kernel/src/filesystem/vfs/mount.rs +++ b/kernel/src/filesystem/vfs/mount.rs @@ -399,6 +399,15 @@ impl IndexNode for MountFSInode { return self.inner_inode.ioctl(cmd, data, private_data); } + #[inline] + fn kernel_ioctl( + &self, + arg: Arc, + data: &FilePrivateData, + ) -> Result { + return self.inner_inode.kernel_ioctl(arg, data); + } + #[inline] fn list(&self) -> Result, SystemError> { return self.inner_inode.list(); diff --git a/kernel/src/ipc/pipe.rs b/kernel/src/ipc/pipe.rs index 864bc750..05b8927c 100644 --- a/kernel/src/ipc/pipe.rs +++ b/kernel/src/ipc/pipe.rs @@ -267,7 +267,7 @@ impl IndexNode for LockedPipeInode { let pollflag = EPollEventType::from_bits_truncate(inode.poll(&data)? as u32); // 唤醒epoll中等待的进程 - EventPoll::wakeup_epoll(&inode.epitems, pollflag)?; + EventPoll::wakeup_epoll(&inode.epitems, Some(pollflag))?; //返回读取的字节数 return Ok(num); @@ -413,7 +413,7 @@ impl IndexNode for LockedPipeInode { let pollflag = EPollEventType::from_bits_truncate(inode.poll(&data)? as u32); // 唤醒epoll中等待的进程 - EventPoll::wakeup_epoll(&inode.epitems, pollflag)?; + EventPoll::wakeup_epoll(&inode.epitems, Some(pollflag))?; // 返回写入的字节数 return Ok(len); diff --git a/kernel/src/net/event_poll/mod.rs b/kernel/src/net/event_poll/mod.rs index af19ee1c..f6a9ad61 100644 --- a/kernel/src/net/event_poll/mod.rs +++ b/kernel/src/net/event_poll/mod.rs @@ -716,41 +716,50 @@ impl EventPoll { /// ### epoll的回调,支持epoll的文件有事件到来时直接调用该方法即可 pub fn wakeup_epoll( epitems: &SpinLock>>, - pollflags: EPollEventType, + pollflags: Option, ) -> Result<(), SystemError> { let mut epitems_guard = epitems.try_lock_irqsave()?; // 一次只取一个,因为一次也只有一个进程能拿到对应文件的🔓 if let Some(epitem) = epitems_guard.pop_front() { - let epoll = epitem.epoll().upgrade().unwrap(); - let mut epoll_guard = epoll.try_lock()?; - let binding = epitem.clone(); - let event_guard = binding.event().read(); - let ep_events = EPollEventType::from_bits_truncate(event_guard.events()); + let pollflags = pollflags.unwrap_or({ + if let Some(file) = epitem.file.upgrade() { + EPollEventType::from_bits_truncate(file.poll()? as u32) + } else { + EPollEventType::empty() + } + }); - // 检查事件合理性以及是否有感兴趣的事件 - if !(ep_events - .difference(EPollEventType::EP_PRIVATE_BITS) - .is_empty() - || pollflags.difference(ep_events).is_empty()) - { - // TODO: 未处理pm相关 + if let Some(epoll) = epitem.epoll().upgrade() { + let mut epoll_guard = epoll.try_lock()?; + let binding = epitem.clone(); + let event_guard = binding.event().read(); + let ep_events = EPollEventType::from_bits_truncate(event_guard.events()); - // 首先将就绪的epitem加入等待队列 - epoll_guard.ep_add_ready(epitem.clone()); + // 检查事件合理性以及是否有感兴趣的事件 + if !(ep_events + .difference(EPollEventType::EP_PRIVATE_BITS) + .is_empty() + || pollflags.difference(ep_events).is_empty()) + { + // TODO: 未处理pm相关 - if epoll_guard.ep_has_waiter() { - if ep_events.contains(EPollEventType::EPOLLEXCLUSIVE) - && !pollflags.contains(EPollEventType::POLLFREE) - { - // 避免惊群 - epoll_guard.ep_wake_one(); - } else { - epoll_guard.ep_wake_all(); + // 首先将就绪的epitem加入等待队列 + epoll_guard.ep_add_ready(epitem.clone()); + + if epoll_guard.ep_has_waiter() { + if ep_events.contains(EPollEventType::EPOLLEXCLUSIVE) + && !pollflags.contains(EPollEventType::POLLFREE) + { + // 避免惊群 + epoll_guard.ep_wake_one(); + } else { + epoll_guard.ep_wake_all(); + } } } - } - epitems_guard.push_back(epitem); + epitems_guard.push_back(epitem); + } } Ok(()) } diff --git a/kernel/src/net/net_core.rs b/kernel/src/net/net_core.rs index c74b0b58..9de8054e 100644 --- a/kernel/src/net/net_core.rs +++ b/kernel/src/net/net_core.rs @@ -233,7 +233,7 @@ fn send_event(sockets: &smoltcp::iface::SocketSet) -> Result<(), SystemError> { } EventPoll::wakeup_epoll( &posix_item.epitems, - EPollEventType::from_bits_truncate(events as u32), + Some(EPollEventType::from_bits_truncate(events as u32)), )?; drop(handle_guard); // crate::debug!(