1 use alloc::string::String; 2 3 use thingbuf::mpsc::{ 4 self, 5 errors::{TryRecvError, TrySendError}, 6 }; 7 8 use crate::libs::rwlock::RwLock; 9 10 pub mod tty_device; 11 12 bitflags! { 13 pub struct TtyCoreState: u32{ 14 /// 在读取stdin缓冲区时,由于队列为空,有读者被阻塞 15 const BLOCK_AT_STDIN_READ = (1 << 0); 16 /// 开启输入回显。 17 const ECHO_ON = (1 << 1); 18 } 19 20 #[derive(Default)] 21 pub struct TtyFileFlag:u32{ 22 /// 当前文件是stdin文件 23 const STDIN = (1 << 0); 24 /// 当前文件是stdout文件 25 const STDOUT = (1 << 1); 26 /// 当前文件是stderr文件 27 const STDERR = (1 << 2); 28 } 29 } 30 31 /// @brief tty文件的私有信息 32 #[derive(Debug, Default, Clone)] 33 pub struct TtyFilePrivateData { 34 flags: TtyFileFlag, 35 } 36 37 /// @brief tty设备的核心功能结构体。在此结构体的基础上,衍生出TTY/PTY/PTS等 38 /// 39 /// 每个TTY Core有5个端口: 40 /// - stdin:连接到一个活动进程的stdin文件描述符 41 /// - stdout:连接到多个进程的stdout文件描述符 42 /// - stderr:连接到多个进程的stdout文件描述符 43 /// - 输入端口:向tty设备输入数据的接口。输入到该接口的数据,将被导向stdin接口。 44 /// 如果开启了回显,那么,数据也将同时被导向输出端 45 /// - 输出端口:tty设备对外输出数据的端口。从stdout、stderr输入的数据,将会被导向此端口。 46 /// 此端口可以连接到屏幕、文件、或者是另一个tty core的输入端口。如果开启了 47 /// 输入数据回显,那么,输入端口的数据,将会被同时导向此端口,以及stdin端口 48 #[derive(Debug)] 49 struct TtyCore { 50 /// stdin的mpsc队列输入输出端 51 stdin_rx: mpsc::Receiver<u8>, 52 stdin_tx: mpsc::Sender<u8>, 53 /// 输出的mpsc队列输入输出端 54 output_rx: mpsc::Receiver<u8>, 55 output_tx: mpsc::Sender<u8>, 56 57 /// tty核心的状态 58 state: RwLock<TtyCoreState>, 59 } 60 61 #[derive(Debug)] 62 #[allow(dead_code)] 63 pub enum TtyError { 64 /// 缓冲区满,返回成功传送的字节数 65 BufferFull(usize), 66 /// 缓冲区空,返回成功传送的字节数 67 BufferEmpty(usize), 68 /// 设备已经被关闭 69 Closed, 70 /// End of file(已经读取的字符数,包含eof) 71 EOF(usize), 72 Unknown(String), 73 } 74 75 impl TtyCore { 76 // 各个缓冲区的大小 77 pub const STDIN_BUF_SIZE: usize = 4096; 78 pub const OUTPUT_BUF_SIZE: usize = 4096; 79 80 /// @brief 创建一个TTY核心组件 new() -> TtyCore81 pub fn new() -> TtyCore { 82 let (stdin_tx, stdin_rx) = mpsc::channel::<u8>(Self::STDIN_BUF_SIZE); 83 let (output_tx, output_rx) = mpsc::channel::<u8>(Self::OUTPUT_BUF_SIZE); 84 let state: RwLock<TtyCoreState> = RwLock::new(TtyCoreState { bits: 0 }); 85 86 return TtyCore { 87 stdin_rx, 88 stdin_tx, 89 output_rx, 90 output_tx, 91 state, 92 }; 93 } 94 95 /// @brief 向tty的输入端口输入数据 96 /// 97 /// @param buf 输入数据 98 /// 99 /// @param block 是否允许阻塞 100 /// 101 /// @return Ok(成功传送的字节数) 102 /// @return Err(TtyError) 内部错误信息 input(&self, buf: &[u8], block: bool) -> Result<usize, TtyError>103 pub fn input(&self, buf: &[u8], block: bool) -> Result<usize, TtyError> { 104 // TODO: 在这里考虑增加对信号发送的处理 105 let val = self.write_stdin(buf, block)?; 106 // 如果开启了输入回显,那么就写一份到输出缓冲区 107 if self.echo_enabled() { 108 self.write_output(&buf[0..val], true)?; 109 } 110 return Ok(val); 111 } 112 113 /// @brief 从tty的输出端口读出数据 114 /// 115 /// @param buf 输出缓冲区 116 /// 117 /// @return Ok(成功传送的字节数) 118 /// @return Err(TtyError) 内部错误信息 119 #[inline] output(&self, buf: &mut [u8], block: bool) -> Result<usize, TtyError>120 pub fn output(&self, buf: &mut [u8], block: bool) -> Result<usize, TtyError> { 121 return self.read_output(buf, block); 122 } 123 124 /// @brief tty的stdout接口 125 /// 126 /// @param buf 输入缓冲区 127 /// 128 /// @return Ok(成功传送的字节数) 129 /// @return Err(TtyError) 内部错误信息 130 #[inline] stdout(&self, buf: &[u8], block: bool) -> Result<usize, TtyError>131 pub fn stdout(&self, buf: &[u8], block: bool) -> Result<usize, TtyError> { 132 return self.write_output(buf, block); 133 } 134 135 /// @brief tty的stderr接口 136 /// 137 /// @param buf 输入缓冲区 138 /// 139 /// @return Ok(成功传送的字节数) 140 /// @return Err(TtyError) 内部错误信息 141 #[inline] stderr(&self, buf: &[u8], block: bool) -> Result<usize, TtyError>142 pub fn stderr(&self, buf: &[u8], block: bool) -> Result<usize, TtyError> { 143 return self.write_output(buf, block); 144 } 145 146 /// @brief 读取TTY的stdin缓冲区 147 /// 148 /// @param buf 读取到的位置 149 /// @param block 是否阻塞读 150 /// 151 /// @return Ok(成功读取的字节数) 152 /// @return Err(TtyError) 内部错误信息 read_stdin(&self, buf: &mut [u8], block: bool) -> Result<usize, TtyError>153 pub fn read_stdin(&self, buf: &mut [u8], block: bool) -> Result<usize, TtyError> { 154 // TODO: 增加对EOF的处理 155 let mut cnt = 0; 156 while cnt < buf.len() { 157 let val: Result<mpsc::RecvRef<u8>, TryRecvError> = self.stdin_rx.try_recv_ref(); 158 if let Err(err) = val { 159 match err { 160 TryRecvError::Closed => return Err(TtyError::Closed), 161 TryRecvError::Empty => { 162 if block { 163 continue; 164 } else { 165 return Ok(cnt); 166 } 167 } 168 _ => return Err(TtyError::Unknown(format!("{err:?}"))), 169 } 170 } else { 171 buf[cnt] = *val.unwrap(); 172 cnt += 1; 173 } 174 } 175 return Ok(cnt); 176 } 177 178 /// @brief 向stdin缓冲区内写入数据 179 /// 180 /// @param buf 输入缓冲区 181 /// 182 /// @param block 当缓冲区满的时候,是否阻塞 183 /// 184 /// @return Ok(成功传送的字节数) 185 /// @return Err(BufferFull(成功传送的字节数)) 缓冲区满,成功传送的字节数 186 /// @return Err(TtyError) 内部错误信息 write_stdin(&self, buf: &[u8], block: bool) -> Result<usize, TtyError>187 fn write_stdin(&self, buf: &[u8], block: bool) -> Result<usize, TtyError> { 188 let mut cnt = 0; 189 while cnt < buf.len() { 190 let r: Result<mpsc::SendRef<u8>, TrySendError> = self.stdin_tx.try_send_ref(); 191 if let Err(e) = r { 192 match e { 193 TrySendError::Closed(_) => return Err(TtyError::Closed), 194 TrySendError::Full(_) => { 195 if block { 196 continue; 197 } else { 198 return Err(TtyError::BufferFull(cnt)); 199 } 200 } 201 _ => return Err(TtyError::Unknown(format!("{e:?}"))), 202 } 203 } else { 204 *r.unwrap() = buf[cnt]; 205 cnt += 1; 206 } 207 } 208 209 return Ok(cnt); 210 } 211 212 /// @brief 读取TTY的output缓冲区 213 /// 214 /// @param buf 读取到的位置 215 /// @param block 是否阻塞读 216 /// 217 /// @return Ok(成功读取的字节数) 218 /// @return Err(TtyError) 内部错误信息 read_output(&self, buf: &mut [u8], block: bool) -> Result<usize, TtyError>219 fn read_output(&self, buf: &mut [u8], block: bool) -> Result<usize, TtyError> { 220 let mut cnt = 0; 221 while cnt < buf.len() { 222 let val: Result<mpsc::RecvRef<u8>, TryRecvError> = self.output_rx.try_recv_ref(); 223 if let Err(err) = val { 224 match err { 225 TryRecvError::Closed => return Err(TtyError::Closed), 226 TryRecvError::Empty => { 227 if block { 228 continue; 229 } else { 230 return Ok(cnt); 231 } 232 } 233 _ => return Err(TtyError::Unknown(format!("{err:?}"))), 234 } 235 } else { 236 buf[cnt] = *val.unwrap(); 237 cnt += 1; 238 } 239 } 240 return Ok(cnt); 241 } 242 243 /// @brief 向output缓冲区内写入数据 244 /// 245 /// @param buf 输入缓冲区 246 /// 247 /// @param block 当缓冲区满的时候,是否阻塞 248 /// 249 /// @return Ok(成功传送的字节数) 250 /// @return Err(BufferFull(成功传送的字节数)) 缓冲区满,成功传送的字节数 251 /// @return Err(TtyError) 内部错误信息 write_output(&self, buf: &[u8], block: bool) -> Result<usize, TtyError>252 fn write_output(&self, buf: &[u8], block: bool) -> Result<usize, TtyError> { 253 let mut cnt = 0; 254 while cnt < buf.len() { 255 let r: Result<mpsc::SendRef<u8>, TrySendError> = self.output_tx.try_send_ref(); 256 if let Err(e) = r { 257 match e { 258 TrySendError::Closed(_) => return Err(TtyError::Closed), 259 TrySendError::Full(_) => { 260 if block { 261 continue; 262 } else { 263 return Err(TtyError::BufferFull(cnt)); 264 } 265 } 266 _ => return Err(TtyError::Unknown(format!("{e:?}"))), 267 } 268 } else { 269 *r.unwrap() = buf[cnt]; 270 cnt += 1; 271 } 272 } 273 274 return Ok(cnt); 275 } 276 277 /// @brief 开启tty输入回显(也就是将输入数据传送一份到输出缓冲区) 278 #[inline] enable_echo(&self)279 pub fn enable_echo(&self) { 280 self.state.write().set(TtyCoreState::ECHO_ON, true); 281 } 282 283 /// @brief 关闭输入回显 284 #[inline] 285 #[allow(dead_code)] disable_echo(&self)286 pub fn disable_echo(&self) { 287 self.state.write().set(TtyCoreState::ECHO_ON, false); 288 } 289 290 /// @brief 判断当前tty核心,是否开启了输入回显 291 /// 292 /// @return true 开启了输入回显 293 /// 294 /// @return false 未开启输入回显 295 #[inline] 296 #[allow(dead_code)] echo_enabled(&self) -> bool297 pub fn echo_enabled(&self) -> bool { 298 return self.state.read().contains(TtyCoreState::ECHO_ON); 299 } 300 } 301 302 // ======= 以下代码考虑了“缓冲区满,然后睡眠,当缓冲区有空位就唤醒”的逻辑。 303 // 但是由于在开发过程中的调整,并且由于数据结构发生变化,因此暂时不实现上述优化,因此先注释。 304 // 305 // @brief 读取TTY的stdin缓冲区 306 // 307 // @param buf 读取到的位置 308 // @param block 是否阻塞读 309 // 310 // @return Ok(成功读取的字节数) 311 // @return Err(TtyError) 内部错误信息 312 // pub fn read_stdin(&mut self, buf: &mut [u8], block: bool) -> Result<usize, TtyError> { 313 // let mut cnt = 0; 314 // loop{ 315 // if cnt == buf.len(){ 316 // break; 317 // } 318 // let val:Option<u8> = self.stdin_queue.dequeue(); 319 // // 如果没读到 320 // if val.is_none() { 321 // // 如果阻塞读 322 // if block { 323 // let state_guard: RwLockUpgradableGuard<TtyCoreState> = 324 // self.state.upgradeable_read(); 325 // // 判断是否有进程正在stdin上睡眠,如果有,则忙等读 326 // // 理论上,这种情况应该不存在,因为stdin是单读者的 327 // if state_guard.contains(TtyCoreState::BLOCK_AT_STDIN_READ) { 328 // 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); 329 // drop(state_guard); 330 // Self::ringbuf_spin_dequeue(&mut buf[cnt], &mut self.stdin_queue); 331 // cnt += 1; 332 // } else { 333 // // 正常情况,阻塞读,将当前进程休眠 334 // let mut state_guard: RwLockWriteGuard<TtyCoreState> = state_guard.upgrade(); 335 // let mut stdin_waiter_guard: RwLockWriteGuard< 336 // Option<&mut process_control_block>, 337 // > = self.stdin_waiter.write(); 338 339 // // 由于输入数据到stdin的时候,必须先获得state guard的读锁。而这里我们已经获取了state的写锁。 340 // // 因此可以保证,此时没有新的数据会进入stdin_queue. 因此再次尝试读取stdin_queue 341 // let val:Option<u8> = self.stdin_queue.dequeue(); 342 // // 读到数据,不用睡眠 343 // if val.is_some(){ 344 // buf[cnt] = val.unwrap(); 345 // cnt += 1; 346 // continue; 347 // } 348 // // 没读到数据,准备睡眠 349 350 // // 设置等待标志位 351 // state_guard.set(TtyCoreState::BLOCK_AT_STDIN_READ, true); 352 353 // // 将当前进程标记为被其他机制管理 354 // unsafe { 355 // current_pcb().mark_sleep_interruptible(); 356 // } 357 358 // *stdin_waiter_guard = Some(current_pcb()); 359 // drop(stdin_waiter_guard); 360 // drop(state_guard); 361 // sched(); 362 // continue; 363 // } 364 // } else { 365 // // 非阻塞读,没读到就直接返回了 366 // return Ok(cnt); 367 // } 368 // }else{ 369 // buf[cnt] = val.unwrap(); 370 // cnt += 1; 371 // } 372 // } 373 374 // return Ok(cnt); 375 // } 376 377 // fn write_stdin(&self) 378 379 // /// @brief 非休眠的,自旋地读队列,直到有元素被读出来 380 // fn ringbuf_spin_dequeue(dst: &mut u8, queue: &mut AllocRingBuffer<u8>) { 381 // loop { 382 // if let Some(val) = queue.dequeue() { 383 // *dst = val; 384 // return; 385 // } 386 // } 387 // } 388