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

This commit is contained in:
login 2023-03-16 19:48:59 +08:00 committed by GitHub
parent 790d457640
commit 0d48c3c9c2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
22 changed files with 572 additions and 129 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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