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