SETGATE(idt[i],0,GD_KTEXT,__vectors[i],DPL_KERNEL);
}
SETGATE(idt[T_SYSCALL],1,GD_KTEXT,__vectors[T_SYSCALL],DPL_USER);
lidt(&idt_pd);
Kern/process/proc.c:
staticstructproc_struct*
alloc_proc(void){
structproc_struct*proc=kmalloc(sizeof(structproc_struct));
if(proc!
=NULL){
//LAB4:
EXERCISE1YOURCODE
/*
*belowfieldsinproc_structneedtobeinitialized
*enumproc_statestate;//Processstate
*intpid;//ProcessID
*intruns;//therunningtimesofProces
*uintptr_tkstack;//Processkernelstack
*volatileboolneed_resched;//boolvalue:
needtoberescheduledtoreleaseCPU?
*structproc_struct*parent;//theparentprocess
*structmm_struct*mm;//Process'smemorymanagementfield
*structcontextcontext;//Switchheretorunprocess
*structtrapframe*tf;//Trapframeforcurrentinterrupt
*uintptr_tcr3;//CR3register:
thebaseaddrofPageDirectroyTable(PDT)
*uint32_tflags;//Processflag
*charname[PROC_NAME_LEN+1];//Processname
*/
proc->state=PROC_UNINIT;
proc->pid=-1;
proc->runs=0;
proc->kstack=0;
proc->need_resched=0;
proc->parent=NULL;
proc->mm=NULL;
memset(&(proc->context),0,sizeof(structcontext));
proc->tf=NULL;
proc->cr3=boot_cr3;
proc->flags=0;
memset(proc->name,0,PROC_NAME_LEN);
//LAB5YOURCODE:
(updateLAB4steps)
/*
*belowfields(addinLAB5)inproc_structneedtobeinitialized
*uint32_twait_state;//waitingstate
*structproc_struct*cptr,*yptr,*optr;//relationsbetweenprocesses
*/
proc->wait_state=0;
proc->cptr=proc->yptr=proc->optr=NULL;
}
returnproc;
}
int
do_fork(uint32_tclone_flags,uintptr_tstack,structtrapframe*tf){
intret=-E_NO_FREE_PROC;
structproc_struct*proc;
if(nr_process>=MAX_PROCESS){
gotofork_out;
}
ret=-E_NO_MEM;
//LAB4:
EXERCISE2YOURCODE
/*
*SomeUsefulMACROs,FunctionsandDEFINEs,youcanusetheminbelowimplementation.
*MACROsorFunctions:
*alloc_proc:
createaprocstructandinitfields(lab4:
exercise1)
*setup_kstack:
allocpageswithsizeKSTACKPAGEasprocesskernelstack
*copy_mm:
process"proc"duplicateORshareprocess"current"'smmaccordingclone_flags
*ifclone_flags&CLONE_VM,then"share";else"duplicate"
*copy_thread:
setupthetrapframeontheprocess'skernelstacktopand
*setupthekernelentrypointandstackofprocess
*hash_proc:
addprocintoprochash_list
*get_pid:
allocauniquepidforprocess
*wakup_proc:
setproc->state=PROC_RUNNABLE
*VARIABLES:
*proc_list:
theprocessset'slist
*nr_process:
thenumberofprocessset
*/
//1.callalloc_proctoallocateaproc_struct
//2.callsetup_kstacktoallocateakernelstackforchildprocess
//3.callcopy_mmtodupORsharemmaccordingclone_flag
//4.callcopy_threadtosetuptf&contextinproc_struct
//5.insertproc_structintohash_list&&proc_list
//6.callwakup_proctomakethenewchildprocessRUNNABLE
//7.setretvauleusingchildproc'spid
if((proc=alloc_proc())==NULL){
gotofork_out;
}
proc->parent=current;
assert(current->wait_state==0);
if(setup_kstack(proc)!
=0){
gotobad_fork_cleanup_proc;
}
if(copy_mm(clone_flags,proc)!
=0){
gotobad_fork_cleanup_kstack;
}
copy_thread(proc,stack,tf);
boolintr_flag;
local_intr_save(intr_flag);
{
proc->pid=get_pid();
hash_proc(proc);
set_links(proc);
}
local_intr_restore(intr_flag);
wakeup_proc(proc);
ret=proc->pid;
//LAB5YOURCODE:
(updateLAB4steps)
/*SomeFunctions
*set_links:
settherelationlinksofprocess.ALSOSEE:
remove_links:
leantherelationlinksofprocess
*-------------------
*updatestep1:
setchildproc'sparenttocurrentprocess,makesurecurrentprocess'swait_stateis0
*updatestep5:
insertproc_structintohash_list&&proc_list,settherelationlinksofprocess
*/
fork_out:
returnret;
bad_fork_cleanup_kstack:
put_kstack(proc);
bad_fork_cleanup_proc:
kfree(proc);
gotofork_out;
}
练习1:
加载应用程序并执行
do_execv函数调用load_icode(位于kern/process/proc.c中)来加载并解析一个处于内存中的ELF执行文件格式的应用程序,建立相应的用户内存空间来放置应用程序的代码段、数据段等,且要设置好proc_struct结构中的成员变量trapframe中的内容,确保在执行此进程后,能够从应用程序设定的起始执行地址开始执行。
需设置正确的trapframe内容。
程序代码:
staticintload_icode(unsignedchar*binary,size_tsize){
if(current->mm!
=NULL){
panic("load_icode:
current->mmmustbeempty.\n");
}
intret=-E_NO_MEM;
structmm_struct*mm;
//为当前进程申请内存
if((mm=mm_create())==NULL){
gotobad_mm;
}
//建立一个新的PDT,设置mm->pgdir为PDT的内核虚拟地址
if(setup_pgdir(mm)!
=0){
gotobad_pgdir_cleanup_mm;
}
//复制上下文和数据部分,建立二进制程序的BSS段
structPage*page;
//getthefileheaderofthebianryprogram(ELFformat)
structelfhdr*elf=(structelfhdr*)binary;
//gettheentryoftheprogramsectionheadersofthebianryprogram(ELFformat)
structproghdr*ph=(structproghdr*)(binary+elf->e_phoff);
//Thisprogramisvalid?
if(elf->e_magic!
=ELF_MAGIC){
ret=-E_INVAL_ELF;
gotobad_elf_cleanup_pgdir;
}
uint32_tvm_flags,perm;
structproghdr*ph_end=ph+elf->e_phnum;
for(;ph//findeveryprogramsectionheaders
if(ph->p_type!
=ELF_PT_LOAD){
continue;
}
if(ph->p_filesz>ph->p_memsz){
ret=-E_INVAL_ELF;
gotobad_cleanup_mmap;
}
if(ph->p_filesz==0){
continue;
}
//callmm_mapfuntosetupthenewvma(ph->p_va,ph->p_memsz)
vm_flags=0,perm=PTE_U;
if(ph->p_flags&ELF_PF_X)vm_flags|=VM_EXEC;
if(ph->p_flags&ELF_PF_W)vm_flags|=VM_WRITE;
if(ph->p_flags&ELF_PF_R)vm_flags|=VM_READ;
if(vm_flags&VM_WRITE)perm|=PTE_W;
if((ret=mm_map(mm,ph->p_va,ph->p_memsz,vm_flags,NULL))!
=0){
gotobad_cleanup_mmap;
}
unsignedchar*from=binary+ph->p_offset;
size_toff,size;
uintptr_tstart=ph->p_va,end,la=ROUNDDOWN(start,PGSIZE);
ret=-E_NO_MEM;
//allocmemory,andcopythecontentsofeveryprogramsection(from,from+end)toprocess'smemory(la,la+end)
end=ph->p_va+ph->p_filesz;
//copyTEXT/DATAsectionofbianryprogram
while(startif((page=pgdir_alloc_page(mm->pgdir,la,perm))==NULL){
gotobad_cleanup_mmap;
}
off=start-la,size=PGSIZE-off,la+=PGSIZE;
if(endsize-=la-end;
}
memcpy(page2kva(page)+off,from,size);
start+=size,from+=size;
}
//buildBSSsectionofbinaryprogram
end=ph->p_va+ph->p_memsz;
if(start/*ph->p_memsz==ph->p_filesz*/
if(start==end){
continue;
}
off=start+PGSIZE-la,size=PGSIZE-off;
if(endsize-=la-end;
}
memset(page2kva(page)+off,0,size);
start+=size;
assert((end=la&&start==la));
}
while(startif((page=pgdir_alloc_page(mm->pgdir,la,perm))==NULL){
gotobad_cleanup_mmap;
}
off=start-la,size=PGSIZE-off,la+=PGSIZE;
if(endsize-=la-end;
}
memset(page2kva(page)+off,0,size);
start+=size;
}
}
//设置用户堆栈内存
vm_flags=VM_READ|VM_WRITE|VM_STACK;
if((ret=mm_map(mm,USTACKTOP-USTACKSIZE,USTACKSIZE,vm_flags,NULL))!
=0){
gotobad_cleanup_mmap;
}
assert(pgdir_alloc_page(mm->pgdir,USTACKTOP-PGSIZE,PTE_USER)!
=NULL);
assert(pgdir_alloc_page(mm->pgdir,USTACKTOP-2*PGSIZE,PTE_USER)!
=NULL);
assert(pgdir_alloc_page(mm->pgdir,USTACKTOP-3*PGSIZE,PTE_USER)!
=