void kfork_proc(char *addr) { register struct task_struct *t; t = find_empty_process(); t->t_xregs.cs = kernel_cs; /* Run in kernel space */ t->t_regs.ds = t->t_regs.es = t->t_regs.ss = kernel_ds; arch_build_stack(t, addr); }
int do_fork() { // int i = 0; int child_pid = -1; //child process pid int pid = current->pid; //parent process pid; int ret = -1; int child_base = 0; struct task_struct *p; // struct file *f; // p = (struct task_struct *)get_free_page(); ret = find_empty_process(); if(ret == -1) panic("cannot find empty process\n"); else child_pid = ret; p = proc_table + child_pid; *p = proc_table[3]; //*p = *current; p->state = TASK_UNINTERRUPTIBLE; p->pid = child_pid; p->parent = pid; p->regs.eflags = 0x1202; sprintf(p->name,"%s-%d",p->name,p->pid); // printk("p->name= %s\n",p->name); child_base = copy_mem(pid,p); /* for(i = 0;i < NR_OPEN;i++) { if((f = p->filp[i]) != NULL) { f->f_count++; } } if(current->pwd) current->pwd->i_count++; if(current->root) current->root->i_count++; */ p->state = TASK_RUNNING; init_descriptor(&p->ldts[INDEX_LDT_C],child_base,(PROC_IMAGE_SIZE_DEFAULT - 1)>>LIMIT_4K_SHIFT,DA_LIMIT_4K | DA_32 |DA_C|PRIVILEGE_USER << 5); init_descriptor(&p->ldts[INDEX_LDT_D],child_base,(PROC_IMAGE_SIZE_DEFAULT - 1)>>LIMIT_4K_SHIFT,DA_LIMIT_4K | DA_32 |DA_DRW|PRIVILEGE_USER << 5); return pid; }
/* * fork系统调用。NOTE! 其参数须与copy_process()同步。fork只创建 * 一个新进程,子进程与父进程暂时共享页表。直到父进程或子进程 * 写页面时,子进程再分配自己的页表以及页面。 */ int sys_fork(long none, long ebx, long ecx, long edx, long gs, long fs, long es, long ds, long ebp, long esi, long edi, long eip, long cs, long eflags, long esp, long ss) { int nr = 0; if(!(nr = find_empty_process())) { k_printf("fork: have no empty-process!"); return -1; } if(0 == (proc[nr]=(struct proc_struct *)get_free_page())) { k_printf("fork: have no free-page!"); return -1; } d_printf("pid-%d-proc-struct ADDR: %x.\n", last_pid, proc[nr]); copy_process(nr, gs, fs, es, ds, edi, esi, ebp, edx, ecx, ebx, eip, cs, eflags, esp, ss); proc[nr]->state = RUNNING; return last_pid; }
asmlinkage int sys_fork(struct pt_regs regs) { struct task_struct *tsk; int nr; long flags; unsigned long used_memory = 0; save_flags(flags); cli(); // find a free entry in the process table nr = find_empty_process(); if (nr < 0) { printk("fork: pids not available at the moment!\n"); goto fork_no_entry; } // allocate a page for the process descriptor tsk = (struct task_struct *) get_free_page(); if (!tsk) { goto fork_no_mem; } // copy descriptor: pid and counter will contain different values for // father and child *tsk = *current; tsk->pid = nr; tsk->counter = tsk->priority; // if we are forking the idle process, we assume its child will call an // exec just after the fork. In this case we do not duplicate code/data. // If we are forking whatever process, so it is necessary allocate a // page for it (containing code and data) e setup its LDT to the new // address space if (current->pid != 0) { // allocate memory for code/data tsk->mem = (char *) get_free_pages(current->used_pages); if (!tsk->mem) { goto fork_data_no_mem; } // total memory used by current process used_memory = current->used_pages * PAGE_SIZE; // copy process data memcpy(tsk->mem, current->mem, used_memory); // set up LDT set_code_desc(&(tsk->ldt[1]), (u_long) tsk->mem, used_memory); set_data_desc(&(tsk->ldt[2]), (u_long) tsk->mem, used_memory); } // setup TSS tsk->tss.back_link = 0; tsk->tss.esp0 = PAGE_SIZE + (unsigned long) tsk; tsk->tss.ss0 = KERNEL_DS; tsk->tss.esp1 = 0; tsk->tss.ss1 = 0; tsk->tss.esp2 = 0; tsk->tss.ss2 = 0; tsk->tss.cr3 = 0; tsk->tss.eip = regs.eip; tsk->tss.eflags = regs.eflags; tsk->tss.eax = 0; tsk->tss.ecx = regs.ecx; tsk->tss.edx = regs.edx; tsk->tss.ebx = regs.ebx; tsk->tss.esp = regs.esp; tsk->tss.ebp = regs.ebp; tsk->tss.esi = regs.esi; tsk->tss.edi = regs.edi; tsk->tss.es = regs.xes & 0xffff; tsk->tss.cs = regs.xcs & 0xffff; tsk->tss.ss = regs.xss & 0xffff; tsk->tss.ds = regs.xds & 0xffff; // it is not necessary set FS and GS tsk->tss.ldt = _LDT(nr); tsk->tss.trace = 0; tsk->tss.bitmap = 0xDFFF; tsk->tss.tr = _TSS(nr); set_tss_desc(gdt+(nr<<1)+FIRST_TSS_ENTRY, &(tsk->tss)); set_ldt_desc(gdt+(nr<<1)+FIRST_LDT_ENTRY, &(tsk->ldt), 3); task[nr] = tsk; restore_flags(flags); return nr; fork_data_no_mem: free_page(tsk); fork_no_mem: restore_flags(flags); return -ENOMEM; fork_no_entry: restore_flags(flags); return -EAGAIN; }