kbdgetc(void){static uint shift;static uchar *charcode[4]={
normalmap, shiftmap, ctlmap, ctlmap
};//映射表
uint st, data, c;
st =inb(KBSTATP);if((st & KBS_DIB)==0)return-1;
data =inb(KBDATAP);if(data ==0xE0){
shift |= E0ESC;return0;}elseif(data &0x80){
data =(shift & E0ESC ? data : data &0x7F);
shift &=~(shiftcode[data]| E0ESC);return0;}elseif(shift & E0ESC){
data |=0x80;
shift &=~E0ESC;}
shift |= shiftcode[data];
shift ^= togglecode[data];
c = charcode[shift &(CTL | SHIFT)][data];if(shift & CAPSLOCK){if('a'<= c && c <='z')
c +='A'-'a';elseif('A'<= c && c <='Z')
c +='a'-'A';}return c;}
structbuf{int flags;//表示该块是否脏是否有效
uint dev;//该缓存块表示的设备
uint blockno;//块号structsleeplock lock;//休眠锁
uint refcnt;//引用该块的个数structbuf*prev;//该块的前一个块structbuf*next;//该块的后一个块structbuf*qnext;//下一个磁盘队列块
uchar data[BSIZE];//缓存的数据};#defineB_VALID0x2// buffer has been read from disk#defineB_DIRTY0x4// buffer needs to be written to disk
voidkfree(char*v){structrun*r;if((uint)v % PGSIZE || v < end ||V2P(v)>= PHYSTOP)panic("kfree");// Fill with junk to catch dangling refs.memset(v,1, PGSIZE);if(kmem.use_lock)acquire(&kmem.lock);
r =(structrun*)v;
r->next = kmem.freelist;
kmem.freelist = r;if(kmem.use_lock)release(&kmem.lock);}
char*kalloc(void){structrun*r;if(kmem.use_lock)acquire(&kmem.lock);
r = kmem.freelist;if(r)
kmem.freelist = r->next;if(kmem.use_lock)release(&kmem.lock);return(char*)r;}
voidinituvm(pde_t*pgdir,char*init, uint sz){char*mem;if(sz >= PGSIZE)panic("inituvm: more than a page");
mem =kalloc();memset(mem,0, PGSIZE);mappages(pgdir,0, PGSIZE,V2P(mem), PTE_W|PTE_U);memmove(mem, init, sz);}
voidfreevm(pde_t*pgdir){
uint i;if(pgdir ==0)panic("freevm: no pgdir");deallocuvm(pgdir, KERNBASE,0);for(i =0; i < NPDENTRIES; i++){if(pgdir[i]& PTE_P){char* v =P2V(PTE_ADDR(pgdir[i]));kfree(v);}}kfree((char*)pgdir);}
voidscheduler(void){structproc*p;for(;;){// Enable interrupts on this processor.sti();// Loop over process table looking for process to run.acquire(&ptable.lock);for(p = ptable.proc; p <&ptable.proc[NPROC]; p++){if(p->state != RUNNABLE)continue;
proc = p;switchuvm(p);
p->state = RUNNING;swtch(&cpu->scheduler, p->context);switchkvm();
proc =0;}release(&ptable.lock);}}
// Give up the CPU for one scheduling round.voidyield(void){acquire(&ptable.lock);//DOC: yieldlock
proc->state = RUNNABLE;sched();release(&ptable.lock);}
staticvoidwakeup1(void*chan){structproc*p;for(p = ptable.proc; p <&ptable.proc[NPROC]; p++)if(p->state == SLEEPING && p->chan == chan)
p->state = RUNNABLE;}// Wake up all processes sleeping on chan.voidwakeup(void*chan){acquire(&ptable.lock);wakeup1(chan);release(&ptable.lock);}
for(b =0; b < sb.size; b += BPB){
bp =bread(dev,BBLOCK(b, sb));for(bi =0; bi < BPB && b + bi < sb.size; bi++){
m =1<<(bi %8);if((bp->data[bi/8]& m)==0){
bp->data[bi/8]|= m;log_write(bp);brelse(bp);bzero(dev, b + bi);return b + bi;}}brelse(bp);}panic("balloc: out of blocks");
// Free a disk block.staticvoidbfree(int dev, uint b){structbuf*bp;int bi, m;readsb(dev,&sb);
bp =bread(dev,BBLOCK(b, sb));
bi = b % BPB;
m =1<<(bi %8);if((bp->data[bi/8]& m)==0)panic("freeing free block");
bp->data[bi/8]&=~m;log_write(bp);brelse(bp);}
struct{structspinlock lock;structbuf buf[NBUF];// Linked list of all buffers, through prev/next.// head.next is most recently used.structbuf head;} bcache;
structdinode{short type;// File typeshort major;// Major device number (T_DEV only)short minor;// Minor device number (T_DEV only)short nlink;// Number of links to inode in file system
uint size;// Size of file (bytes)
uint addrs[NDIRECT+1];// Data block addresses};
default:if(proc ==0||(tf->cs&3)==0){// In kernel, it must be our mistake.cprintf("unexpected trap %d from cpu %d eip %x (cr2=0x%x)\n",
tf->trapno,cpunum(), tf->eip,rcr2());panic("trap");}// In user space, assume process misbehaved.cprintf("pid %d %s: trap %d err %d on cpu %d ""eip 0x%x addr 0x%x--kill proc\n",
proc->pid, proc->name, tf->trapno, tf->err,cpunum(), tf->eip,rcr2());
proc->killed =1;