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