console.c

来自「美国mit操作系统课程所用的一个教学操作系统xv6」· C语言 代码 · 共 306 行

C
306
字号
// Console input and output.// Input is from the keyboard only.// Output is written to the screen and the printer port.#include "types.h"#include "defs.h"#include "param.h"#include "traps.h"#include "spinlock.h"#include "dev.h"#include "mmu.h"#include "proc.h"#include "x86.h"#define CRTPORT 0x3d4#define LPTPORT 0x378#define BACKSPACE 0x100static ushort *crt = (ushort*)0xb8000;  // CGA memorystatic struct spinlock console_lock;int panicked = 0;int use_console_lock = 0;// Copy console output to parallel port, which you can tell// .bochsrc to copy to the stdout://   parport1: enabled=1, file="/dev/stdout"static voidlpt_putc(int c){  int i;  for(i = 0; !(inb(LPTPORT+1) & 0x80) && i < 12800; i++)    ;  if(c == BACKSPACE)    c = '\b';  outb(LPTPORT+0, c);  outb(LPTPORT+2, 0x08|0x04|0x01);  outb(LPTPORT+2, 0x08);}static voidcga_putc(int c){  int pos;    // Cursor position: col + 80*row.  outb(CRTPORT, 14);  pos = inb(CRTPORT+1) << 8;  outb(CRTPORT, 15);  pos |= inb(CRTPORT+1);  if(c == '\n')    pos += 80 - pos%80;  else if(c == BACKSPACE){    if(pos > 0)      crt[--pos] = ' ' | 0x0700;  } else    crt[pos++] = (c&0xff) | 0x0700;  // black on white    if((pos/80) >= 24){  // Scroll up.    memmove(crt, crt+80, sizeof(crt[0])*23*80);    pos -= 80;    memset(crt+pos, 0, sizeof(crt[0])*(24*80 - pos));  }    outb(CRTPORT, 14);  outb(CRTPORT+1, pos>>8);  outb(CRTPORT, 15);  outb(CRTPORT+1, pos);  crt[pos] = ' ' | 0x0700;}voidcons_putc(int c){  if(panicked){    cli();    for(;;)      ;  }  lpt_putc(c);  cga_putc(c);}voidprintint(int xx, int base, int sgn){  static char digits[] = "0123456789ABCDEF";  char buf[16];  int i = 0, neg = 0;  uint x;  if(sgn && xx < 0){    neg = 1;    x = 0 - xx;  } else {    x = xx;  }  do{    buf[i++] = digits[x % base];  }while((x /= base) != 0);  if(neg)    buf[i++] = '-';  while(--i >= 0)    cons_putc(buf[i]);}// Print to the console. only understands %d, %x, %p, %s.voidcprintf(char *fmt, ...){  int i, c, state, locking;  uint *argp;  char *s;  locking = use_console_lock;  if(locking)    acquire(&console_lock);  argp = (uint*)(void*)&fmt + 1;  state = 0;  for(i = 0; fmt[i]; i++){    c = fmt[i] & 0xff;    switch(state){    case 0:      if(c == '%')        state = '%';      else        cons_putc(c);      break;        case '%':      switch(c){      case 'd':        printint(*argp++, 10, 1);        break;      case 'x':      case 'p':        printint(*argp++, 16, 0);        break;      case 's':        s = (char*)*argp++;        if(s == 0)          s = "(null)";        for(; *s; s++)          cons_putc(*s);        break;      case '%':        cons_putc('%');        break;      default:        // Print unknown % sequence to draw attention.        cons_putc('%');        cons_putc(c);        break;      }      state = 0;      break;    }  }  if(locking)    release(&console_lock);}intconsole_write(struct inode *ip, char *buf, int n){  int i;  iunlock(ip);  acquire(&console_lock);  for(i = 0; i < n; i++)    cons_putc(buf[i] & 0xff);  release(&console_lock);  ilock(ip);  return n;}#define INPUT_BUF 128struct {  struct spinlock lock;  char buf[INPUT_BUF];  uint r;  // Read index  uint w;  // Write index  uint e;  // Edit index} input;#define C(x)  ((x)-'@')  // Control-xvoidconsole_intr(int (*getc)(void)){  int c;  acquire(&input.lock);  while((c = getc()) >= 0){    switch(c){    case C('P'):  // Process listing.      procdump();      break;    case C('U'):  // Kill line.      while(input.e != input.w &&            input.buf[(input.e-1) % INPUT_BUF] != '\n'){        input.e--;        cons_putc(BACKSPACE);      }      break;    case C('H'):  // Backspace      if(input.e != input.w){        input.e--;        cons_putc(BACKSPACE);      }      break;    default:      if(c != 0 && input.e-input.r < INPUT_BUF){        input.buf[input.e++ % INPUT_BUF] = c;        cons_putc(c);        if(c == '\n' || c == C('D') || input.e == input.r+INPUT_BUF){          input.w = input.e;          wakeup(&input.r);        }      }      break;    }  }  release(&input.lock);}intconsole_read(struct inode *ip, char *dst, int n){  uint target;  int c;  iunlock(ip);  target = n;  acquire(&input.lock);  while(n > 0){    while(input.r == input.w){      if(cp->killed){        release(&input.lock);        ilock(ip);        return -1;      }      sleep(&input.r, &input.lock);    }    c = input.buf[input.r++ % INPUT_BUF];    if(c == C('D')){  // EOF      if(n < target){        // Save ^D for next time, to make sure        // caller gets a 0-byte result.        input.r--;      }      break;    }    *dst++ = c;    --n;    if(c == '\n')      break;  }  release(&input.lock);  ilock(ip);  return target - n;}voidconsole_init(void){  initlock(&console_lock, "console");  initlock(&input.lock, "console input");  devsw[CONSOLE].write = console_write;  devsw[CONSOLE].read = console_read;  use_console_lock = 1;  pic_enable(IRQ_KBD);  ioapic_enable(IRQ_KBD, 0);}voidpanic(char *s){  int i;  uint pcs[10];    __asm __volatile("cli");  use_console_lock = 0;  cprintf("cpu%d: panic: ", cpu());  cprintf(s);  cprintf("\n");  getcallerpcs(&s, pcs);  for(i=0; i<10; i++)    cprintf(" %p", pcs[i]);  panicked = 1; // freeze other CPU  for(;;)    ;}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?