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