Skip to content

驱虫日志:控制台异常输入

现象描述:

  • c

#include <stdlib.h> #include <stdio.h> int main() { char *s = malloc(1024); scanf("%s", s); printf("%s", s); } ``` - StarryOS多次运行用户态程序,类似上述代码之时,会因为一些控制台输入问题导致重复第一次的输入。

bash
starry:# ./a.out  
first  
first
starry:# ./a.out  
second  
first
  • 但是使用pipe传递给程序的时候被证明是正确的,将问题确认在控制台输入处

解决问题

  • 全局的tty设备为一个全局静态单例,所有进程应该是共享这一实例
rust
lazy_static! {
    /// The default TTY device.
    pub static ref N_TTY: Arc<NTtyDriver> = new_n_tty();
}
  • 追溯一下NTtyDriver应该是一个Tty,根据已有信息可以直接排查TtyRead
rust
impl<R: TtyRead, W: TtyWrite> InputReader<R, W> {
//注意这个函数
pub fn poll(&mut self) -> bool {
            if self.read_range.is_empty() {
            let read = self.reader.read(&mut self.read_buf);
            self.read_range = 0..read;
        }
}
  • poll是负责从底层控制台读取原始字节的函数
    • 此处仅当 read_range 为空(上次读取的数据已全部处理完)时才读取(调用reader.read,最底层调用为console::read_byte)
  • 那么下面一个分句中介绍了line_read是是否完成一行的读取,offset是用来判断读取的偏移是否已经达到这一行的末位,即本行是否完成。但是这里仅将line_read标志位置为0,没有清空buff,而buff仅在满了之后清空,所以会出现第二次调用的时候从头开始读取,还是第一次的缓存的效果
rust
            if let Some(offset) = &mut self.line_read {
                let read = self.buf_tx.push_slice(&self.line_buf[*offset..]);
                if read == 0 {
                    break;
                }
                sent += read;
                *offset += read;
                if *offset == self.line_buf.len() {
                    self.line_read = None;
                    self.line_buf.clear();  // 新加入,用于清空 
                }
                continue;
            }

上次更新于: