mirror of
https://github.com/DragonOS-Community/DragonOS.git
synced 2025-06-18 16:26:31 +00:00
@ -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);
|
||||
|
||||
|
@ -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,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);
|
||||
}
|
||||
|
@ -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(());
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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]
|
||||
|
@ -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>
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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();
|
||||
|
@ -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();
|
||||
|
@ -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(());
|
||||
}
|
||||
|
@ -182,4 +182,4 @@ impl SystemError {
|
||||
pub fn to_posix_errno(&self) -> i32 {
|
||||
return -<Self as ToPrimitive>::to_i32(self).unwrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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,
|
||||
};
|
||||
}
|
||||
}
|
@ -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;
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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]; // 注意这里,输出的数字,是小端对齐的。低位存低位
|
||||
|
@ -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));
|
||||
|
Reference in New Issue
Block a user