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

* 将stdio与tty接上
This commit is contained in:
login
2023-03-31 12:54:37 +08:00
committed by GitHub
parent 5fb12ce447
commit 20e3152e1e
21 changed files with 528 additions and 169 deletions

View File

@ -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);

View File

@ -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)]

View File

@ -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);
}

View File

@ -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(());
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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,
}
}
}

View File

@ -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]

View File

@ -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>

View File

@ -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;
}

View File

@ -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,

View File

@ -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();

View File

@ -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();

View File

@ -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(());
}

View File

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

View File

@ -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,
};
}
}

View File

@ -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;

View File

@ -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)

View File

@ -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

View File

@ -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]; // 注意这里,输出的数字,是小端对齐的。低位存低位

View File

@ -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));