📄 process.c
字号:
// process#include "hos.h"union task_union process_table[10]; // 10 process for nowunsigned long *swapper_dir0; // page dir 0 for kernel. kernel is // max 2M(which is 512 frames), and // each dir can cover 1024 frames, so // we need only 1 dir for kernel.union task_union * init_task_union = &process_table[0];struct task_struct * current; struct task_struct * init_task = (struct task_struct *) &process_table[0];struct task_struct *process_q_head, *process_q_tail, *run_q_head, *run_q_tail;//struct task_struct * p1 = (struct task_struct *) &process_table[1];//struct task_struct * p2 = (struct task_struct *) &process_table[2];struct tss_struct init_tss;#define _set_tssldt_desc(n, addr, limit, type) \__asm__("movw %w3, 0(%2)\n\t" \ "movw %%ax,2(%2)\n\t" \ "rorl $16,%%eax\n\t" \ "movb %%al,4(%2)\n\t" \ "movb %4,5(%2)\n\t" \ "movb $0,6(%2)\n\t" \ "movb %%ah,7(%2)\n\t" \ "rorl $16,%%eax" \ :"=m"(*(n)): "a"(addr), "r"(n), "ir"(limit), "i"(type))void tss_init(void){ // make tss descr in GDT point to init_tss _set_tssldt_desc(GDT+3, (int)&init_tss, 235, 0x89); // copy linux GDT[3].b &= 0xfffffdff; // now load TR __asm__("ltr %%ax"::"a"(3<<3));}void init_process_q(void){ process_q_head=process_q_tail=init_task;}void init_run_q(void){ run_q_head=run_q_tail=init_task;}void add_to_process_q(struct task_struct *p){ process_q_tail->next_task=p; p->prev_task = process_q_tail; p->next_task = process_q_head; process_q_tail=p;}void remove_from_process_q(struct task_struct *p){ struct task_struct *prev, *next, *tmp=process_q_head->next_task; while(tmp != process_q_head){ if (tmp==p){ prev = tmp->prev_task; next = tmp->next_task; prev->next_task = next; next->prev_task = prev; if (tmp==process_q_tail) process_q_tail = prev; break; } else tmp=tmp->next_task; }}void wake_up(struct task_struct *p){ run_q_tail->next_run=p; p->prev_run = run_q_tail; p->next_run = run_q_head; run_q_tail=p;}struct task_struct * find_child(struct task_struct *p){// return process whose parent is p struct task_struct *tmp=process_q_head->next_task; while(tmp != run_q_head){ if (tmp->parent==p) return tmp; else tmp=tmp->next_task; } panic("could not find child\n");}void remove_from_run_q(struct task_struct *p){ struct task_struct *prev, *next, *tmp=run_q_head->next_run; while(tmp != run_q_head){ if (tmp==p){ prev = tmp->prev_run; next = tmp->next_run; prev->next_run = next; next->prev_run = prev; if (tmp==run_q_tail) run_q_tail = prev; break; } else tmp=tmp->next_run; }}void display_regs(struct pt_regs *regs){ printk("ebx:%x,ecx:%x,edx:%x,esi:%x,edi:%x,ebp:%x,eax:%x,xds:%x,xes:%x,orig_eax:%x,eip:%x,xcs:%x,eflags:%x,esp:%x,xss:%x\n",regs->ebx,regs->ecx,regs->edx,regs->esi,regs->edi,regs->ebp,regs->eax,regs->xds,regs->xes,regs->orig_eax,regs->eip,regs->xcs,regs->eflags,regs->esp,regs->xss);}void display_regs2(struct pt_regs regs){ printk("display reg2\n"); display_regs(®s);}void init_task_init_mm(struct task_struct *p){// init mm for init task int i; printk("in Init_task_init_mm\n"); swapper_dir0 = (unsigned long *)get_free_pgframe(); init_directory(swapper_dir0); // init with 0's p->mm.pgdir = (unsigned long *)get_free_pgframe(); init_directory_table(p); // init with 0's first printk("aft init dir\n"); p->mm.pgdir[0]=(unsigned long)swapper_dir0 | 0x03;// kernel's page directory 0 for(i=0;i<MAXFRAME;i++){ swapper_dir0[i]=(i*PGSIZE) | 0x03; // location of each frame. each frame // is R/W and occupied //printk("swapper_dir0[%d] is %x\n", i, swapper_dir0[i]); //wait_for_anykey(); } //printk("dump swapper_dir0\n"); //dump_directory(swapper_dir0); printk("bef dump mm\n"); dump_mm(p); wait_for_anykey();}void make_init_task(void){ // first intialize all entries in process table printk("In make_init_task\n"); int i; struct task_struct *t; for(i=0;i<10;i++){ t=(struct task_struct *)&process_table[i]; t->pid=-1; } // process_table[0] is for init_task t= init_task; t->pid = 0; t->state = 0; t->pptr=0; t->next_task=t; // next_task is itself for now t->next_run=t; // next_run is itself for now t->prev_task=t; // prev_task is itself for now t->prev_run=t; // prev_run is itself for now init_process_q(); init_run_q(); init_task_init_mm(t); t->counter = INIT_COUNTER; t->need_reschedule=0; init_tss.esp0 = (long)init_task+8192; init_tss.ss0=__KERNEL_DS; FDTable_init(t->fd);}int kernel_thread(void (*f)()){ long retval; __asm__ __volatile__( "int $0x80\n\t" "cmpl $0,%%eax\n\t" "jne 1f\n\t" // parent - jump // child here //"L1: jmp L1\n\t" //"call p1_body\n\t" "call *%2\n\t" // child call f "1:\t" :"=&a"(retval) :"0"(2),"r"(f):"memory"); return retval;}char exec_path[10]="/sh";void init(){ printk("in init. we are about to exec to /sh\n"); wait_for_anykey(); //do_exec("/p1"); __asm__ __volatile__( "movl $11, %%eax\n\t" "movl %0, %%ecx\n\t" "int $0x80\n\t" : : "g"(exec_path):"memory"); printk("this should never be printed\n");}void p1_body(struct pt_regs regs){ // addr of regs is actually 4 bytes ahead of pt_regs structure // when we come here through ret because ret pops out ret addr // but compiler assumes there is return addr in stack and computes // addr of regs. int i; long esp; float a=3.0; //printk("p1. regs is %x",®s); //display_regs(®s); for(;;); /* asm("cli\n\t" "movl %%esp, %0\n\t":"=m"(esp):); printk("p1. esp is %x\n",esp); for(;;); */ for(;;){ printk("p1"); for(i=0;i<10000000;i++) a=a+1.0; }}void p2_body(){ int i; float a=3.0; for(;;){ printk("p2"); for(i=0;i<10000000;i++) a=a+1.0; }}int sys_fork(struct pt_regs regs){ return do_fork(regs.esp, ®s);}struct task_struct * alloc_task_struct(void){ int i; struct task_struct * t; for(i=0;i<10;i++){ t=(struct task_struct *)&process_table[i]; if (t->pid == -1) {// found empty entry printk("process is assigend. location: %x. entry: %d\n", t,i); return t; } } panic("no more process\n");}int get_pid(){ static curr_pid=0; return ++curr_pid;}void cp_curr_to_p(struct task_struct *src, struct task_struct *dest){// copy task struct from src to dest int n = sizeof(struct task_struct); int i; char * s = (char *)src; char * d = (char *)dest; printk("in cp_curr_to_p. src at %x, dest at %x, size %d\n",src,dest,n); for(i=0;i<n;i++) d[i]=s[i]; printk("after cp curr to p. src:%d, dest:%d\n",src->pid,dest->pid);}int do_fork(long stack_start, struct pt_regs *regs){ struct task_struct * p; printk("in do_fork\n"); p=alloc_task_struct(); //*p = *current; // some weird err happens when the size of task struct is over 16*4 // bytes. the asm code calls memcpy and the compiler complains it has // no memcpy. why then it generates code that calls memcpy? // anyway, i manually copy them to avoid that error cp_curr_to_p(current,p); copy_mm(current, p); printk("aft copy task_struct\n"); p->pid = get_pid(); p->counter=INIT_COUNTER; p->need_reschedule=0; printk("child's pid is %d\n",p->pid); copy_thread(stack_start, p, regs); p->parent = current; add_to_process_q(p); // add to process q wake_up(p); // add to ruq q // change eax of parent to child's pid regs->eax=p->pid;}void copy_thread(unsigned long esp, struct task_struct *p, struct pt_regs *regs){ struct pt_regs * childregs; printk("copy thread\n"); childregs = ((struct pt_regs *)(8192+(unsigned long)p))-1; //struct_cpy(childregs, regs); *childregs = *regs; childregs->eax = 0; //regs->eax=p->pid; // for parent //childregs->esp=esp; linux does this way. copies parent's stack top // and later when the child really used the stack Linux provides // child's own stack and adjust esp. for us, we simply set // childregs->esp to esp0. this will work only for kernel_thread. // for user stack (for fork from user program), we need to provide // a stack to the child and copy parent's stack on it and set // esp accordingly p->esp = (unsigned long) childregs; //p->esp0= (unsigned long) (childregs+1); //childregs->esp = p->esp0; we handle only kernel mode process display_regs(childregs); printk("stack top is %x\n", p->esp); printk("ret from fork is %x\n", &ret_from_fork); p->eip=(unsigned long) &ret_from_fork; //p->eip=(unsigned long) p1_body;}void panic(char *text){ printk("PANIC: %s", text); for(;;);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -