You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

263 lines
7.0 KiB

/*
* linux/kernel/fork.c
*
* (C) 1991 Linus Torvalds
*/
/*
* 'fork.c' contains the help-routines for the 'fork' system call
* (see also system_call.s), and some misc functions ('verify_area').
* Fork is rather simple, once you get the hang of it, but the memory
* management can be a bitch. See 'mm/mm.c': 'copy_page_tables()'
*/
#include <errno.h>
#include <linux/sched.h>
#include <linux/kernel.h>
#include <asm/segment.h>
#include <asm/system.h>
#include <signal.h>
#include <sys/wait.h>
#include <linux/tty.h>
extern void write_verify(unsigned long address);
long last_pid=0;
void verify_area(void * addr,int size)
{
unsigned long start;
start = (unsigned long) addr;
size += start & 0xfff;
start &= 0xfffff000;
start += get_base(current->ldt[2]);
while (size>0) {
size -= 4096;
write_verify(start);
start += 4096;
}
}
int copy_mem(int nr,struct task_struct * p)
{
unsigned long old_data_base,new_data_base,data_limit;
unsigned long old_code_base,new_code_base,code_limit;
code_limit=get_limit(0x0f);
data_limit=get_limit(0x17);
old_code_base = get_base(current->ldt[1]);
old_data_base = get_base(current->ldt[2]);
if (old_data_base != old_code_base)
panic("We don't support separate I&D");
if (data_limit < code_limit)
panic("Bad data_limit");
new_data_base = new_code_base = nr * 0x4000000;
p->start_code = new_code_base;
set_base(p->ldt[1],new_code_base);
set_base(p->ldt[2],new_data_base);
if (copy_page_tables(old_data_base,new_data_base,data_limit)) {
free_page_tables(new_data_base,data_limit);
return -ENOMEM;
}
return 0;
}
/*
* Ok, this is the main fork-routine. It copies the system process
* information (task[nr]) and sets up the necessary registers. It
* also copies the data segment in it's entirety.
*/
int copy_process(int nr,long ebp,long edi,long esi,long gs,long none,
long ebx,long ecx,long edx,
long fs,long es,long ds,
long eip,long cs,long eflags,long esp,long ss)
{
struct task_struct *p;
int i;
struct file *f;
p = (struct task_struct *) get_free_page();
if (!p)
return -EAGAIN;
task[nr] = p;
__asm__ volatile ("cld"); /* by wyj */
*p = *current; /* NOTE! this doesn't copy the supervisor stack */
p->state = TASK_UNINTERRUPTIBLE;
p->pid = last_pid;
p->father = current->pid;
p->counter = p->priority;
p->signal = 0;
p->alarm = 0;
p->leader = 0; /* process leadership doesn't inherit */
p->utime = p->stime = 0;
p->cutime = p->cstime = 0;
p->start_time = jiffies;
p->tss.back_link = 0;
p->tss.esp0 = PAGE_SIZE + (long) p;
p->tss.ss0 = 0x10;
p->tss.eip = eip;
p->tss.eflags = eflags;
p->tss.eax = 0;
p->tss.ecx = ecx;
p->tss.edx = edx;
p->tss.ebx = ebx;
p->tss.esp = esp;
p->tss.ebp = ebp;
p->tss.esi = esi;
p->tss.edi = edi;
p->tss.es = es & 0xffff;
p->tss.cs = cs & 0xffff;
p->tss.ss = ss & 0xffff;
p->tss.ds = ds & 0xffff;
p->tss.fs = fs & 0xffff;
p->tss.gs = gs & 0xffff;
p->tss.ldt = _LDT(nr);
p->tss.trace_bitmap = 0x80000000;
if (last_task_used_math == current)
__asm__("clts ; fnsave %0"::"m" (p->tss.i387));
if (copy_mem(nr,p)) {
task[nr] = NULL;
free_page((long) p);
return -EAGAIN;
}
for (i=0; i<NR_OPEN;i++)
if (f=p->filp[i])
f->f_count++;
if (current->pwd)
current->pwd->i_count++;
if (current->root)
current->root->i_count++;
if (current->executable)
current->executable->i_count++;
set_tss_desc(gdt+(nr<<1)+FIRST_TSS_ENTRY,&(p->tss));
set_ldt_desc(gdt+(nr<<1)+FIRST_LDT_ENTRY,&(p->ldt));
short int tmp = NR_TASKS;
while (tmp--) /*<2A><><EFBFBD>̳<EFBFBD>ʼ<EFBFBD><CABC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1>Ҫ<EFBFBD><D2AA>ʼ<EFBFBD><CABC><EFBFBD><EFBFBD>Щ<EFBFBD><D0A9><EFBFBD><EFBFBD>*/
p->threads[tmp] = NULL;
p->index = 0;
p->process_or_thread = 0;
p->state = TASK_RUNNING; /* do this last, just in case */
return last_pid;
}
int find_empty_process(void)
{
int i;
repeat:
if ((++last_pid)<0) last_pid=1;
for(i=0 ; i<NR_TASKS ; i++)
if (task[i] && task[i]->pid == last_pid) goto repeat;
for(i=1 ; i<NR_TASKS ; i++)
if (!task[i])
return i;
return -EAGAIN;
}
//new
int create_thread(long eax, long ebp, long edi, long esi, long gs, long none,
long ebx, long ecx, long edx,
long fs, long es, long ds,
long eip, long cs, long eflags, long esp, long ss)
{
struct task_struct* p;
int i;
struct file* f;
int nr = find_empty_process();
p = (struct task_struct*)get_free_page();
if (!p)
return -EAGAIN;
task[nr] = p;
*p = *current; /* NOTE! this doesn't copy the supervisor stack */
p->state = TASK_UNINTERRUPTIBLE;
p->counter = p->priority;
p->signal = 0;
int index = 33;
while (index--)
p->sigaction[index] = current->sigaction[index];
p->blocked = current->blocked;
p->exit_code = p->exit_code;
p->start_code = current->start_code;
p->end_code = current->end_code;
p->end_data = current->end_data;
p->brk = current->brk;
current->brk += PAGE_SIZE;
p->start_stack = current->brk;
p->pid = nr;
p->father = current->pid;
p->pgrp = current->pgrp;
p->session = current->session;
p->leader = 0; /* process leadership doesn't inherit */
p->uid = current->uid;
p->euid = current->euid;
p->suid = current->suid;
p->gid = current->gid;
p->egid = current->egid;
p->sgid = current->sgid;
p->alarm = 0;
p->utime = p->stime = 0;
p->cutime = p->cstime = 0;
p->start_time = jiffies;
p->used_math = current->used_math;
p->tty = current->tty;
p->umask = current->umask;
p->close_on_exec = current->close_on_exec;
p->tss.back_link = 0;
p->tss.esp0 = PAGE_SIZE + (long)p;
p->tss.ss0 = 0x10;
p->tss.eip = ebx;
p->tss.eflags = eflags;
p->tss.eax = eax;
p->tss.ecx = ecx;
p->tss.edx = edx;
p->tss.ebx = ebx;
p->tss.esp = p->start_stack;
p->tss.ebp = ebp;
p->tss.esi = esi;
p->tss.edi = edi;
p->tss.es = es & 0xffff;
p->tss.cs = cs & 0xffff;
p->tss.ss = ss & 0xffff;
p->tss.ds = ds & 0xffff;
p->tss.fs = fs & 0xffff;
p->tss.gs = gs & 0xffff;
//p->tss.ldt = _LDT(nr);
p->tss.ldt = current->tss.ldt; // <20><><EFBFBD><EFBFBD>Ϊ<EFBFBD><CEAA><EFBFBD>׽<EFBFBD><D7BD>̵<EFBFBD>ldt<64><74>ַ
p->tss.trace_bitmap = 0x80000000;
if (last_task_used_math == current)
__asm__("clts ; fnsave %0"::"m" (p->tss.i387));
if (copy_mem(nr, p)) {
task[nr] = NULL;
free_page((long)p);
return -EAGAIN;
}
for (i = 0; i < NR_OPEN;i++)
if ((f = p->filp[i]))
f->f_count++;
if (current->pwd)
current->pwd->i_count++;
if (current->root)
current->root->i_count++;
if (current->executable)
current->executable->i_count++;
set_tss_desc(gdt + (nr << 1) + FIRST_TSS_ENTRY, &(p->tss));
set_ldt_desc(gdt + (nr << 1) + FIRST_LDT_ENTRY, &(p->ldt));
// <20><><EFBFBD>ݲ<EFBFBD><DDB2><EFBFBD>
//put_fs_long<6E><67><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>µ<EFBFBD><C2B5>̵߳Ķ<CCB5>ջ<EFBFBD><D5BB>ջ<EFBFBD><D5BB>
put_fs_long(ecx, p->tss.esp); // ecx<63><78><EFBFBD><EFBFBD>ŵ<EFBFBD><C5B5>ǽ<EFBFBD><C7BD><EFBFBD>Ҫ<EFBFBD><D2AA><EFBFBD>ݸ<EFBFBD><DDB8>̵߳IJ<CCB5><C4B2><EFBFBD>
p->tss.esp -= 4; // <20><>ջָ<D5BB><D6B8><EFBFBD>ٻ<EFBFBD><D9BB><EFBFBD>4<EFBFBD><34><EFBFBD>µ<EFBFBD><C2B5>߳<EFBFBD><DFB3><EFBFBD>תʱ<D7AA>򣬾Ϳ<F2A3ACBE><CDBF>Ի<EFBFBD><D4BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
current->threads[index] = p; // <20><>¼<EFBFBD><C2BC><EFBFBD>߳<EFBFBD>
current->index++; // <20><><EFBFBD><EFBFBD><EFBFBD>±<EFBFBD>++
p->process_or_thread = 1; // <20>´<EFBFBD><C2B4><EFBFBD><EFBFBD>߳<EFBFBD>
p->state = TASK_RUNNING; // <20><><EFBFBD>߳<EFBFBD>״̬<D7B4><CCAC><EFBFBD><EFBFBD>Ϊ<EFBFBD><CEAA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȴ<EFBFBD><C8B4><EFBFBD><EFBFBD><EFBFBD>
return nr; /*<2A><><EFBFBD><EFBFBD><EFBFBD>̺߳<DFB3>*/
}