Sfoglia il codice sorgente

将TTY与stdio进行连接,实现基本的stdio功能 (#217)

* 将stdio与tty接上
login 1 anno fa
parent
commit
20e3152e1e

+ 5 - 5
kernel/src/driver/keyboard/ps2_keyboard.c

@@ -146,11 +146,11 @@ void ps2_keyboard_handler(ul irq_num, ul buf_vaddr, struct pt_regs *regs)
     unsigned char x = io_in8(PORT_PS2_KEYBOARD_DATA);
     ps2_keyboard_parse_keycode((uint8_t)x);
     uint8_t count = kfifo_in((struct kfifo_t *)buf_vaddr, &x, sizeof(unsigned char));
-    if (count == 0)
-    {
-        kwarn("ps2 keyboard buffer full.");
-        return;
-    }
+    // if (count == 0)
+    // {
+    //     kwarn("ps2 keyboard buffer full.");
+    //     return;
+    // }
 
     wait_queue_wakeup(&ps2_keyboard_wait_queue, PROC_UNINTERRUPTIBLE);
     

+ 9 - 1
kernel/src/driver/keyboard/ps2_keyboard.rs

@@ -3,6 +3,7 @@ use core::sync::atomic::AtomicI32;
 use alloc::sync::{Arc, Weak};
 
 use crate::{
+    driver::tty::tty_device::TTY_DEVICES,
     filesystem::{
         devfs::{devfs_register, DevFS, DeviceINode},
         vfs::{core::generate_inode_id, file::FileMode, FileType, IndexNode, Metadata, PollStatus},
@@ -17,7 +18,14 @@ use crate::{
 pub struct LockedPS2KeyBoardInode(RwLock<PS2KeyBoardInode>, AtomicI32); // self.1 用来记录有多少个文件打开了这个inode
 
 lazy_static! {
-    static ref PS2_KEYBOARD_FSM: SpinLock<TypeOneFSM> = SpinLock::new(TypeOneFSM::new());
+    static ref PS2_KEYBOARD_FSM: SpinLock<TypeOneFSM> = {
+        let tty0 = TTY_DEVICES
+            .read()
+            .get("tty0")
+            .expect("Initializing PS2_KEYBOARD_FSM: Cannot found TTY0!")
+            .clone();
+        SpinLock::new(TypeOneFSM::new(tty0))
+    };
 }
 
 #[derive(Debug)]

+ 5 - 2
kernel/src/driver/tty/mod.rs

@@ -5,7 +5,7 @@ use thingbuf::mpsc::{
     errors::{TryRecvError, TrySendError},
 };
 
-use crate::libs::rwlock::RwLock;
+use crate::{libs::rwlock::RwLock, kdebug};
 
 pub mod tty_device;
 
@@ -59,6 +59,7 @@ struct TtyCore {
 }
 
 #[derive(Debug)]
+#[allow(dead_code)]
 pub enum TtyError {
     /// 缓冲区满,返回成功传送的字节数
     BufferFull(usize),
@@ -281,16 +282,18 @@ impl TtyCore {
 
     /// @brief 关闭输入回显
     #[inline]
+    #[allow(dead_code)]
     pub fn disable_echo(&self) {
         self.state.write().set(TtyCoreState::ECHO_ON, false);
     }
-
+    
     /// @brief 判断当前tty核心,是否开启了输入回显
     ///
     /// @return true 开启了输入回显
     ///
     /// @return false 未开启输入回显
     #[inline]
+    #[allow(dead_code)]
     pub fn echo_enabled(&self) -> bool {
         return self.state.read().contains(TtyCoreState::ECHO_ON);
     }

+ 199 - 15
kernel/src/driver/tty/tty_device.rs

@@ -1,31 +1,62 @@
-use alloc::sync::{Arc, Weak};
+use alloc::{
+    collections::BTreeMap,
+    string::{String, ToString},
+    sync::{Arc, Weak},
+};
 
 use crate::{
     filesystem::{
-        devfs::{DeviceINode, DevFS},
-        vfs::{file::FileMode, FilePrivateData, IndexNode},
+        devfs::{devfs_register, DevFS, DeviceINode},
+        vfs::{file::FileMode, FilePrivateData, FileType, IndexNode, Metadata, ROOT_INODE},
     },
-    kerror, libs::rwlock::RwLock, syscall::SystemError,
+    include::bindings::bindings::{printk_color, textui_putchar, BLACK, WHITE},
+    kdebug, kerror,
+    libs::rwlock::RwLock,
+    print,
+    syscall::SystemError,
 };
 
 use super::{TtyCore, TtyError, TtyFileFlag, TtyFilePrivateData};
 
+lazy_static! {
+    /// 所有TTY设备的B树。用于根据名字,找到Arc<TtyDevice>
+    /// TODO: 待设备驱动模型完善,具有类似功能的机制后,删掉这里
+    pub static ref TTY_DEVICES: RwLock<BTreeMap<String, Arc<TtyDevice>>> = RwLock::new(BTreeMap::new());
+}
+
+/// @brief TTY设备
 #[derive(Debug)]
 pub struct TtyDevice {
+    /// TTY核心
     core: TtyCore,
-    fs: RwLock<Weak<DevFS>>
-    
+    /// TTY所属的文件系统
+    fs: RwLock<Weak<DevFS>>,
+    /// TTY设备私有信息
+    private_data: RwLock<TtyDevicePrivateData>,
+}
+
+#[derive(Debug)]
+struct TtyDevicePrivateData {
+    /// TTY设备名(如tty1)
+    name: String,
+    /// TTY设备文件的元数据
+    metadata: Metadata,
+    // TODO: 增加指向输出端口连接的设备的指针
 }
 
 impl TtyDevice {
-    pub fn new() -> Arc<TtyDevice> {
-        return Arc::new(TtyDevice {
+    pub fn new(name: &str) -> Arc<TtyDevice> {
+        let result = Arc::new(TtyDevice {
             core: TtyCore::new(),
             fs: RwLock::new(Weak::default()),
+            private_data: TtyDevicePrivateData::new(name),
         });
+        // 默认开启输入回显
+        result.core.enable_echo();
+        return result;
     }
 
-    /// @brief 判断文件私有信息是否为TTY的私有信息
+    /// @brief 判断文件私有信息是否为TTY文件的私有信息
     #[inline]
     fn verify_file_private_data<'a>(
         &self,
@@ -36,6 +67,39 @@ impl TtyDevice {
         }
         return Err(SystemError::EIO);
     }
+
+    /// @brief 获取TTY设备名
+    #[inline]
+    pub fn name(&self) -> String {
+        return self.private_data.read().name.clone();
+    }
+
+    /// @brief 检查TTY文件的读写参数是否合法
+    #[inline]
+    pub fn check_rw_param(&self, len: usize, buf: &[u8]) -> Result<(), SystemError> {
+        if len > buf.len() {
+            return Err(SystemError::EINVAL);
+        }
+        return Ok(());
+    }
+
+    /// @brief 向TTY的输入端口导入数据
+    pub fn input(&self, buf: &[u8]) -> Result<usize, SystemError> {
+        let r: Result<usize, TtyError> = self.core.input(buf, false);
+        if r.is_ok() {
+            return Ok(r.unwrap());
+        }
+
+        let r = r.unwrap_err();
+        match r {
+            TtyError::BufferFull(x) => return Ok(x),
+            TtyError::Closed => return Err(SystemError::ENODEV),
+            e => {
+                kerror!("tty error occurred while writing data to its input port, msg={e:?}");
+                return Err(SystemError::EBUSY);
+            }
+        }
+    }
 }
 
 impl DeviceINode for TtyDevice {
@@ -45,15 +109,40 @@ impl DeviceINode for TtyDevice {
 }
 
 impl IndexNode for TtyDevice {
+    /// @brief 打开TTY设备
+    ///
+    /// @param data 文件私有信息
+    /// @param mode 打开模式
+    ///
+    /// TTY设备通过mode来确定这个文件到底是stdin/stdout/stderr
+    /// - mode的值为O_RDONLY时,表示这个文件是stdin
+    /// - mode的值为O_WRONLY时,表示这个文件是stdout
+    /// - mode的值为O_WRONLY | O_SYNC时,表示这个文件是stderr
     fn open(&self, data: &mut FilePrivateData, mode: &FileMode) -> Result<(), SystemError> {
-        let p = TtyFilePrivateData::default();
+        let mut p = TtyFilePrivateData::default();
+
+        // 检查打开模式
+        let accmode = mode.accmode();
+        if accmode == FileMode::O_RDONLY.accmode() {
+            p.flags.insert(TtyFileFlag::STDIN);
+        } else if accmode == FileMode::O_WRONLY.accmode() {
+            if mode.contains(FileMode::O_SYNC) {
+                p.flags.insert(TtyFileFlag::STDERR);
+            } else {
+                p.flags.insert(TtyFileFlag::STDOUT);
+            }
+        } else {
+            return Err(SystemError::EINVAL);
+        }
+
+        // 保存文件私有信息
         *data = FilePrivateData::Tty(p);
         return Ok(());
     }
 
     fn read_at(
         &self,
-        offset: usize,
+        _offset: usize,
         len: usize,
         buf: &mut [u8],
         data: &mut crate::filesystem::vfs::FilePrivateData,
@@ -65,9 +154,10 @@ impl IndexNode for TtyDevice {
                 return Err(e);
             }
         };
+        self.check_rw_param(len, buf)?;
 
         // 读取stdin队列
-        let r: Result<usize, TtyError> = self.core.read_stdin(buf, true);
+        let r: Result<usize, TtyError> = self.core.read_stdin(&mut buf[0..len], true);
         if r.is_ok() {
             return Ok(r.unwrap());
         }
@@ -76,6 +166,7 @@ impl IndexNode for TtyDevice {
             TtyError::EOF(n) => {
                 return Ok(n);
             }
+
             x => {
                 kerror!("Error occurred when reading tty, msg={x:?}");
                 return Err(SystemError::ECONNABORTED);
@@ -85,7 +176,7 @@ impl IndexNode for TtyDevice {
 
     fn write_at(
         &self,
-        offset: usize,
+        _offset: usize,
         len: usize,
         buf: &[u8],
         data: &mut crate::filesystem::vfs::FilePrivateData,
@@ -98,16 +189,19 @@ impl IndexNode for TtyDevice {
             }
         };
 
+        self.check_rw_param(len, buf)?;
+
         // 根据当前文件是stdout还是stderr,选择不同的发送方式
         let r: Result<usize, TtyError> = if data.flags.contains(TtyFileFlag::STDOUT) {
-            self.core.stdout(buf, true)
+            self.core.stdout(&buf[0..len], true)
         } else if data.flags.contains(TtyFileFlag::STDERR) {
-            self.core.stderr(buf, true)
+            self.core.stderr(&buf[0..len], true)
         } else {
             return Err(SystemError::EPERM);
         };
 
         if r.is_ok() {
+            self.sync().expect("Failed to sync tty device!");
             return Ok(r.unwrap());
         }
 
@@ -131,4 +225,94 @@ impl IndexNode for TtyDevice {
     fn list(&self) -> Result<alloc::vec::Vec<alloc::string::String>, SystemError> {
         return Err(SystemError::ENOTSUP);
     }
+
+    fn metadata(&self) -> Result<Metadata, SystemError> {
+        return Ok(self.private_data.read().metadata.clone());
+    }
+
+    fn close(&self, _data: &mut FilePrivateData) -> Result<(), SystemError> {
+        return Ok(());
+    }
+
+    fn sync(&self) -> Result<(), SystemError> {
+        // TODO: 引入IO重定向后,需要将输出重定向到对应的设备。
+        // 目前只是简单的输出到屏幕(为了实现的简便)
+
+        loop {
+            let mut buf = [0u8; 512];
+            let r: Result<usize, TtyError> = self.core.read_output(&mut buf[0..511], false);
+            let len;
+            match r {
+                Ok(x) => {
+                    len = x;
+                }
+                Err(TtyError::EOF(x)) | Err(TtyError::BufferEmpty(x)) => {
+                    len = x;
+                }
+                _ => return Err(SystemError::EIO),
+            }
+
+            if len == 0 {
+                break;
+            }
+            // 输出到屏幕
+            print!("{}", unsafe {
+                core::str::from_utf8_unchecked(&buf[0..len])
+            });
+        }
+        return Ok(());
+    }
+}
+
+impl TtyDevicePrivateData {
+    pub fn new(name: &str) -> RwLock<Self> {
+        let mut metadata = Metadata::new(FileType::CharDevice, 0o755);
+        metadata.size = TtyCore::STDIN_BUF_SIZE as i64;
+        return RwLock::new(TtyDevicePrivateData {
+            name: name.to_string(),
+            metadata,
+        });
+    }
+}
+
+/// @brief 导出到C的tty初始化函数
+#[no_mangle]
+pub extern "C" fn rs_tty_init() -> i32 {
+    let r = tty_init();
+    if r.is_ok() {
+        return 0;
+    } else {
+        return r.unwrap_err().to_posix_errno();
+    }
+}
+
+/// @brief 初始化TTY设备
+pub fn tty_init() -> Result<(), SystemError> {
+    let tty: Arc<TtyDevice> = TtyDevice::new("tty0");
+    let devfs_root_inode = ROOT_INODE().lookup("/dev");
+    if devfs_root_inode.is_err() {
+        return Err(devfs_root_inode.unwrap_err());
+    }
+    // 当前关闭键盘输入回显
+    // TODO: 完善Termios之后, 改为默认开启键盘输入回显.
+    tty.core.disable_echo();
+    let guard = TTY_DEVICES.upgradeable_read();
+
+    // 如果已经存在了这个设备
+    if guard.contains_key("tty0") {
+        return Err(SystemError::EEXIST);
+    }
+
+    let mut guard = guard.upgrade();
+
+    guard.insert("tty0".to_string(), tty.clone());
+
+    drop(guard);
+
+    let r = devfs_register(&tty.name(), tty);
+    if r.is_err() {
+        return Err(devfs_root_inode.unwrap_err());
+    }
+
+    return Ok(());
 }

+ 27 - 8
kernel/src/filesystem/devfs/mod.rs

@@ -10,7 +10,8 @@ use super::vfs::{
 use crate::{
     kerror,
     libs::spinlock::{SpinLock, SpinLockGuard},
-    time::TimeSpec, syscall::SystemError,
+    syscall::SystemError,
+    time::TimeSpec,
 };
 use alloc::{
     collections::BTreeMap,
@@ -94,9 +95,14 @@ impl DevFS {
     ///
     /// @param name 设备名称
     /// @param device 设备节点的结构体
-    pub fn register_device<T: DeviceINode>(&self, name: &str, device: Arc<T>) -> Result<(), SystemError> {
+    pub fn register_device<T: DeviceINode>(
+        &self,
+        name: &str,
+        device: Arc<T>,
+    ) -> Result<(), SystemError> {
         let dev_root_inode: Arc<LockedDevFSInode> = self.root_inode.clone();
-        match device.metadata().unwrap().file_type {
+        let metadata = device.metadata()?;
+        match metadata.file_type {
             // 字节设备挂载在 /dev/char
             FileType::CharDevice => {
                 if let Err(_) = dev_root_inode.find("char") {
@@ -108,8 +114,13 @@ impl DevFS {
                     .as_any_ref()
                     .downcast_ref::<LockedDevFSInode>()
                     .unwrap();
-
+                // 在 /dev/char 下创建设备节点
                 dev_char_inode.add_dev(name, device.clone())?;
+
+                // 特殊处理 tty 设备,挂载在 /dev 下
+                if name.starts_with("tty") && name.len() > 3 {
+                    dev_root_inode.add_dev(name, device.clone())?;
+                }
                 device.set_fs(dev_char_inode.0.lock().fs.clone());
             }
             FileType::BlockDevice => {
@@ -135,7 +146,11 @@ impl DevFS {
     }
 
     /// @brief 卸载设备
-    pub fn unregister_device<T: DeviceINode>(&self, name: &str, device: Arc<T>) -> Result<(), SystemError> {
+    pub fn unregister_device<T: DeviceINode>(
+        &self,
+        name: &str,
+        device: Arc<T>,
+    ) -> Result<(), SystemError> {
         let dev_root_inode: Arc<LockedDevFSInode> = self.root_inode.clone();
         match device.metadata().unwrap().file_type {
             // 字节设备挂载在 /dev/char
@@ -325,7 +340,11 @@ impl IndexNode for LockedDevFSInode {
         self
     }
 
-    fn open(&self, _data: &mut super::vfs::FilePrivateData, _mode: &FileMode) -> Result<(), SystemError> {
+    fn open(
+        &self,
+        _data: &mut super::vfs::FilePrivateData,
+        _mode: &FileMode,
+    ) -> Result<(), SystemError> {
         return Ok(());
     }
 
@@ -459,6 +478,7 @@ impl IndexNode for LockedDevFSInode {
         _buf: &mut [u8],
         _data: &mut super::vfs::file::FilePrivateData,
     ) -> Result<usize, SystemError> {
+        kerror!("DevFS: read_at is not supported!");
         Err(SystemError::ENOTSUP)
     }
 
@@ -485,7 +505,7 @@ macro_rules! devfs_exact_ref {
     () => {{
         let devfs_inode: Result<Arc<dyn IndexNode>, SystemError> = ROOT_INODE().find("dev");
         if let Err(e) = devfs_inode {
-            kerror!("failed to get DevFS ref. errcode = {:?}",e);
+            kerror!("failed to get DevFS ref. errcode = {:?}", e);
             return Err(SystemError::ENOENT);
         }
 
@@ -511,4 +531,3 @@ pub fn devfs_register<T: DeviceINode>(name: &str, device: Arc<T>) -> Result<(),
 pub fn devfs_unregister<T: DeviceINode>(name: &str, device: Arc<T>) -> Result<(), SystemError> {
     return devfs_exact_ref!().unregister_device(name, device);
 }
-

+ 11 - 3
kernel/src/filesystem/vfs/file.rs

@@ -62,7 +62,7 @@ bitflags! {
     const O_APPEND = 0o00002000;
     /// 非阻塞式IO模式
     const O_NONBLOCK = 0o00004000;
-    /// used to be O_SYNC, see below
+    /// 每次write都等待物理I/O完成,但是如果写操作不影响读取刚写入的数据,则不等待文件属性更新
     const O_DSYNC = 0o00010000;
     /// fcntl, for BSD compatibility
     const FASYNC = 0o00020000;
@@ -76,9 +76,18 @@ bitflags! {
     const O_NOATIME = 0o01000000;
     /// set close_on_exec
     const O_CLOEXEC = 0o02000000;
+    /// 每次write都等到物理I/O完成,包括write引起的文件属性的更新
+    const O_SYNC = 0o04000000;
     }
 }
 
+impl FileMode {
+    /// @brief 获取文件的访问模式的值
+    #[inline]
+    pub fn accmode(&self) -> u32 {
+        return self.bits() & FileMode::O_ACCMODE.bits();
+    }
+}
 /// @brief 抽象文件结构体
 #[derive(Debug)]
 pub struct File {
@@ -128,7 +137,6 @@ impl File {
         if buf.len() < len {
             return Err(SystemError::ENOBUFS);
         }
-
         let len = self
             .inode
             .read_at(self.offset, len, buf, &mut self.private_data)?;
@@ -151,7 +159,7 @@ impl File {
         }
         let len = self
             .inode
-            .write_at(self.offset, len, buf, &mut FilePrivateData::Unused)?;
+            .write_at(self.offset, len, buf, &mut self.private_data)?;
         self.offset += len;
         return Ok(len);
     }

+ 29 - 3
kernel/src/filesystem/vfs/mod.rs

@@ -15,7 +15,7 @@ use crate::{
     syscall::SystemError,
 };
 
-use self::file::FileMode;
+use self::{core::generate_inode_id, file::FileMode};
 pub use self::{core::ROOT_INODE, file::FilePrivateData, mount::MountFS};
 
 /// vfs容许的最大的路径名称长度
@@ -234,9 +234,9 @@ pub trait IndexNode: Any + Sync + Send + Debug {
     }
 
     /// @brief 删除文件夹
-    /// 
+    ///
     /// @param name 文件夹名称
-    /// 
+    ///
     /// @return 成功 Ok(())
     /// @return 失败 Err(错误码)
     fn rmdir(&self, _name: &str) ->Result<(), SystemError>{
@@ -332,6 +332,11 @@ pub trait IndexNode: Any + Sync + Send + Debug {
     fn truncate(&self, _len: usize) -> Result<(), SystemError> {
         return Err(SystemError::ENOTSUP);
     }
+
+    /// @brief 将当前inode的内容同步到具体设备上
+    fn sync(&self) -> Result<(), SystemError> {
+        return Ok(());
+    }
 }
 
 impl dyn IndexNode {
@@ -516,3 +521,24 @@ pub struct Dirent {
     d_type: u8,    // entry的类型
     d_name: u8,    // 文件entry的名字(是一个零长数组), 本字段仅用于占位
 }
+
+impl Metadata {
+    pub fn new(file_type: FileType, mode: u32) -> Self {
+        Metadata {
+            dev_id: 0,
+            inode_id: generate_inode_id(),
+            size: 0,
+            blk_size: 0,
+            blocks: 0,
+            atime: TimeSpec::default(),
+            mtime: TimeSpec::default(),
+            ctime: TimeSpec::default(),
+            file_type,
+            mode,
+            nlinks: 1,
+            uid: 0,
+            gid: 0,
+            raw_dev: 0,
+        }
+    }
+}

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

@@ -164,11 +164,11 @@ impl IndexNode for MountFSInode {
         offset: usize,
         len: usize,
         buf: &[u8],
-        _data: &mut FilePrivateData,
+        data: &mut FilePrivateData,
     ) -> Result<usize, SystemError> {
         return self
             .inner_inode
-            .write_at(offset, len, buf, &mut FilePrivateData::Unused);
+            .write_at(offset, len, buf, data);
     }
 
     #[inline]

+ 5 - 6
kernel/src/include/bindings/wrapper.h

@@ -26,22 +26,21 @@
 #include <common/printk.h>
 #include <common/spinlock.h>
 #include <common/stdio.h>
+#include <common/string.h>
 #include <common/time.h>
 #include <common/unistd.h>
-#include <common/string.h>
 #include <driver/disk/ahci/ahci.h>
 #include <driver/disk/ahci/ahci_rust.h>
 #include <driver/pci/pci.h>
+#include <driver/virtio/virtio.h>
 #include <include/DragonOS/refcount.h>
 #include <include/DragonOS/signal.h>
+#include <libs/libUI/textui.h>
+#include <mm/mm-types.h>
 #include <mm/mm.h>
 #include <mm/mmio.h>
 #include <mm/slab.h>
 #include <process/process.h>
 #include <sched/sched.h>
-#include <time/sleep.h>
-#include <mm/mm-types.h>
-#include <driver/pci/pci.h>
-#include <driver/virtio/virtio.h>
 #include <smp/smp.h>
-
+#include <time/sleep.h>

+ 0 - 2
kernel/src/lib.rs

@@ -39,7 +39,6 @@ extern crate alloc;
 extern crate bitflags;
 #[macro_use]
 extern crate lazy_static;
-
 extern crate num;
 #[macro_use]
 extern crate num_derive;
@@ -99,6 +98,5 @@ pub fn panic(info: &PanicInfo) -> ! {
 pub extern "C" fn __rust_demo_func() -> i32 {
     printk_color!(GREEN, BLACK, "__rust_demo_func()\n");
 
-
     return 0;
 }

+ 66 - 33
kernel/src/libs/keyboard_parser.rs

@@ -1,4 +1,6 @@
-use crate::kdebug;
+use alloc::sync::Arc;
+
+use crate::driver::tty::tty_device::TtyDevice;
 
 #[allow(dead_code)]
 pub const NUM_SCAN_CODES: u8 = 0x80;
@@ -26,21 +28,25 @@ pub enum KeyFlag {
 pub struct TypeOneFSM {
     status: ScanCodeStatus,
     current_state: TypeOneFSMState,
+    tty: Arc<TtyDevice>,
 }
 
 impl TypeOneFSM {
     #[allow(dead_code)]
-    pub fn new() -> Self {
+    pub fn new(tty: Arc<TtyDevice>) -> Self {
         Self {
             status: ScanCodeStatus::new(),
             current_state: TypeOneFSMState::Start,
+            tty,
         }
     }
 
     /// @brief 解析扫描码
     #[allow(dead_code)]
     pub fn parse(&mut self, scancode: u8) -> TypeOneFSMState {
-        self.current_state = self.current_state.parse(scancode, &mut self.status);
+        self.current_state = self
+            .current_state
+            .parse(scancode, &mut self.status, &self.tty);
         self.current_state
     }
 }
@@ -63,30 +69,42 @@ pub enum TypeOneFSMState {
 
 impl TypeOneFSMState {
     /// @brief 状态机总控程序
-    fn parse(&self, scancode: u8, scancode_status: &mut ScanCodeStatus) -> TypeOneFSMState {
+    fn parse(
+        &self,
+        scancode: u8,
+        scancode_status: &mut ScanCodeStatus,
+        tty: &Arc<TtyDevice>,
+    ) -> TypeOneFSMState {
         // kdebug!("the code is {:#x}\n", scancode);
         match self {
             TypeOneFSMState::Start => {
-                return self.handle_start(scancode, scancode_status);
+                return self.handle_start(scancode, scancode_status, tty);
             }
             TypeOneFSMState::PauseBreak(n) => {
-                return self.handle_pause_break(*n, scancode_status);
+                return self.handle_pause_break(*n, scancode_status, tty);
             }
             TypeOneFSMState::Func0 => {
-                return self.handle_func0(scancode, scancode_status);
+                return self.handle_func0(scancode, scancode_status, tty);
             }
             TypeOneFSMState::Type3 => {
-                return self.handle_type3(scancode, scancode_status);
+                return self.handle_type3(scancode, scancode_status, tty);
+            }
+            TypeOneFSMState::PrtscPress(n) => {
+                return self.handle_prtsc_press(*n, scancode_status, tty)
             }
-            TypeOneFSMState::PrtscPress(n) => return self.handle_prtsc_press(*n, scancode_status),
             TypeOneFSMState::PrtscRelease(n) => {
-                return self.handle_prtsc_release(*n, scancode_status)
+                return self.handle_prtsc_release(*n, scancode_status, tty)
             }
         }
     }
 
     /// @brief 处理起始状态
-    fn handle_start(&self, scancode: u8, scancode_status: &mut ScanCodeStatus) -> TypeOneFSMState {
+    fn handle_start(
+        &self,
+        scancode: u8,
+        scancode_status: &mut ScanCodeStatus,
+        tty: &Arc<TtyDevice>,
+    ) -> TypeOneFSMState {
         //kdebug!("in handle_start the code is {:#x}\n",scancode);
         match scancode {
             0xe1 => {
@@ -97,7 +115,7 @@ impl TypeOneFSMState {
             }
             _ => {
                 //kdebug!("in _d the code is {:#x}\n",scancode);
-                return TypeOneFSMState::Type3.handle_type3(scancode, scancode_status);
+                return TypeOneFSMState::Type3.handle_type3(scancode, scancode_status, tty);
             }
         }
     }
@@ -107,16 +125,17 @@ impl TypeOneFSMState {
         &self,
         scancode: u8,
         scancode_status: &mut ScanCodeStatus,
+        tty: &Arc<TtyDevice>,
     ) -> TypeOneFSMState {
         static PAUSE_BREAK_SCAN_CODE: [u8; 6] = [0xe1, 0x1d, 0x45, 0xe1, 0x9d, 0xc5];
         let i = match self {
             TypeOneFSMState::PauseBreak(i) => *i,
             _ => {
-                return self.handle_type3(scancode, scancode_status);
+                return self.handle_type3(scancode, scancode_status, tty);
             }
         };
         if scancode != PAUSE_BREAK_SCAN_CODE[i as usize] {
-            return self.handle_type3(scancode, scancode_status);
+            return self.handle_type3(scancode, scancode_status, tty);
         } else {
             if i == 5 {
                 // 所有Pause Break扫描码都被清除
@@ -127,7 +146,12 @@ impl TypeOneFSMState {
         }
     }
 
-    fn handle_func0(&self, scancode: u8, scancode_status: &mut ScanCodeStatus) -> TypeOneFSMState {
+    fn handle_func0(
+        &self,
+        scancode: u8,
+        scancode_status: &mut ScanCodeStatus,
+        tty: &Arc<TtyDevice>,
+    ) -> TypeOneFSMState {
         //0xE0
         match scancode {
             0x2a => {
@@ -190,7 +214,7 @@ impl TypeOneFSMState {
             }
             0x53 => {
                 scancode_status.del = true;
-                Self::emit(127);
+                Self::emit(tty, 127);
             }
             0xd3 => {
                 scancode_status.del = false;
@@ -209,32 +233,32 @@ impl TypeOneFSMState {
             }
             0x48 => {
                 scancode_status.arrow_u = true;
-                Self::emit(224);
-                Self::emit(72);
+                Self::emit(tty, 224);
+                Self::emit(tty, 72);
             }
             0xc8 => {
                 scancode_status.arrow_u = false;
             }
             0x4b => {
                 scancode_status.arrow_l = true;
-                Self::emit(224);
-                Self::emit(75);
+                Self::emit(tty, 224);
+                Self::emit(tty, 75);
             }
             0xcb => {
                 scancode_status.arrow_l = false;
             }
             0x50 => {
                 scancode_status.arrow_d = true;
-                Self::emit(224);
-                Self::emit(80);
+                Self::emit(tty, 224);
+                Self::emit(tty, 80);
             }
             0xd0 => {
                 scancode_status.arrow_d = false;
             }
             0x4d => {
                 scancode_status.arrow_r = true;
-                Self::emit(224);
-                Self::emit(77);
+                Self::emit(tty, 224);
+                Self::emit(tty, 77);
             }
             0xcd => {
                 scancode_status.arrow_r = false;
@@ -245,14 +269,14 @@ impl TypeOneFSMState {
                 scancode_status.kp_forward_slash = true;
 
                 let ch = '/' as u8;
-                Self::emit(ch);
+                Self::emit(tty, ch);
             }
             0xb5 => {
                 scancode_status.kp_forward_slash = false;
             }
             0x1c => {
                 scancode_status.kp_enter = true;
-                Self::emit('\n' as u8);
+                Self::emit(tty, '\n' as u8);
             }
             0x9c => {
                 scancode_status.kp_enter = false;
@@ -264,7 +288,12 @@ impl TypeOneFSMState {
         return TypeOneFSMState::Start;
     }
 
-    fn handle_type3(&self, scancode: u8, scancode_status: &mut ScanCodeStatus) -> TypeOneFSMState {
+    fn handle_type3(
+        &self,
+        scancode: u8,
+        scancode_status: &mut ScanCodeStatus,
+        tty: &Arc<TtyDevice>,
+    ) -> TypeOneFSMState {
         // 判断按键是被按下还是抬起
         let flag_make = if (scancode & (TYPE1_KEYCODE_FLAG_BREAK as u8)) > 0 {
             false
@@ -311,13 +340,15 @@ impl TypeOneFSMState {
         }
 
         if key != KeyFlag::NoneFlag {
-            Self::emit(ch);
+            Self::emit(tty, ch);
         }
         return TypeOneFSMState::Start;
     }
 
-    fn emit(_ch: u8) {
-        // todo: 发送到tty
+    #[inline(always)]
+    fn emit(tty: &Arc<TtyDevice>, ch: u8) {
+        // 发送到tty
+        tty.input(&[ch]).ok();
     }
 
     /// @brief 处理Prtsc按下事件
@@ -325,6 +356,7 @@ impl TypeOneFSMState {
         &self,
         scancode: u8,
         scancode_status: &mut ScanCodeStatus,
+        tty: &Arc<TtyDevice>,
     ) -> TypeOneFSMState {
         static PRTSC_SCAN_CODE: [u8; 4] = [0xe0, 0x2a, 0xe0, 0x37];
         let i = match self {
@@ -336,7 +368,7 @@ impl TypeOneFSMState {
             return TypeOneFSMState::Start;
         }
         if scancode != PRTSC_SCAN_CODE[i as usize] {
-            return self.handle_type3(scancode, scancode_status);
+            return self.handle_type3(scancode, scancode_status, tty);
         } else {
             if i == 3 {
                 // 成功解析出PrtscPress
@@ -352,6 +384,7 @@ impl TypeOneFSMState {
         &self,
         scancode: u8,
         scancode_status: &mut ScanCodeStatus,
+        tty: &Arc<TtyDevice>,
     ) -> TypeOneFSMState {
         static PRTSC_SCAN_CODE: [u8; 4] = [0xe0, 0xb7, 0xe0, 0xaa];
         let i = match self {
@@ -363,7 +396,7 @@ impl TypeOneFSMState {
             return TypeOneFSMState::Start;
         }
         if scancode != PRTSC_SCAN_CODE[i as usize] {
-            return self.handle_type3(scancode, scancode_status);
+            return self.handle_type3(scancode, scancode_status, tty);
         } else {
             if i == 3 {
                 // 成功解析出PrtscRelease
@@ -446,7 +479,7 @@ const TYPE1_KEY_CODE_MAPTABLE: [u8; 256] = [
     /*0x08*/ '7' as u8, '&' as u8, /*0x09*/ '8' as u8, '*' as u8,
     /*0x0a*/ '9' as u8, '(' as u8, /*0x0b*/ '0' as u8, ')' as u8,
     /*0x0c*/ '-' as u8, '_' as u8, /*0x0d*/ '=' as u8, '+' as u8,
-    /*0x0e*/ 0x0e as u8, 0x0e as u8, // BACKSPACE
+    /*0x0e  \b */ 8 as u8, 8 as u8, // BACKSPACE
     /*0x0f*/ '\t' as u8, '\t' as u8, // TAB
     /*0x10*/ 'q' as u8, 'Q' as u8, /*0x11*/ 'w' as u8, 'W' as u8,
     /*0x12*/ 'e' as u8, 'E' as u8, /*0x13*/ 'r' as u8, 'R' as u8,

+ 4 - 1
kernel/src/main.c

@@ -36,6 +36,8 @@
 
 #include <driver/interrupt/apic/apic_timer.h>
 
+extern int rs_tty_init();
+
 ul bsp_idt_size, bsp_gdt_size;
 
 #pragma GCC push_options
@@ -135,7 +137,8 @@ void system_initialize()
     io_mfence();
 
     vfs_init();
-
+    rs_tty_init();
+    
     cpu_init();
     ps2_keyboard_init();
     // tty_init();

+ 5 - 7
kernel/src/process/process.c

@@ -48,6 +48,7 @@ extern void process_exit_signal(struct process_control_block *pcb);
 extern void initial_proc_init_signal(struct process_control_block *pcb);
 extern void rs_process_exit_fpstate(struct process_control_block *pcb);
 extern int process_init_files();
+extern int rs_init_stdio();
 
 // 设置初始进程的PCB
 #define INITIAL_PROC(proc)                                                                                             \
@@ -452,10 +453,6 @@ ul do_execve(struct pt_regs *regs, char *path, char *argv[], char *envp[])
     current_pcb->mm->brk_end = brk_start_addr;
     current_pcb->mm->stack_start = stack_start_addr;
 
-    // 关闭之前的文件描述符
-    process_exit_files(current_pcb);
-    process_init_files();
-
     // 清除进程的vfork标志位
     current_pcb->flags &= ~PF_VFORK;
 
@@ -540,9 +537,10 @@ struct process_control_block *process_init_rt_pcb(struct process_control_block *
 ul initial_kernel_thread(ul arg)
 {
     kinfo("initial proc running...\targ:%#018lx, vruntime=%d", arg, current_pcb->virtual_runtime);
-
-    scm_enable_double_buffer();
-
+    int val = 0;
+    val = scm_enable_double_buffer();
+    
+    rs_init_stdio();
     // block_io_scheduler_init();
     ahci_init();
     mount_root_fs();

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

@@ -7,7 +7,7 @@ use alloc::boxed::Box;
 
 use crate::{
     arch::{asm::current::current_pcb, fpu::FpState},
-    filesystem::vfs::file::{File, FileDescriptorVec},
+    filesystem::vfs::{file::{File, FileDescriptorVec, FileMode}, ROOT_INODE},
     include::bindings::bindings::{
         process_control_block, CLONE_FS, PROC_INTERRUPTIBLE,
         PROC_RUNNING, PROC_STOPPED, PROC_UNINTERRUPTIBLE,
@@ -350,4 +350,37 @@ pub extern "C" fn rs_process_exit_fpstate(pcb: &'static mut process_control_bloc
     }
 }
 
+#[no_mangle]
+pub extern "C" fn rs_init_stdio() -> i32 {
+    let r = init_stdio();
+    if r.is_ok() {
+        return 0;
+    } else {
+        return r.unwrap_err().to_posix_errno();
+    }
+}
 // =========== 以上为导出到C的函数,在将来,进程管理模块被完全重构之后,需要删掉他们 END ============
+
+/// @brief 初始化pid=1的进程的stdio
+pub fn init_stdio() -> Result<(), SystemError> {
+    if current_pcb().pid != 1 {
+        return Err(SystemError::EPERM);
+    }
+    let tty_inode = ROOT_INODE()
+        .lookup("/dev/tty0")
+        .expect("Init stdio: can't find tty0");
+    let stdin =
+        File::new(tty_inode.clone(), FileMode::O_RDONLY).expect("Init stdio: can't create stdin");
+    let stdout =
+        File::new(tty_inode.clone(), FileMode::O_WRONLY).expect("Init stdio: can't create stdout");
+    let stderr = File::new(tty_inode.clone(), FileMode::O_WRONLY | FileMode::O_SYNC)
+        .expect("Init stdio: can't create stderr");
+
+    /*
+        按照规定,进程的文件描述符数组的前三个位置,分别是stdin, stdout, stderr
+     */
+    assert_eq!(current_pcb().alloc_fd(stdin).unwrap(), 0);
+    assert_eq!(current_pcb().alloc_fd(stdout).unwrap(), 1);
+    assert_eq!(current_pcb().alloc_fd(stderr).unwrap(), 2);
+    return Ok(());
+}

+ 1 - 1
kernel/src/syscall/mod.rs

@@ -182,4 +182,4 @@ impl SystemError {
     pub fn to_posix_errno(&self) -> i32 {
         return -<Self as ToPrimitive>::to_i32(self).unwrap();
     }
-}
+}

+ 9 - 0
kernel/src/time/mod.rs

@@ -6,3 +6,12 @@ pub struct TimeSpec {
     pub tv_sec: i64,
     pub tv_nsec: i64,
 }
+
+impl TimeSpec {
+    pub fn new(sec: i64, nsec: i64) -> TimeSpec {
+        return TimeSpec {
+            tv_sec: sec,
+            tv_nsec: nsec,
+        };
+    }
+}

+ 10 - 0
user/apps/shell/cmd.c

@@ -309,6 +309,11 @@ int shell_cmd_cat(int argc, char **argv)
 
     // 打开文件
     int fd = open(file_path, 0);
+    if (fd <= 0)
+    {
+        printf("ERROR: Cannot open file: %s, fd=%d\n", file_path, fd);
+        return -1;
+    }
     // 获取文件总大小
     int file_size = lseek(fd, 0, SEEK_END);
     // 将文件指针切换回文件起始位置
@@ -320,6 +325,11 @@ int shell_cmd_cat(int argc, char **argv)
     {
         memset(buf, 0, 512);
         int l = read(fd, buf, 511);
+        if (l < 0)
+        {
+            printf("ERROR: Cannot read file: %s\n", file_path);
+            return -1;
+        }
         buf[l] = '\0';
 
         file_size -= l;

+ 56 - 37
user/apps/shell/shell.c

@@ -1,6 +1,6 @@
 #include "cmd.h"
-#include <libKeyboard/keyboard.h>
 #include <fcntl.h>
+#include <libKeyboard/keyboard.h>
 #include <printf.h>
 #include <stddef.h>
 #include <stdio.h>
@@ -22,12 +22,12 @@
 int shell_readline(int fd, char *buf);
 void print_ascii_logo();
 extern char *shell_current_path;
-//保存的历史命令(瞬时更改)
+// 保存的历史命令(瞬时更改)
 char history_commands[MEM_HISTORY][INPUT_BUFFER_SIZE];
-//真正的历史命令
+// 真正的历史命令
 char real_history_commands[MEM_HISTORY][INPUT_BUFFER_SIZE];
 int count_history;
-//现在对应的命令
+// 现在对应的命令
 int current_command_index;
 /**
  * @brief shell主循环
@@ -51,12 +51,12 @@ void main_loop(int kb_fd)
     {
         int argc = 0;
         char **argv;
-        
+
         printf("[DragonOS] %s # ", shell_current_path);
-        
+
         memset(input_buffer, 0, INPUT_BUFFER_SIZE);
 
-        //添加初始光标
+        // 添加初始光标
         put_string(" ", COLOR_BLACK, COLOR_WHITE);
 
         // 循环读取每一行到buffer
@@ -90,14 +90,14 @@ void main_loop(int kb_fd)
 int main()
 {
     // 打开键盘文件
-    char kb_file_path[] = "/dev/char/ps2_keyboard";
+    // char kb_file_path[] = "/dev/char/ps2_keyboard";
 
-    int kb_fd = open(kb_file_path, 0);
+    // int kb_fd = open(kb_file_path, 0);
     print_ascii_logo();
     // printf("before mkdir\n");
     // mkdir("/aaac", 0);
     // printf("after mkdir\n");
-    main_loop(kb_fd);
+    main_loop(0);
     while (1)
         ;
 }
@@ -122,22 +122,22 @@ void clear_command(int count, char *buf)
 void change_command(char *buf, int type)
 {
     current_command_index -= type;
-    //处理边界
+    // 处理边界
     if (current_command_index < 0)
         current_command_index++;
     if (current_command_index >= count_history - 1)
     {
-        //初始只含一条空历史记录,需单独考虑
-        if(count_history == 1)
+        // 初始只含一条空历史记录,需单独考虑
+        if (count_history == 1)
         {
-            //防止出现多条空历史记录
-            if(current_command_index > 1)
+            // 防止出现多条空历史记录
+            if (current_command_index > 1)
                 current_command_index = 1;
         }
         else
             current_command_index = count_history - 2;
     }
-        
+
     strcpy(buf, history_commands[current_command_index]);
     printf("%s", buf);
     put_string(" ", COLOR_BLACK, COLOR_WHITE);
@@ -155,29 +155,48 @@ int shell_readline(int fd, char *buf)
     int count = 0;
     while (1)
     {
-        key = keyboard_analyze_keycode(fd);
-        //向上方向键
-        if (count_history != 0 && key == 0xc8)
+        // key = keyboard_analyze_keycode(fd);
+        key = getchar();
+        // printf("key = %d\n", key);
+        if (key == 224)
         {
-            // put_string(" ", COLOR_WHITE, COLOR_BLACK);
-            printf("%c", '\b');
-            clear_command(count, buf);
-            count = 0;
-            //向历史
-            change_command(buf, 1);
-            count = strlen(buf);
-        }
-        //向下方向键
-        if (count_history != 0 && key == 0x50)
-        {
-            // put_string(" ", COLOR_WHITE, COLOR_BLACK);
-            printf("%c", '\b');
-            clear_command(count, buf);
-            count = 0;
-            //向现在
-            change_command(buf, -1);
-            count = strlen(buf);
+            key = getchar();
+            // printf("key = %d\n", key);
+            switch (key)
+            {
+            case 72:
+                // 向上方向键
+                if (count_history != 0)
+                {
+                    // put_string(" ", COLOR_WHITE, COLOR_BLACK);
+                    printf("%c", '\b');
+                    clear_command(count, buf);
+                    count = 0;
+                    // 向历史
+                    change_command(buf, 1);
+                    count = strlen(buf);
+                }
+                key = 0xc8;
+                break;
+            case 80:
+                // 向下方向键
+                if (count_history != 0)
+                {
+                    // put_string(" ", COLOR_WHITE, COLOR_BLACK);
+                    printf("%c", '\b');
+                    clear_command(count, buf);
+                    count = 0;
+                    // 向历史
+                    change_command(buf, -1);
+                    count = strlen(buf);
+                }
+                key = 0x50;
+                break;
+            default:
+                break;
+            }
         }
+
         if (key == '\n')
         {
             if (count > 0 && current_command_index >= count_history)

+ 1 - 1
user/libs/libc/src/include/export/stdio.h

@@ -57,7 +57,7 @@ FILE *fopen(const char *restrict pathname, const char *restrict mode);
 int fclose(FILE *stream);
 int puts(const char *s);
 int putchar(int c);
-
+int getchar(void);
 #if defined(__cplusplus) 
 }  /* extern "C" */ 
 #endif

+ 36 - 34
user/libs/libc/src/printf.c

@@ -1,10 +1,11 @@
 #include <printf.h>
 
+#include <libsystem/syscall.h>
 #include <math.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include <libsystem/syscall.h>
+#include <unistd.h>
 
 static char *write_num(char *str, uint64_t num, int base, int field_width, int precision, int flags);
 static char *write_float_point_num(char *str, double num, int field_width, int precision, int flags);
@@ -46,7 +47,8 @@ int printf(const char *fmt, ...)
 
     count = vsprintf(buf, fmt, args);
     va_end(args);
-    put_string(buf, COLOR_WHITE, COLOR_BLACK);
+    // put_string(buf, COLOR_WHITE, COLOR_BLACK);
+    write(1, buf, count);
     return count;
 }
 
@@ -79,15 +81,15 @@ int vsprintf(char *buf, const char *fmt, va_list args)
     str = buf;
 
     int flags;       // 用来存储格式信息的bitmap
-    int field_width; //区域宽度
-    int precision;   //精度
-    int qualifier;   //数据显示的类型
+    int field_width; // 区域宽度
+    int precision;   // 精度
+    int qualifier;   // 数据显示的类型
     int len;
 
-    //开始解析字符串
+    // 开始解析字符串
     for (; *fmt; ++fmt)
     {
-        //内容不涉及到格式化,直接输出
+        // 内容不涉及到格式化,直接输出
         if (*fmt != '%')
         {
             *str = *fmt;
@@ -95,9 +97,9 @@ int vsprintf(char *buf, const char *fmt, va_list args)
             continue;
         }
 
-        //开始格式化字符串
+        // 开始格式化字符串
 
-        //清空标志位和field宽度
+        // 清空标志位和field宽度
         field_width = flags = 0;
 
         bool flag_tmp = true;
@@ -109,7 +111,7 @@ int vsprintf(char *buf, const char *fmt, va_list args)
             switch (*fmt)
             {
             case '\0':
-                //结束解析
+                // 结束解析
                 flag_break = true;
                 flag_tmp = false;
                 break;
@@ -120,7 +122,7 @@ int vsprintf(char *buf, const char *fmt, va_list args)
                 ++fmt;
                 break;
             case '+':
-                //在正数前面显示加号
+                // 在正数前面显示加号
                 flags |= PLUS;
                 ++fmt;
                 break;
@@ -129,12 +131,12 @@ int vsprintf(char *buf, const char *fmt, va_list args)
                 ++fmt;
                 break;
             case '#':
-                //在八进制数前面显示 '0o',在十六进制数前面显示 '0x' 或 '0X'
+                // 在八进制数前面显示 '0o',在十六进制数前面显示 '0x' 或 '0X'
                 flags |= SPECIAL;
                 ++fmt;
                 break;
             case '0':
-                //显示的数字之前填充‘0’来取代空格
+                // 显示的数字之前填充‘0’来取代空格
                 flags |= PAD_ZERO;
                 ++fmt;
                 break;
@@ -146,7 +148,7 @@ int vsprintf(char *buf, const char *fmt, va_list args)
         if (flag_break)
             break;
 
-        //获取区域宽度
+        // 获取区域宽度
         field_width = -1;
         if (*fmt == '*')
         {
@@ -163,7 +165,7 @@ int vsprintf(char *buf, const char *fmt, va_list args)
             }
         }
 
-        //获取小数精度
+        // 获取小数精度
         precision = -1;
         if (*fmt == '.')
         {
@@ -179,28 +181,28 @@ int vsprintf(char *buf, const char *fmt, va_list args)
             }
         }
 
-        //获取要显示的数据的类型
+        // 获取要显示的数据的类型
         if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' || *fmt == 'Z')
         {
             qualifier = *fmt;
             ++fmt;
         }
-        //为了支持lld
+        // 为了支持lld
         if (qualifier == 'l' && *fmt == 'l', *(fmt + 1) == 'd')
             ++fmt;
 
-        //转化成字符串
+        // 转化成字符串
         long long *ip;
         switch (*fmt)
         {
-        //输出 %
+        // 输出 %
         case '%':
             *str++ = '%';
 
             break;
         // 显示一个字符
         case 'c':
-            //靠右对齐
+            // 靠右对齐
             if (!(flags & LEFT))
             {
                 while (--field_width > 0)
@@ -220,7 +222,7 @@ int vsprintf(char *buf, const char *fmt, va_list args)
 
             break;
 
-        //显示一个字符串
+        // 显示一个字符串
         case 's':
             s = va_arg(args, char *);
             if (!s)
@@ -228,7 +230,7 @@ int vsprintf(char *buf, const char *fmt, va_list args)
             len = strlen(s);
             if (precision < 0)
             {
-                //未指定精度
+                // 未指定精度
                 precision = len;
             }
 
@@ -237,7 +239,7 @@ int vsprintf(char *buf, const char *fmt, va_list args)
                 len = precision;
             }
 
-            //靠右对齐
+            // 靠右对齐
             if (!(flags & LEFT))
                 while (len < field_width--)
                 {
@@ -259,7 +261,7 @@ int vsprintf(char *buf, const char *fmt, va_list args)
             }
 
             break;
-        //以八进制显示字符串
+        // 以八进制显示字符串
         case 'o':
             flags |= SMALL;
         case 'O':
@@ -270,7 +272,7 @@ int vsprintf(char *buf, const char *fmt, va_list args)
                 str = write_num(str, va_arg(args, int), 8, field_width, precision, flags);
             break;
 
-        //打印指针指向的地址
+        // 打印指针指向的地址
         case 'p':
             if (field_width == 0)
             {
@@ -282,7 +284,7 @@ int vsprintf(char *buf, const char *fmt, va_list args)
 
             break;
 
-        //打印十六进制
+        // 打印十六进制
         case 'x':
             flags |= SMALL;
         case 'X':
@@ -293,7 +295,7 @@ int vsprintf(char *buf, const char *fmt, va_list args)
                 str = write_num(str, va_arg(args, int), 16, field_width, precision, flags);
             break;
 
-        //打印十进制有符号整数
+        // 打印十进制有符号整数
         case 'i':
         case 'd':
 
@@ -304,7 +306,7 @@ int vsprintf(char *buf, const char *fmt, va_list args)
                 str = write_num(str, va_arg(args, int), 10, field_width, precision, flags);
             break;
 
-        //打印十进制无符号整数
+        // 打印十进制无符号整数
         case 'u':
             if (qualifier == 'l')
                 str = write_num(str, va_arg(args, unsigned long long), 10, field_width, precision, flags);
@@ -312,7 +314,7 @@ int vsprintf(char *buf, const char *fmt, va_list args)
                 str = write_num(str, va_arg(args, unsigned int), 10, field_width, precision, flags);
             break;
 
-        //输出有效字符数量到*ip对应的变量
+        // 输出有效字符数量到*ip对应的变量
         case 'n':
 
             if (qualifier == 'l')
@@ -331,7 +333,7 @@ int vsprintf(char *buf, const char *fmt, va_list args)
 
             break;
 
-        //对于不识别的控制符,直接输出
+        // 对于不识别的控制符,直接输出
         default:
             *str++ = '%';
             if (*fmt)
@@ -343,7 +345,7 @@ int vsprintf(char *buf, const char *fmt, va_list args)
     }
     *str = '\0';
 
-    //返回缓冲区已有字符串的长度。
+    // 返回缓冲区已有字符串的长度。
     return str - buf;
 }
 
@@ -411,7 +413,7 @@ static char *write_num(char *str, uint64_t num, int base, int field_width, int p
     else
     {
         num = llabs(num);
-        //进制转换
+        // 进制转换
         while (num > 0)
         {
             tmp_num[js_num++] = digits[num % base]; // 注意这里,输出的数字,是小端对齐的。低位存低位
@@ -438,7 +440,7 @@ static char *write_num(char *str, uint64_t num, int base, int field_width, int p
             *str++ = digits[33];
         }
         else if (base == 8)
-            *str++ = digits[24]; //注意这里是英文字母O或者o
+            *str++ = digits[24]; // 注意这里是英文字母O或者o
     if (!(flags & LEFT))
         while (field_width-- > 0)
             *str++ = pad;
@@ -502,7 +504,7 @@ static char *write_float_point_num(char *str, double num, int field_width, int p
         tmp_num_z[js_num_z++] = '0';
     else
     {
-        //存储整数部分
+        // 存储整数部分
         while (num_z > 0)
         {
             tmp_num_z[js_num_z++] = digits[num_z % 10]; // 注意这里,输出的数字,是小端对齐的。低位存低位

+ 14 - 7
user/libs/libc/src/stdio.c

@@ -25,6 +25,13 @@ int fprintf(FILE *restrict stream, const char *restrict format, ...)
     free(buf);
 }
 
+int getchar(void)
+{
+    unsigned int c;
+    read(0, &c, 1);
+    return c;
+}
+
 int puts(const char *s)
 {
     return put_string(s, COLOR_WHITE, COLOR_BLACK);
@@ -47,17 +54,17 @@ int ferror(FILE *stream)
 
 int fclose(FILE *stream)
 {
+    int retval = close(stream->fd);
+    if (retval)
+        return retval;
     if (stream->fd >= 3)
-    {
-        int retcval = close(stream->fd);
         free(stream);
-        return 0;
-    }
-    else
-        return 0;
+
+    return 0;
 }
 
-// FIXME: 请注意,这个函数的实现,没有遵照posix,行为也与Linux的不一致,请在将来用Rust重构时改变它,以使得它的行为与Linux的一致。
+// FIXME:
+// 请注意,这个函数的实现,没有遵照posix,行为也与Linux的不一致,请在将来用Rust重构时改变它,以使得它的行为与Linux的一致。
 FILE *fopen(const char *restrict pathname, const char *restrict mode)
 {
     FILE *stream = malloc(sizeof(FILE));