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