mirror of
https://github.com/DragonOS-Community/DragonOS.git
synced 2025-06-09 15:26:47 +00:00
new: tty设备(尚未与stdio接上) (#202)
This commit is contained in:
parent
790d457640
commit
0d48c3c9c2
@ -13,7 +13,8 @@ crate-type = ["staticlib"]
|
|||||||
x86_64 = "0.14.10"
|
x86_64 = "0.14.10"
|
||||||
bitflags = "1.3.2"
|
bitflags = "1.3.2"
|
||||||
virtio-drivers = "0.2.0"
|
virtio-drivers = "0.2.0"
|
||||||
|
# 一个无锁MPSC队列
|
||||||
|
thingbuf = { version = "0.1.3", default-features = false, features = ["alloc"] }
|
||||||
|
|
||||||
# 构建时依赖项
|
# 构建时依赖项
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
|
|
||||||
CFLAGS += -I .
|
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:
|
||||||
@echo "$@"
|
@echo "$@"
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
use crate::filesystem::devfs::{DevFS, DeviceINode};
|
use crate::filesystem::devfs::{DevFS, DeviceINode};
|
||||||
|
use crate::filesystem::vfs::file::FileMode;
|
||||||
use crate::filesystem::vfs::{
|
use crate::filesystem::vfs::{
|
||||||
core::generate_inode_id, make_rawdev, FilePrivateData, FileSystem, FileType, IndexNode,
|
core::generate_inode_id, make_rawdev, FilePrivateData, FileSystem, FileType, IndexNode,
|
||||||
Metadata, PollStatus,
|
Metadata, PollStatus,
|
||||||
@ -77,7 +78,7 @@ impl IndexNode for LockedAhciInode {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
fn open(&self, _data: &mut FilePrivateData) -> Result<(), i32> {
|
fn open(&self, _data: &mut FilePrivateData, _mode: &FileMode) -> Result<(), i32> {
|
||||||
Err(-(ENOTSUP as i32))
|
Err(-(ENOTSUP as i32))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@ use alloc::sync::{Arc, Weak};
|
|||||||
use crate::{
|
use crate::{
|
||||||
filesystem::{
|
filesystem::{
|
||||||
devfs::{devfs_register, DevFS, DeviceINode},
|
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},
|
include::bindings::bindings::{vfs_file_operations_t, vfs_file_t, vfs_index_node_t, ENOTSUP},
|
||||||
kdebug,
|
kdebug,
|
||||||
@ -68,10 +68,8 @@ impl DeviceINode for LockedPS2KeyBoardInode {
|
|||||||
|
|
||||||
#[no_mangle] // 不重命名
|
#[no_mangle] // 不重命名
|
||||||
pub extern "C" fn ps2_keyboard_register(f_ops: &vfs_file_operations_t) {
|
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))
|
devfs_register("ps2_keyboard", LockedPS2KeyBoardInode::new(f_ops))
|
||||||
.expect("Failed to register ps/2 keyboard");
|
.expect("Failed to register ps/2 keyboard");
|
||||||
kdebug!("register keyboard = {:p}", f_ops);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl IndexNode for LockedPS2KeyBoardInode {
|
impl IndexNode for LockedPS2KeyBoardInode {
|
||||||
@ -105,7 +103,11 @@ impl IndexNode for LockedPS2KeyBoardInode {
|
|||||||
return Err(-(ENOTSUP as i32));
|
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 guard = self.0.lock();
|
||||||
let func = guard.f_ops.open.unwrap();
|
let func = guard.f_ops.open.unwrap();
|
||||||
let _ = unsafe { func(0 as *mut vfs_index_node_t, 0 as *mut vfs_file_t) };
|
let _ = unsafe { func(0 as *mut vfs_index_node_t, 0 as *mut vfs_file_t) };
|
||||||
|
@ -2,5 +2,6 @@ pub mod disk;
|
|||||||
pub mod keyboard;
|
pub mod keyboard;
|
||||||
pub mod pci;
|
pub mod pci;
|
||||||
pub mod timers;
|
pub mod timers;
|
||||||
|
pub mod tty;
|
||||||
pub mod uart;
|
pub mod uart;
|
||||||
pub mod virtio;
|
pub mod virtio;
|
||||||
|
@ -1,8 +0,0 @@
|
|||||||
|
|
||||||
all: tty.o
|
|
||||||
|
|
||||||
CFLAGS += -I .
|
|
||||||
|
|
||||||
|
|
||||||
tty.o: tty.c
|
|
||||||
$(CC) $(CFLAGS) -c tty.c -o tty.o
|
|
384
kernel/src/driver/tty/mod.rs
Normal file
384
kernel/src/driver/tty/mod.rs
Normal 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;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
@ -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);
|
|
||||||
// }
|
|
@ -1,3 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
void tty_init();
|
|
135
kernel/src/driver/tty/tty_device.rs
Normal file
135
kernel/src/driver/tty/tty_device.rs
Normal 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));
|
||||||
|
}
|
||||||
|
}
|
@ -4,7 +4,7 @@ pub mod zero_dev;
|
|||||||
|
|
||||||
use super::vfs::{
|
use super::vfs::{
|
||||||
core::{generate_inode_id, ROOT_INODE},
|
core::{generate_inode_id, ROOT_INODE},
|
||||||
FileSystem, FileType, FsInfo, IndexNode, Metadata, PollStatus,
|
FileSystem, FileType, FsInfo, IndexNode, Metadata, PollStatus, file::FileMode,
|
||||||
};
|
};
|
||||||
use crate::{
|
use crate::{
|
||||||
include::bindings::bindings::{EEXIST, EISDIR, ENOENT, ENOTDIR, ENOTSUP},
|
include::bindings::bindings::{EEXIST, EISDIR, ENOENT, ENOTDIR, ENOTSUP},
|
||||||
@ -322,7 +322,7 @@ impl IndexNode for LockedDevFSInode {
|
|||||||
self
|
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(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
use crate::filesystem::vfs::file::FileMode;
|
||||||
use crate::filesystem::vfs::make_rawdev;
|
use crate::filesystem::vfs::make_rawdev;
|
||||||
use crate::filesystem::vfs::{
|
use crate::filesystem::vfs::{
|
||||||
core::generate_inode_id, FilePrivateData, FileSystem, FileType, IndexNode, Metadata, PollStatus,
|
core::generate_inode_id, FilePrivateData, FileSystem, FileType, IndexNode, Metadata, PollStatus,
|
||||||
@ -72,7 +73,7 @@ impl IndexNode for LockedNullInode {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
fn open(&self, _data: &mut FilePrivateData) -> Result<(), i32> {
|
fn open(&self, _data: &mut FilePrivateData, _mode: &FileMode) -> Result<(), i32> {
|
||||||
Err(-(ENOTSUP as i32))
|
Err(-(ENOTSUP as i32))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
use crate::filesystem::vfs::file::FileMode;
|
||||||
use crate::filesystem::vfs::make_rawdev;
|
use crate::filesystem::vfs::make_rawdev;
|
||||||
use crate::filesystem::vfs::{
|
use crate::filesystem::vfs::{
|
||||||
core::generate_inode_id, FilePrivateData, FileSystem, FileType, IndexNode, Metadata, PollStatus,
|
core::generate_inode_id, FilePrivateData, FileSystem, FileType, IndexNode, Metadata, PollStatus,
|
||||||
@ -72,7 +73,7 @@ impl IndexNode for LockedZeroInode {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
fn open(&self, _data: &mut FilePrivateData) -> Result<(), i32> {
|
fn open(&self, _data: &mut FilePrivateData, _mode: &FileMode) -> Result<(), i32> {
|
||||||
Err(-(ENOTSUP as i32))
|
Err(-(ENOTSUP as i32))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@ use alloc::{
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
filesystem::vfs::{
|
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,
|
Metadata, PollStatus,
|
||||||
},
|
},
|
||||||
include::bindings::bindings::{
|
include::bindings::bindings::{
|
||||||
@ -1506,7 +1506,7 @@ impl IndexNode for LockedFATInode {
|
|||||||
return Ok(target);
|
return Ok(target);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn open(&self, _data: &mut FilePrivateData) -> Result<(), i32> {
|
fn open(&self, _data: &mut FilePrivateData, _mode: &FileMode) -> Result<(), i32> {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,7 +24,7 @@ use crate::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
use super::vfs::{
|
use super::vfs::{
|
||||||
file::FilePrivateData, FileSystem, FsInfo, IndexNode, InodeId, Metadata, PollStatus,
|
file::{FilePrivateData, FileMode}, FileSystem, FsInfo, IndexNode, InodeId, Metadata, PollStatus,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// @brief 进程文件类型
|
/// @brief 进程文件类型
|
||||||
@ -319,7 +319,7 @@ impl ProcFS {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl IndexNode for LockedProcFSInode {
|
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();
|
let mut inode: SpinLockGuard<ProcFSInode> = self.0.lock();
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@ use crate::{
|
|||||||
process_control_block, EINVAL, ENOBUFS, EOVERFLOW, EPERM, ESPIPE,
|
process_control_block, EINVAL, ENOBUFS, EOVERFLOW, EPERM, ESPIPE,
|
||||||
},
|
},
|
||||||
io::SeekFrom,
|
io::SeekFrom,
|
||||||
kerror,
|
kerror, driver::tty::TtyFilePrivateData,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{Dirent, FileType, IndexNode, Metadata};
|
use super::{Dirent, FileType, IndexNode, Metadata};
|
||||||
@ -17,9 +17,11 @@ use super::{Dirent, FileType, IndexNode, Metadata};
|
|||||||
/// 文件私有信息的枚举类型
|
/// 文件私有信息的枚举类型
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum FilePrivateData {
|
pub enum FilePrivateData {
|
||||||
// procfs文件私有信息
|
/// procfs文件私有信息
|
||||||
Procfs(ProcfsFilePrivateData),
|
Procfs(ProcfsFilePrivateData),
|
||||||
// 不需要文件私有信息
|
/// Tty设备的私有信息
|
||||||
|
Tty(TtyFilePrivateData),
|
||||||
|
/// 不需要文件私有信息
|
||||||
Unused,
|
Unused,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -107,7 +109,7 @@ impl File {
|
|||||||
private_data: FilePrivateData::default(),
|
private_data: FilePrivateData::default(),
|
||||||
};
|
};
|
||||||
// kdebug!("inode:{:?}",f.inode);
|
// kdebug!("inode:{:?}",f.inode);
|
||||||
f.inode.open(&mut f.private_data)?;
|
f.inode.open(&mut f.private_data, &mode)?;
|
||||||
return Ok(f);
|
return Ok(f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,6 +15,7 @@ use crate::{
|
|||||||
time::TimeSpec,
|
time::TimeSpec,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use self::file::FileMode;
|
||||||
pub use self::{core::ROOT_INODE, file::FilePrivateData, mount::MountFS};
|
pub use self::{core::ROOT_INODE, file::FilePrivateData, mount::MountFS};
|
||||||
|
|
||||||
/// vfs容许的最大的路径名称长度
|
/// vfs容许的最大的路径名称长度
|
||||||
@ -91,7 +92,7 @@ pub trait IndexNode: Any + Sync + Send + Debug {
|
|||||||
///
|
///
|
||||||
/// @return 成功:Ok()
|
/// @return 成功:Ok()
|
||||||
/// 失败:Err(错误码)
|
/// 失败:Err(错误码)
|
||||||
fn open(&self, _data: &mut FilePrivateData) -> Result<(), i32> {
|
fn open(&self, _data: &mut FilePrivateData, _mode: &FileMode) -> Result<(), i32> {
|
||||||
// 若文件系统没有实现此方法,则返回“不支持”
|
// 若文件系统没有实现此方法,则返回“不支持”
|
||||||
return Err(-(ENOTSUP as i32));
|
return Err(-(ENOTSUP as i32));
|
||||||
}
|
}
|
||||||
|
@ -10,7 +10,7 @@ use crate::{
|
|||||||
libs::spinlock::SpinLock,
|
libs::spinlock::SpinLock,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{FilePrivateData, FileSystem, FileType, IndexNode, InodeId};
|
use super::{FilePrivateData, FileSystem, FileType, IndexNode, InodeId, file::FileMode};
|
||||||
|
|
||||||
/// @brief 挂载文件系统
|
/// @brief 挂载文件系统
|
||||||
/// 挂载文件系统的时候,套了MountFS这一层,以实现文件系统的递归挂载
|
/// 挂载文件系统的时候,套了MountFS这一层,以实现文件系统的递归挂载
|
||||||
@ -126,8 +126,8 @@ impl MountFSInode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl IndexNode for MountFSInode {
|
impl IndexNode for MountFSInode {
|
||||||
fn open(&self, data: &mut FilePrivateData) -> Result<(), i32> {
|
fn open(&self, data: &mut FilePrivateData, mode: &FileMode) -> Result<(), i32> {
|
||||||
return self.inner_inode.open(data);
|
return self.inner_inode.open(data, mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn close(&self, data: &mut FilePrivateData) -> Result<(), i32> {
|
fn close(&self, data: &mut FilePrivateData) -> Result<(), i32> {
|
||||||
|
@ -45,6 +45,7 @@ pub trait Device: Any + Send + Sync + Debug {
|
|||||||
fn sync(&self) -> Result<(), i32>;
|
fn sync(&self) -> Result<(), i32>;
|
||||||
|
|
||||||
// TODO: 待实现 open, close
|
// TODO: 待实现 open, close
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief 块设备应该实现的操作
|
/// @brief 块设备应该实现的操作
|
||||||
|
@ -38,7 +38,7 @@ extern crate lazy_static;
|
|||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate bitflags;
|
extern crate bitflags;
|
||||||
|
extern crate thingbuf;
|
||||||
|
|
||||||
use mm::allocator::KernelAllocator;
|
use mm::allocator::KernelAllocator;
|
||||||
|
|
||||||
|
@ -28,7 +28,6 @@
|
|||||||
#include "driver/mouse/ps2_mouse.h"
|
#include "driver/mouse/ps2_mouse.h"
|
||||||
#include "driver/multiboot2/multiboot2.h"
|
#include "driver/multiboot2/multiboot2.h"
|
||||||
#include "driver/pci/pci.h"
|
#include "driver/pci/pci.h"
|
||||||
#include "driver/tty/tty.h"
|
|
||||||
#include <driver/timers/HPET/HPET.h>
|
#include <driver/timers/HPET/HPET.h>
|
||||||
#include <driver/uart/uart.h>
|
#include <driver/uart/uart.h>
|
||||||
#include <driver/usb/usb.h>
|
#include <driver/usb/usb.h>
|
||||||
|
@ -9,7 +9,8 @@ use crate::{
|
|||||||
arch::asm::current::current_pcb,
|
arch::asm::current::current_pcb,
|
||||||
filesystem::vfs::file::{File, FileDescriptorVec},
|
filesystem::vfs::file::{File, FileDescriptorVec},
|
||||||
include::bindings::bindings::{
|
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},
|
sched::core::{cpu_executing, sched_enqueue},
|
||||||
smp::core::{smp_get_processor_id, smp_send_reschedule},
|
smp::core::{smp_get_processor_id, smp_send_reschedule},
|
||||||
@ -253,6 +254,22 @@ impl process_control_block {
|
|||||||
|
|
||||||
return Ok(());
|
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 ============
|
// =========== 导出到C的函数,在将来,进程管理模块被完全重构之后,需要删掉他们 BEGIN ============
|
||||||
|
Loading…
x
Reference in New Issue
Block a user