Selaa lähdekoodia

new: tty设备(尚未与stdio接上) (#202)

login 2 vuotta sitten
vanhempi
commit
0d48c3c9c2

+ 2 - 1
kernel/Cargo.toml

@@ -13,7 +13,8 @@ crate-type = ["staticlib"]
 x86_64 = "0.14.10"
 bitflags = "1.3.2"
 virtio-drivers = "0.2.0"
-
+# 一个无锁MPSC队列
+thingbuf = { version = "0.1.3", default-features = false, features = ["alloc"] }
 
 # 构建时依赖项
 [build-dependencies]

+ 1 - 1
kernel/src/driver/Makefile

@@ -1,7 +1,7 @@
 
 CFLAGS += -I .
 
-kernel_driver_subdirs:=video interrupt usb pci acpi disk keyboard mouse multiboot2 timers tty hid virtio
+kernel_driver_subdirs:=video interrupt usb pci acpi disk keyboard mouse multiboot2 timers hid virtio
 
 ECHO:
 	@echo "$@"

+ 2 - 1
kernel/src/driver/disk/ahci/ahci_inode.rs

@@ -1,4 +1,5 @@
 use crate::filesystem::devfs::{DevFS, DeviceINode};
+use crate::filesystem::vfs::file::FileMode;
 use crate::filesystem::vfs::{
     core::generate_inode_id, make_rawdev, FilePrivateData, FileSystem, FileType, IndexNode,
     Metadata, PollStatus,
@@ -77,7 +78,7 @@ impl IndexNode for LockedAhciInode {
         self
     }
 
-    fn open(&self, _data: &mut FilePrivateData) -> Result<(), i32> {
+    fn open(&self, _data: &mut FilePrivateData, _mode: &FileMode) -> Result<(), i32> {
         Err(-(ENOTSUP as i32))
     }
 

+ 6 - 4
kernel/src/driver/keyboard/ps2_keyboard.rs

@@ -3,7 +3,7 @@ use alloc::sync::{Arc, Weak};
 use crate::{
     filesystem::{
         devfs::{devfs_register, DevFS, DeviceINode},
-        vfs::{core::generate_inode_id, FileType, IndexNode, Metadata, PollStatus},
+        vfs::{core::generate_inode_id, file::FileMode, FileType, IndexNode, Metadata, PollStatus},
     },
     include::bindings::bindings::{vfs_file_operations_t, vfs_file_t, vfs_index_node_t, ENOTSUP},
     kdebug,
@@ -68,10 +68,8 @@ impl DeviceINode for LockedPS2KeyBoardInode {
 
 #[no_mangle] // 不重命名
 pub extern "C" fn ps2_keyboard_register(f_ops: &vfs_file_operations_t) {
-    kdebug!("register keyboard = {:p}", f_ops);
     devfs_register("ps2_keyboard", LockedPS2KeyBoardInode::new(f_ops))
         .expect("Failed to register ps/2 keyboard");
-    kdebug!("register keyboard = {:p}", f_ops);
 }
 
 impl IndexNode for LockedPS2KeyBoardInode {
@@ -105,7 +103,11 @@ impl IndexNode for LockedPS2KeyBoardInode {
         return Err(-(ENOTSUP as i32));
     }
 
-    fn open(&self, _data: &mut crate::filesystem::vfs::FilePrivateData) -> Result<(), i32> {
+    fn open(
+        &self,
+        _data: &mut crate::filesystem::vfs::FilePrivateData,
+        _mode: &FileMode,
+    ) -> Result<(), i32> {
         let guard = self.0.lock();
         let func = guard.f_ops.open.unwrap();
         let _ = unsafe { func(0 as *mut vfs_index_node_t, 0 as *mut vfs_file_t) };

+ 1 - 0
kernel/src/driver/mod.rs

@@ -2,5 +2,6 @@ pub mod disk;
 pub mod keyboard;
 pub mod pci;
 pub mod timers;
+pub mod tty;
 pub mod uart;
 pub mod virtio;

+ 0 - 8
kernel/src/driver/tty/Makefile

@@ -1,8 +0,0 @@
-
-all: tty.o
-
-CFLAGS += -I .
-
-
-tty.o: tty.c
-	$(CC) $(CFLAGS) -c tty.c -o tty.o

+ 384 - 0
kernel/src/driver/tty/mod.rs

@@ -0,0 +1,384 @@
+use alloc::string::String;
+
+use thingbuf::mpsc::{
+    self,
+    errors::{TryRecvError, TrySendError},
+};
+
+use crate::libs::rwlock::RwLock;
+
+pub mod tty_device;
+
+bitflags! {
+    pub struct TtyCoreState: u32{
+        /// 在读取stdin缓冲区时,由于队列为空,有读者被阻塞
+        const BLOCK_AT_STDIN_READ = (1 << 0);
+        /// 开启输入回显。
+        const ECHO_ON = (1 << 1);
+    }
+
+    #[derive(Default)]
+    pub struct TtyFileFlag:u32{
+        /// 当前文件是stdin文件
+        const STDIN = (1 << 0);
+        /// 当前文件是stdout文件
+        const STDOUT = (1 << 1);
+        /// 当前文件是stderr文件
+        const STDERR = (1 << 2);
+    }
+}
+
+/// @brief tty文件的私有信息
+#[derive(Debug, Default, Clone)]
+pub struct TtyFilePrivateData {
+    flags: TtyFileFlag,
+}
+
+/// @brief tty设备的核心功能结构体。在此结构体的基础上,衍生出TTY/PTY/PTS等
+///
+/// 每个TTY Core有5个端口:
+/// - stdin:连接到一个活动进程的stdin文件描述符
+/// - stdout:连接到多个进程的stdout文件描述符
+/// - stderr:连接到多个进程的stdout文件描述符
+/// - 输入端口:向tty设备输入数据的接口。输入到该接口的数据,将被导向stdin接口。
+///     如果开启了回显,那么,数据也将同时被导向输出端
+/// - 输出端口:tty设备对外输出数据的端口。从stdout、stderr输入的数据,将会被导向此端口。
+///             此端口可以连接到屏幕、文件、或者是另一个tty core的输入端口。如果开启了
+///             输入数据回显,那么,输入端口的数据,将会被同时导向此端口,以及stdin端口
+#[derive(Debug)]
+struct TtyCore {
+    /// stdin的mpsc队列输入输出端
+    stdin_rx: mpsc::Receiver<u8>,
+    stdin_tx: mpsc::Sender<u8>,
+    /// 输出的mpsc队列输入输出端
+    output_rx: mpsc::Receiver<u8>,
+    output_tx: mpsc::Sender<u8>,
+
+    /// tty核心的状态
+    state: RwLock<TtyCoreState>,
+}
+
+#[derive(Debug)]
+pub enum TtyError {
+    /// 缓冲区满,返回成功传送的字节数
+    BufferFull(usize),
+    /// 缓冲区空,返回成功传送的字节数
+    BufferEmpty(usize),
+    /// 设备已经被关闭
+    Closed,
+    /// End of file(已经读取的字符数,包含eof)
+    EOF(usize),
+    Unknown(String),
+}
+
+impl TtyCore {
+    // 各个缓冲区的大小
+    pub const STDIN_BUF_SIZE: usize = 4096;
+    pub const OUTPUT_BUF_SIZE: usize = 4096;
+
+    /// @brief 创建一个TTY核心组件
+    pub fn new() -> TtyCore {
+        let (stdin_tx, stdin_rx) = mpsc::channel::<u8>(Self::STDIN_BUF_SIZE);
+        let (output_tx, output_rx) = mpsc::channel::<u8>(Self::OUTPUT_BUF_SIZE);
+        let state: RwLock<TtyCoreState> = RwLock::new(TtyCoreState { bits: 0 });
+
+        return TtyCore {
+            stdin_rx,
+            stdin_tx,
+            output_rx,
+            output_tx,
+            state,
+        };
+    }
+
+    /// @brief 向tty的输入端口输入数据
+    ///
+    /// @param buf 输入数据
+    ///
+    /// @param block 是否允许阻塞
+    ///
+    /// @return Ok(成功传送的字节数)
+    /// @return Err(TtyError) 内部错误信息
+    pub fn input(&self, buf: &[u8], block: bool) -> Result<usize, TtyError> {
+        // TODO: 在这里考虑增加对信号发送的处理
+        let val = self.write_stdin(buf, block)?;
+        // 如果开启了输入回显,那么就写一份到输出缓冲区
+        if self.echo_enabled() {
+            self.write_output(&buf[0..val], true)?;
+        }
+        return Ok(val);
+    }
+
+    /// @brief 从tty的输出端口读出数据
+    ///
+    /// @param buf 输出缓冲区
+    ///
+    /// @return Ok(成功传送的字节数)
+    /// @return Err(TtyError) 内部错误信息
+    #[inline]
+    pub fn output(&self, buf: &mut [u8], block: bool) -> Result<usize, TtyError> {
+        return self.read_output(buf, block);
+    }
+
+    /// @brief tty的stdout接口
+    ///
+    /// @param buf 输入缓冲区
+    ///
+    /// @return Ok(成功传送的字节数)
+    /// @return Err(TtyError) 内部错误信息
+    #[inline]
+    pub fn stdout(&self, buf: &[u8], block: bool) -> Result<usize, TtyError> {
+        return self.write_output(buf, block);
+    }
+
+    /// @brief tty的stderr接口
+    ///
+    /// @param buf 输入缓冲区
+    ///
+    /// @return Ok(成功传送的字节数)
+    /// @return Err(TtyError) 内部错误信息
+    #[inline]
+    pub fn stderr(&self, buf: &[u8], block: bool) -> Result<usize, TtyError> {
+        return self.write_output(buf, block);
+    }
+
+    /// @brief 读取TTY的stdin缓冲区
+    ///
+    /// @param buf 读取到的位置
+    /// @param block 是否阻塞读
+    ///
+    /// @return Ok(成功读取的字节数)
+    /// @return Err(TtyError) 内部错误信息
+    pub fn read_stdin(&self, buf: &mut [u8], block: bool) -> Result<usize, TtyError> {
+        // TODO: 增加对EOF的处理
+        let mut cnt = 0;
+        while cnt < buf.len() {
+            let val: Result<mpsc::RecvRef<u8>, TryRecvError> = self.stdin_rx.try_recv_ref();
+            if let Err(err) = val {
+                match err {
+                    TryRecvError::Closed => return Err(TtyError::Closed),
+                    TryRecvError::Empty => {
+                        if block {
+                            continue;
+                        } else {
+                            return Ok(cnt);
+                        }
+                    }
+                    _ => return Err(TtyError::Unknown(format!("{err:?}"))),
+                }
+            } else {
+                buf[cnt] = *val.unwrap();
+                cnt += 1;
+            }
+        }
+        return Ok(cnt);
+    }
+
+    /// @brief 向stdin缓冲区内写入数据
+    ///
+    /// @param buf 输入缓冲区
+    ///
+    /// @param block 当缓冲区满的时候,是否阻塞
+    ///
+    /// @return Ok(成功传送的字节数)
+    /// @return Err(BufferFull(成功传送的字节数)) 缓冲区满,成功传送的字节数
+    /// @return Err(TtyError) 内部错误信息
+    fn write_stdin(&self, buf: &[u8], block: bool) -> Result<usize, TtyError> {
+        let mut cnt = 0;
+        while cnt < buf.len() {
+            let r: Result<mpsc::SendRef<u8>, TrySendError> = self.stdin_tx.try_send_ref();
+            if let Err(e) = r {
+                match e {
+                    TrySendError::Closed(_) => return Err(TtyError::Closed),
+                    TrySendError::Full(_) => {
+                        if block {
+                            continue;
+                        } else {
+                            return Err(TtyError::BufferFull(cnt));
+                        }
+                    }
+                    _ => return Err(TtyError::Unknown(format!("{e:?}"))),
+                }
+            } else {
+                *r.unwrap() = buf[cnt];
+                cnt += 1;
+            }
+        }
+
+        return Ok(cnt);
+    }
+
+    /// @brief 读取TTY的output缓冲区
+    ///
+    /// @param buf 读取到的位置
+    /// @param block 是否阻塞读
+    ///
+    /// @return Ok(成功读取的字节数)
+    /// @return Err(TtyError) 内部错误信息
+    fn read_output(&self, buf: &mut [u8], block: bool) -> Result<usize, TtyError> {
+        let mut cnt = 0;
+        while cnt < buf.len() {
+            let val: Result<mpsc::RecvRef<u8>, TryRecvError> = self.output_rx.try_recv_ref();
+            if let Err(err) = val {
+                match err {
+                    TryRecvError::Closed => return Err(TtyError::Closed),
+                    TryRecvError::Empty => {
+                        if block {
+                            continue;
+                        } else {
+                            return Ok(cnt);
+                        }
+                    }
+                    _ => return Err(TtyError::Unknown(format!("{err:?}"))),
+                }
+            } else {
+                buf[cnt] = *val.unwrap();
+                cnt += 1;
+            }
+        }
+        return Ok(cnt);
+    }
+
+    /// @brief 向output缓冲区内写入数据
+    ///
+    /// @param buf 输入缓冲区
+    ///
+    /// @param block 当缓冲区满的时候,是否阻塞
+    ///
+    /// @return Ok(成功传送的字节数)
+    /// @return Err(BufferFull(成功传送的字节数)) 缓冲区满,成功传送的字节数
+    /// @return Err(TtyError) 内部错误信息
+    fn write_output(&self, buf: &[u8], block: bool) -> Result<usize, TtyError> {
+        let mut cnt = 0;
+        while cnt < buf.len() {
+            let r: Result<mpsc::SendRef<u8>, TrySendError> = self.output_tx.try_send_ref();
+            if let Err(e) = r {
+                match e {
+                    TrySendError::Closed(_) => return Err(TtyError::Closed),
+                    TrySendError::Full(_) => {
+                        if block {
+                            continue;
+                        } else {
+                            return Err(TtyError::BufferFull(cnt));
+                        }
+                    }
+                    _ => return Err(TtyError::Unknown(format!("{e:?}"))),
+                }
+            } else {
+                *r.unwrap() = buf[cnt];
+                cnt += 1;
+            }
+        }
+
+        return Ok(cnt);
+    }
+
+    /// @brief 开启tty输入回显(也就是将输入数据传送一份到输出缓冲区)
+    #[inline]
+    pub fn enable_echo(&self) {
+        self.state.write().set(TtyCoreState::ECHO_ON, true);
+    }
+
+    /// @brief 关闭输入回显
+    #[inline]
+    pub fn disable_echo(&self) {
+        self.state.write().set(TtyCoreState::ECHO_ON, false);
+    }
+
+    /// @brief 判断当前tty核心,是否开启了输入回显
+    ///
+    /// @return true 开启了输入回显
+    ///
+    /// @return false 未开启输入回显
+    #[inline]
+    pub fn echo_enabled(&self) -> bool {
+        return self.state.read().contains(TtyCoreState::ECHO_ON);
+    }
+}
+
+// ======= 以下代码考虑了“缓冲区满,然后睡眠,当缓冲区有空位就唤醒”的逻辑。
+// 但是由于在开发过程中的调整,并且由于数据结构发生变化,因此暂时不实现上述优化,因此先注释。
+//
+// @brief 读取TTY的stdin缓冲区
+//
+// @param buf 读取到的位置
+// @param block 是否阻塞读
+//
+// @return Ok(成功读取的字节数)
+// @return Err(TtyError) 内部错误信息
+// pub fn read_stdin(&mut self, buf: &mut [u8], block: bool) -> Result<usize, TtyError> {
+//     let mut cnt = 0;
+//     loop{
+//         if cnt == buf.len(){
+//             break;
+//         }
+//         let val:Option<u8> = self.stdin_queue.dequeue();
+//         // 如果没读到
+//         if val.is_none() {
+//             // 如果阻塞读
+//             if block {
+//                 let state_guard: RwLockUpgradableGuard<TtyCoreState> =
+//                     self.state.upgradeable_read();
+//                 // 判断是否有进程正在stdin上睡眠,如果有,则忙等读
+//                 // 理论上,这种情况应该不存在,因为stdin是单读者的
+//                 if state_guard.contains(TtyCoreState::BLOCK_AT_STDIN_READ) {
+//                     kwarn!("Read stdin: Process {} want to read its' stdin, but previous process {} is sleeping on the stdin.", current_pcb().pid, self.stdin_waiter.read().as_ref().unwrap().pid);
+//                     drop(state_guard);
+//                     Self::ringbuf_spin_dequeue(&mut buf[cnt], &mut self.stdin_queue);
+//                     cnt += 1;
+//                 } else {
+//                     // 正常情况,阻塞读,将当前进程休眠
+//                     let mut state_guard: RwLockWriteGuard<TtyCoreState> = state_guard.upgrade();
+//                     let mut stdin_waiter_guard: RwLockWriteGuard<
+//                         Option<&mut process_control_block>,
+//                     > = self.stdin_waiter.write();
+
+//                     // 由于输入数据到stdin的时候,必须先获得state guard的读锁。而这里我们已经获取了state的写锁。
+//                     // 因此可以保证,此时没有新的数据会进入stdin_queue. 因此再次尝试读取stdin_queue
+//                     let val:Option<u8> = self.stdin_queue.dequeue();
+//                     // 读到数据,不用睡眠
+//                     if val.is_some(){
+//                         buf[cnt] = val.unwrap();
+//                         cnt += 1;
+//                         continue;
+//                     }
+//                     // 没读到数据,准备睡眠
+
+//                     // 设置等待标志位
+//                     state_guard.set(TtyCoreState::BLOCK_AT_STDIN_READ, true);
+
+//                     // 将当前进程标记为被其他机制管理
+//                     unsafe {
+//                         current_pcb().mark_sleep_interruptible();
+//                     }
+
+//                     *stdin_waiter_guard = Some(current_pcb());
+//                     drop(stdin_waiter_guard);
+//                     drop(state_guard);
+//                     sched();
+//                     continue;
+//                 }
+//             } else {
+//                 // 非阻塞读,没读到就直接返回了
+//                 return Ok(cnt);
+//             }
+//         }else{
+//             buf[cnt] = val.unwrap();
+//             cnt += 1;
+//         }
+//     }
+
+//     return Ok(cnt);
+// }
+
+// fn write_stdin(&self)
+
+// /// @brief 非休眠的,自旋地读队列,直到有元素被读出来
+// fn ringbuf_spin_dequeue(dst: &mut u8, queue: &mut AllocRingBuffer<u8>) {
+//     loop {
+//         if let Some(val) = queue.dequeue() {
+//             *dst = val;
+//             return;
+//         }
+//     }
+// }

+ 0 - 92
kernel/src/driver/tty/tty.c

@@ -1,92 +0,0 @@
-#include <filesystem/vfs/VFS.h>
-#include "tty.h"
-
-static struct devfs_private_inode_info_t * tty_inode_private_data_ptr;  // 由devfs创建的inode私有信息指针
-static int tty_private_data;
-
-/**
- * @brief 打开tty文件
- *
- * @param inode 所在的inode
- * @param filp 文件指针
- * @return long
- */
-long tty_open(struct vfs_index_node_t *inode, struct vfs_file_t *filp)
-{
-    filp->private_data = &tty_private_data;
-    return 0;
-}
-
-/**
- * @brief 关闭tty文件
- *
- * @param inode 所在的inode
- * @param filp 文件指针
- * @return long
- */
-long tty_close(struct vfs_index_node_t *inode, struct vfs_file_t *filp)
-{
-    filp->private_data = NULL;
-    return 0;
-}
-
-/**
- * @brief tty控制接口
- *
- * @param inode 所在的inode
- * @param filp tty文件指针
- * @param cmd 命令
- * @param arg 参数
- * @return long
- */
-long tty_ioctl(struct vfs_index_node_t *inode, struct vfs_file_t *filp, uint64_t cmd, uint64_t arg)
-{
-    switch (cmd)
-    {
-    default:
-        break;
-    }
-    return 0;
-}
-
-/**
- * @brief 读取tty文件的操作接口
- *
- * @param filp 文件指针
- * @param buf 输出缓冲区
- * @param count 要读取的字节数
- * @param position 读取的位置
- * @return long 读取的字节数
- */
-long tty_read(struct vfs_file_t *filp, char *buf, int64_t count, long *position)
-{
-    return 0;
-}
-
-/**
- * @brief tty文件写入接口(无作用,空)
- *
- * @param filp
- * @param buf
- * @param count
- * @param position
- * @return long
- */
-long tty_write(struct vfs_file_t *filp, char *buf, int64_t count, long *position)
-{
-    return 0;
-}
-
-struct vfs_file_operations_t tty_fops={
-    .open = tty_open,
-    .close = tty_close,
-    .ioctl = tty_ioctl,
-    .read = tty_read,
-    .write = tty_write,
-};
-
-// void tty_init(){
-//     //注册devfs
-//     devfs_register_device(DEV_TYPE_CHAR, CHAR_DEV_STYPE_TTY, &tty_fops, &tty_inode_private_data_ptr);
-//     kinfo("tty driver registered. uuid=%d", tty_inode_private_data_ptr->uuid);
-// }

+ 0 - 3
kernel/src/driver/tty/tty.h

@@ -1,3 +0,0 @@
-#pragma once
-
-void tty_init();

+ 135 - 0
kernel/src/driver/tty/tty_device.rs

@@ -0,0 +1,135 @@
+use alloc::sync::{Arc, Weak};
+
+use crate::{
+    filesystem::{
+        devfs::{DeviceINode, DevFS},
+        vfs::{file::FileMode, FilePrivateData, IndexNode},
+    },
+    include::bindings::bindings::{ECONNABORTED, EIO, ENOTSUP, EPERM},
+    kerror, libs::rwlock::RwLock,
+};
+
+use super::{TtyCore, TtyError, TtyFileFlag, TtyFilePrivateData};
+
+#[derive(Debug)]
+pub struct TtyDevice {
+    core: TtyCore,
+    fs: RwLock<Weak<DevFS>>
+    
+}
+
+impl TtyDevice {
+    pub fn new() -> Arc<TtyDevice> {
+        return Arc::new(TtyDevice {
+            core: TtyCore::new(),
+            fs: RwLock::new(Weak::default()),
+        });
+    }
+
+    /// @brief 判断文件私有信息是否为TTY的私有信息
+    #[inline]
+    fn verify_file_private_data<'a>(
+        &self,
+        private_data: &'a mut FilePrivateData,
+    ) -> Result<&'a mut TtyFilePrivateData, i32> {
+        if let FilePrivateData::Tty(t) = private_data {
+            return Ok(t);
+        }
+        return Err(-(EIO as i32));
+    }
+}
+
+impl DeviceINode for TtyDevice {
+    fn set_fs(&self, fs: alloc::sync::Weak<crate::filesystem::devfs::DevFS>) {
+        *self.fs.write() = fs;
+    }
+}
+
+impl IndexNode for TtyDevice {
+    fn open(&self, data: &mut FilePrivateData, mode: &FileMode) -> Result<(), i32> {
+        let p = TtyFilePrivateData::default();
+        *data = FilePrivateData::Tty(p);
+        return Ok(());
+    }
+
+    fn read_at(
+        &self,
+        offset: usize,
+        len: usize,
+        buf: &mut [u8],
+        data: &mut crate::filesystem::vfs::FilePrivateData,
+    ) -> Result<usize, i32> {
+        let _data: &mut TtyFilePrivateData = match self.verify_file_private_data(data) {
+            Ok(t) => t,
+            Err(e) => {
+                kerror!("Try to read tty device, but file private data type mismatch!");
+                return Err(e);
+            }
+        };
+
+        // 读取stdin队列
+        let r: Result<usize, TtyError> = self.core.read_stdin(buf, true);
+        if r.is_ok() {
+            return Ok(r.unwrap());
+        }
+
+        match r.unwrap_err() {
+            TtyError::EOF(n) => {
+                return Ok(n);
+            }
+            x => {
+                kerror!("Error occurred when reading tty, msg={x:?}");
+                return Err(-(ECONNABORTED as i32));
+            }
+        }
+    }
+
+    fn write_at(
+        &self,
+        offset: usize,
+        len: usize,
+        buf: &[u8],
+        data: &mut crate::filesystem::vfs::FilePrivateData,
+    ) -> Result<usize, i32> {
+        let data: &mut TtyFilePrivateData = match self.verify_file_private_data(data) {
+            Ok(t) => t,
+            Err(e) => {
+                kerror!("Try to write tty device, but file private data type mismatch!");
+                return Err(e);
+            }
+        };
+
+        // 根据当前文件是stdout还是stderr,选择不同的发送方式
+        let r: Result<usize, TtyError> = if data.flags.contains(TtyFileFlag::STDOUT) {
+            self.core.stdout(buf, true)
+        } else if data.flags.contains(TtyFileFlag::STDERR) {
+            self.core.stderr(buf, true)
+        } else {
+            return Err(-(EPERM as i32));
+        };
+
+        if r.is_ok() {
+            return Ok(r.unwrap());
+        }
+
+        let r: TtyError = r.unwrap_err();
+        kerror!("Error occurred when writing tty deivce. Error msg={r:?}");
+        return Err(-(EIO as i32));
+    }
+
+    fn poll(&self) -> Result<crate::filesystem::vfs::PollStatus, i32> {
+        return Err(-(ENOTSUP as i32));
+    }
+
+    fn fs(&self) -> Arc<dyn crate::filesystem::vfs::FileSystem> {
+        return self.fs.read().upgrade().unwrap();
+    }
+
+    fn as_any_ref(&self) -> &dyn core::any::Any {
+        self
+    }
+
+    fn list(&self) -> Result<alloc::vec::Vec<alloc::string::String>, i32> {
+        return Err(-(ENOTSUP as i32));
+    }
+}

+ 2 - 2
kernel/src/filesystem/devfs/mod.rs

@@ -4,7 +4,7 @@ pub mod zero_dev;
 
 use super::vfs::{
     core::{generate_inode_id, ROOT_INODE},
-    FileSystem, FileType, FsInfo, IndexNode, Metadata, PollStatus,
+    FileSystem, FileType, FsInfo, IndexNode, Metadata, PollStatus, file::FileMode,
 };
 use crate::{
     include::bindings::bindings::{EEXIST, EISDIR, ENOENT, ENOTDIR, ENOTSUP},
@@ -322,7 +322,7 @@ impl IndexNode for LockedDevFSInode {
         self
     }
 
-    fn open(&self, _data: &mut super::vfs::FilePrivateData) -> Result<(), i32> {
+    fn open(&self, _data: &mut super::vfs::FilePrivateData, _mode: &FileMode) -> Result<(), i32> {
         return Ok(());
     }
 

+ 2 - 1
kernel/src/filesystem/devfs/null_dev.rs

@@ -1,3 +1,4 @@
+use crate::filesystem::vfs::file::FileMode;
 use crate::filesystem::vfs::make_rawdev;
 use crate::filesystem::vfs::{
     core::generate_inode_id, FilePrivateData, FileSystem, FileType, IndexNode, Metadata, PollStatus,
@@ -72,7 +73,7 @@ impl IndexNode for LockedNullInode {
         self
     }
 
-    fn open(&self, _data: &mut FilePrivateData) -> Result<(), i32> {
+    fn open(&self, _data: &mut FilePrivateData, _mode: &FileMode) -> Result<(), i32> {
         Err(-(ENOTSUP as i32))
     }
 

+ 2 - 1
kernel/src/filesystem/devfs/zero_dev.rs

@@ -1,3 +1,4 @@
+use crate::filesystem::vfs::file::FileMode;
 use crate::filesystem::vfs::make_rawdev;
 use crate::filesystem::vfs::{
     core::generate_inode_id, FilePrivateData, FileSystem, FileType, IndexNode, Metadata, PollStatus,
@@ -72,7 +73,7 @@ impl IndexNode for LockedZeroInode {
         self
     }
 
-    fn open(&self, _data: &mut FilePrivateData) -> Result<(), i32> {
+    fn open(&self, _data: &mut FilePrivateData, _mode: &FileMode) -> Result<(), i32> {
         Err(-(ENOTSUP as i32))
     }
 

+ 2 - 2
kernel/src/filesystem/fat/fs.rs

@@ -10,7 +10,7 @@ use alloc::{
 
 use crate::{
     filesystem::vfs::{
-        core::generate_inode_id, file::FilePrivateData, FileSystem, FileType, IndexNode, InodeId,
+        core::generate_inode_id, file::{FilePrivateData, FileMode}, FileSystem, FileType, IndexNode, InodeId,
         Metadata, PollStatus,
     },
     include::bindings::bindings::{
@@ -1506,7 +1506,7 @@ impl IndexNode for LockedFATInode {
         return Ok(target);
     }
 
-    fn open(&self, _data: &mut FilePrivateData) -> Result<(), i32> {
+    fn open(&self, _data: &mut FilePrivateData, _mode: &FileMode) -> Result<(), i32> {
         return Ok(());
     }
 

+ 2 - 2
kernel/src/filesystem/procfs/mod.rs

@@ -24,7 +24,7 @@ use crate::{
 };
 
 use super::vfs::{
-    file::FilePrivateData, FileSystem, FsInfo, IndexNode, InodeId, Metadata, PollStatus,
+    file::{FilePrivateData, FileMode}, FileSystem, FsInfo, IndexNode, InodeId, Metadata, PollStatus,
 };
 
 /// @brief 进程文件类型
@@ -319,7 +319,7 @@ impl ProcFS {
 }
 
 impl IndexNode for LockedProcFSInode {
-    fn open(&self, data: &mut FilePrivateData) -> Result<(), i32> {
+    fn open(&self, data: &mut FilePrivateData, _mode: &FileMode) -> Result<(), i32> {
         // 加锁
         let mut inode: SpinLockGuard<ProcFSInode> = self.0.lock();
 

+ 6 - 4
kernel/src/filesystem/vfs/file.rs

@@ -9,7 +9,7 @@ use crate::{
         process_control_block, EINVAL, ENOBUFS, EOVERFLOW, EPERM, ESPIPE,
     },
     io::SeekFrom,
-    kerror,
+    kerror, driver::tty::TtyFilePrivateData,
 };
 
 use super::{Dirent, FileType, IndexNode, Metadata};
@@ -17,9 +17,11 @@ use super::{Dirent, FileType, IndexNode, Metadata};
 /// 文件私有信息的枚举类型
 #[derive(Debug, Clone)]
 pub enum FilePrivateData {
-    // procfs文件私有信息
+    /// procfs文件私有信息
     Procfs(ProcfsFilePrivateData),
-    // 不需要文件私有信息
+    /// Tty设备的私有信息
+    Tty(TtyFilePrivateData),
+    /// 不需要文件私有信息
     Unused,
 }
 
@@ -107,7 +109,7 @@ impl File {
             private_data: FilePrivateData::default(),
         };
         // kdebug!("inode:{:?}",f.inode);
-        f.inode.open(&mut f.private_data)?;
+        f.inode.open(&mut f.private_data, &mode)?;
         return Ok(f);
     }
 

+ 2 - 1
kernel/src/filesystem/vfs/mod.rs

@@ -15,6 +15,7 @@ use crate::{
     time::TimeSpec,
 };
 
+use self::file::FileMode;
 pub use self::{core::ROOT_INODE, file::FilePrivateData, mount::MountFS};
 
 /// vfs容许的最大的路径名称长度
@@ -91,7 +92,7 @@ pub trait IndexNode: Any + Sync + Send + Debug {
     ///
     /// @return 成功:Ok()
     ///         失败:Err(错误码)
-    fn open(&self, _data: &mut FilePrivateData) -> Result<(), i32> {
+    fn open(&self, _data: &mut FilePrivateData, _mode: &FileMode) -> Result<(), i32> {
         // 若文件系统没有实现此方法,则返回“不支持”
         return Err(-(ENOTSUP as i32));
     }

+ 3 - 3
kernel/src/filesystem/vfs/mount.rs

@@ -10,7 +10,7 @@ use crate::{
     libs::spinlock::SpinLock,
 };
 
-use super::{FilePrivateData, FileSystem, FileType, IndexNode, InodeId};
+use super::{FilePrivateData, FileSystem, FileType, IndexNode, InodeId, file::FileMode};
 
 /// @brief 挂载文件系统
 /// 挂载文件系统的时候,套了MountFS这一层,以实现文件系统的递归挂载
@@ -126,8 +126,8 @@ impl MountFSInode {
 }
 
 impl IndexNode for MountFSInode {
-    fn open(&self, data: &mut FilePrivateData) -> Result<(), i32> {
-        return self.inner_inode.open(data);
+    fn open(&self, data: &mut FilePrivateData, mode: &FileMode) -> Result<(), i32> {
+        return self.inner_inode.open(data, mode);
     }
 
     fn close(&self, data: &mut FilePrivateData) -> Result<(), i32> {

+ 1 - 0
kernel/src/io/device.rs

@@ -45,6 +45,7 @@ pub trait Device: Any + Send + Sync + Debug {
     fn sync(&self) -> Result<(), i32>;
 
     // TODO: 待实现 open, close
+
 }
 
 /// @brief 块设备应该实现的操作

+ 1 - 1
kernel/src/lib.rs

@@ -38,7 +38,7 @@ extern crate lazy_static;
 
 #[macro_use]
 extern crate bitflags;
-
+extern crate thingbuf;
 
 use mm::allocator::KernelAllocator;
 

+ 0 - 1
kernel/src/main.c

@@ -28,7 +28,6 @@
 #include "driver/mouse/ps2_mouse.h"
 #include "driver/multiboot2/multiboot2.h"
 #include "driver/pci/pci.h"
-#include "driver/tty/tty.h"
 #include <driver/timers/HPET/HPET.h>
 #include <driver/uart/uart.h>
 #include <driver/usb/usb.h>

+ 18 - 1
kernel/src/process/process.rs

@@ -9,7 +9,8 @@ use crate::{
     arch::asm::current::current_pcb,
     filesystem::vfs::file::{File, FileDescriptorVec},
     include::bindings::bindings::{
-        process_control_block, CLONE_FS, EBADF, EFAULT, ENFILE, EPERM, PROC_RUNNING, PROC_STOPPED,
+        process_control_block, CLONE_FS, EBADF, EFAULT, ENFILE, EPERM, PROC_INTERRUPTIBLE,
+        PROC_RUNNING, PROC_STOPPED, PROC_UNINTERRUPTIBLE,
     },
     sched::core::{cpu_executing, sched_enqueue},
     smp::core::{smp_get_processor_id, smp_send_reschedule},
@@ -253,6 +254,22 @@ impl process_control_block {
 
         return Ok(());
     }
+
+    /// @brief 标记当前pcb已经由其他机制进行管理,调度器将不会将他加入队列(且进程可以被信号打断)
+    /// 当我们要把一个进程,交给其他机制管理时,那么就应该调用本函数。
+    ///
+    /// 由于本函数可能造成进程不再被调度,因此标记为unsafe
+    pub unsafe fn mark_sleep_interruptible(&mut self){
+        self.state = PROC_INTERRUPTIBLE as u64;
+    }
+
+    /// @brief 标记当前pcb已经由其他机制进行管理,调度器将不会将他加入队列(且进程不可以被信号打断)
+    /// 当我们要把一个进程,交给其他机制管理时,那么就应该调用本函数
+    ///
+    /// 由于本函数可能造成进程不再被调度,因此标记为unsafe
+    pub unsafe fn mark_sleep_uninterruptible(&mut self){
+        self.state = PROC_UNINTERRUPTIBLE as u64;
+    }
 }
 
 // =========== 导出到C的函数,在将来,进程管理模块被完全重构之后,需要删掉他们  BEGIN ============