📄 process.c
字号:
int ret_code, error;
int org_stdin=0, org_stdout=0;
if (npz->filp[0] && npz->filp[0]->f_doshandle != 0) {
org_stdin = rm_dup(0);
rm_dup2(npz->filp[0]->f_doshandle, 0);
}
if (npz->filp[1] && npz->filp[1]->f_doshandle != 1) {
org_stdout = rm_dup(1);
rm_dup2(npz->filp[1]->f_doshandle, 1);
}
error = execute_realmode_prg(filename, argv, env, &ret_code);
if (org_stdin) {
rm_dup2(org_stdin, 0);
rm_close(org_stdin);
}
if (org_stdout) {
rm_dup2(org_stdout, 1);
rm_close(org_stdout);
}
if (error)
return doserror_to_errno(ret_code);
else {
EAX = (long) ret_code & 0xff; /* return value */
current_pid++;
return 0;
}
}
static void copy_filedescriptors(NEWPROCESS * father, NEWPROCESS * child)
{
int i;
for (i = 0; i < N_FILES; i++)
if (father->filp[i]) {
child->filp[i] = father->filp[i];
child->filp[i]->f_count ++;
}
}
struct StubInfo {
BYTE magic[16];
DWORD struct_length;
char go32[16];
BYTE need_version[4];
DWORD min_stack;
DWORD keep_on_spawn;
BYTE file_to_run[15];
BYTE enable_globbing;
DWORD free_conv_memory;
} stub_info = {
"StubInfoMagic!!",
sizeof(struct StubInfo),
"RSX",
{ 0,'b',0,4 },
262144L,
0L,
"",
0,
0L
};
struct {
DWORD size_structure;
DWORD linaddr_primary_screen;
DWORD linaddr_secondary_screen;
DWORD linaddr_transfer_buffer;
DWORD size_transfer_buffer; /* >= 4k */
DWORD pid;
BYTE master_pic;
BYTE slave_pic;
WORD selector_linear_memory;
DWORD linaddr_stubinfo;
DWORD linaddr_org_psp;
WORD run_mode;
WORD run_mode_info;
} go32_info_block;
static void set_go32_info_block()
{
go32_info_block.size_structure = sizeof(go32_info_block);
go32_info_block.linaddr_primary_screen = 0xB0000;
go32_info_block.linaddr_secondary_screen = 0xB8000;
go32_info_block.linaddr_transfer_buffer =
(((DWORD) ds16real << 4) + (DWORD) (UINT) iobuf) + 4096L;
go32_info_block.size_transfer_buffer = 4096L;
go32_info_block.pid = 42;
go32_info_block.master_pic = 8;
go32_info_block.slave_pic = 70;
go32_info_block.selector_linear_memory = dosmem_sel;
go32_info_block.linaddr_stubinfo =
((DWORD) ds16real << 4) + (DWORD) (UINT) & stub_info;
go32_info_block.linaddr_org_psp =
((DWORD) cs16real << 4);
go32_info_block.run_mode = 3;
go32_info_block.run_mode_info = 0x090;
}
/*
** load, init and switch to another 32bit program
*/
int exec32(unsigned mode, char *name, int argc, char **argp, int envc, char **envp)
{
NEWPROCESS *child, *father;
int i, ret;
#ifdef CONFIG_KDEB
static kernel_trace = 0;
ret = strlen(name);
if (opt_kdeb && ret >= 9 && strcmp(name+(ret-9), "rsx.emx") == 0) {
if (*kdeb_program) {
name = kdeb_program;
kernel_trace = 1;
printf("KERNEL DEBUG MODE with second prg %s\n", name);
}
else {
printf("KERNEL DEBUG MODE (but no second prg)\n");
return EMX_EINVAL;
}
}
#endif
/* if no wait, free last process */
if (!opt_schedule)
sys_wait((unsigned *)&ret);
/* look for a empty slot */
child = find_empty_process();
if (child == NULL)
return EMX_EAGAIN;
/* try load a a.out program */
if ((ret = load_protected_program(name, child)) != 0) {
child->p_status = PS_EMPTY;
return ret;
}
if (!(child->kstack = alloc_kernel_stack())) {
puts("no kernel stack");
child->p_status = PS_EMPTY;
return EMX_EAGAIN;
}
cpy_exename_to_stack(child, name);
/* copy arguments,environment */
argvenv(argc, argp, envc, envp, child);
/* setup new process table */
child->pid = current_pid++;
child->pptr = npz;
if (mode == P_DEBUG)
child->p_flags |= PF_DEBUG;
/* start values */
child->regs.eip = child->entry;
child->regs.esporg = child->stackp32;
child->regs.esp = child->stackp32 - 12L; /* iret frame */
/* for DJGPP: first MB */
child->regs.eax = ((DWORD) dosmem_sel << 16) | 0x00007008L;
child->regs.ebx = 0;
child->regs.ecx = 0;
child->regs.edx = ((DWORD) ds16real << 4) + (DWORD) (UINT) &go32_info_block;
child->regs.esi = 0;
child->regs.edi = 0;
child->regs.ebp = 0;
child->regs.cs = child->code32sel;
child->regs.ds = child->data32sel;
child->regs.es = child->data32sel;
if (opt_stack || (child->p_flags & PF_USEDPMI10))
child->regs.ss = child->data32sel;
else
child->regs.ss = child->data32sel + sel_incr;
child->regs.fs = child->data32sel;
child->regs.gs = dosmem_sel;
child->regs.eflags = 0x3202;
child->time_tic = time_tic;
npz->cptr = child;
if (child->p_flags & PF_DJGPP_FILE)
set_go32_info_block();
copy_filedescriptors(npz, child);
father = npz;
npz = child;
for (i=0; i<N_FILES; i++)
if (FD_ISSET(i, &father->close_on_exec))
sys_close(i);
npz = father;
/* if current prg extender, switch to first emx-porgram */
if (npz->p_flags & PF_EXTENDER) {
djio_init(); /* before first prg, init djio */
child->p_status = PS_RUN;
switch_context(child);
shut_down(0); /* should never execute */
}
#ifdef CONFIG_KDEB
if (opt_kdeb && kernel_trace == 1) {
EAX = child->pid = 1;
child->p_status = PS_STOP;
RSX_PROCESS.cptr = child;
RSX_PROCESS.regs.eip = 0x10000;
RSX_PROCESS.regs.esp = (DWORD) & ret;
}
#endif
if (mode == P_WAIT) {
MarkPageDemand(npz->memaddress, npz->membytes);
npz->p_status = PS_STOP;
child->p_status = PS_RUN;
switch_context(child);
npz->p_status = PS_RUN;
EFLAGS &= ~1L;
if (child->wait_return & 0xFF) /* signal */
EAX = 3;
else
EAX = (child->wait_return >> 8) & 0xFF;
}
else if (mode == P_NOWAIT) {
child->p_status = PS_RUN;
if (!opt_schedule)
switch_context(child);
EFLAGS &= ~1L;
EAX = (DWORD) child->pid;
} else if (mode == P_DEBUG) {
EAX = child->pid; /* return process no */
child->p_status = PS_STOP;
} else if (mode == P_OVERLAY) {
NEWPROCESS *this = npz;
npz->p_flags &= ~PF_MATH_USED; /* don't save mathe state */
switch_to_process(npz->pptr); /* switch to parent */
free_process(this); /* free process memory */
clean_processtable(this); /* free process table */
npz->cptr = child; /* new child */
child->pptr = npz; /* new parent */
switch_to_process(child); /* switch to new child */
npz->p_status = PS_RUN;
} else
return EMX_EINVAL;
return 0;
}
/*
** fork current process
*/
int sys_fork(void)
{
NEWPROCESS *child;
WORD child_stack32sel;
int pid;
child = find_empty_process();
if (child == NULL)
return -EMX_EAGAIN;
/* copy process tables */
memcpy(child, npz, sizeof(NEWPROCESS));
child->p_status = PS_EMPTY; /* if error, leave empty */
if (!(child->kstack = alloc_kernel_stack())) {
puts("no kernel stack");
return -EMX_EAGAIN;
}
/* MEMORY per DPMI besorgen */
if (child->p_flags & PF_USEDPMI10) {
if (AllocLinearMemory(npz->membytes, 0L, 0L, &child->memhandle, &child->memaddress))
return -EMX_ENOMEM;
} else {
if (AllocMem(npz->membytes, &child->memhandle, &child->memaddress))
return -EMX_ENOMEM;
}
if (AllocLDT(3, &(child->code32sel))) {
FreeMem(child->memhandle);
return -EMX_EIO;
}
child->data32sel = child->code32sel + sel_incr;
child_stack32sel = child->data32sel;
child_stack32sel += sel_incr;
SetBaseAddress(child->code32sel, child->memaddress);
SetBaseAddress(child->data32sel, child->memaddress);
SetBaseAddress(child_stack32sel, child->memaddress);
SetAccess(child->code32sel, APP_CODE_SEL, DEFAULT_BIT | GRANULAR_BIT);
SetAccess(child->data32sel, APP_DATA_SEL, DEFAULT_BIT | GRANULAR_BIT);
SetAccess(child_stack32sel, APP_DATA_SEL | EXPAND_BIT, BIG_BIT | GRANULAR_BIT);
SetLimit(child->code32sel, lsl32(npz->code32sel));
SetLimit(child->data32sel, lsl32(npz->data32sel));
SetLimit(child_stack32sel, lsl32(SS));
child->regs.cs = child->code32sel;
child->regs.ds = child->data32sel;
child->regs.es = child->data32sel;
if (!opt_stack && !(child->p_flags & PF_USEDPMI10))
child->regs.ss = child_stack32sel;
else
child->regs.ss = child->data32sel;
child->regs.fs = child->data32sel;
child->regs.gs = dosmem_sel;/* first Megabyte DOS */
pid = child->pid = current_pid++;
child->pptr = npz;
child->cptr = NULL;
child->time_alarm = 0;
child->time_tic = time_tic;
child->filehandle = 0; /* for swapper !! */
child->entry = child->regs.eip; /* for switch_context !! */
npz->cptr = child;
copy_filedescriptors(npz, child);
/* text segment */
cpy32_32(npz->data32sel, npz->text_start,
child->data32sel, child->text_start,
npz->text_end - npz->text_start);
/* data/bss segment */
cpy32_32(npz->data32sel, npz->data_start,
child->data32sel, child->data_start,
npz->data_end - npz->data_start);
/* heap segment */
cpy32_32(npz->data32sel, npz->init_brk,
child->data32sel, child->init_brk,
npz->brk_value - npz->init_brk);
/* stack segment */
cpy32_32(npz->data32sel, ESP,
child->data32sel, ESP,
npz->stack_top - ESP);
/* child returns null */
child->regs.ecx = 0;
child->regs.eax = 0;
child->p_status = PS_RUN;
switch_context(child);
return pid;
}
/*
** global clean-up for extender
*/
void shut_down(int exit_code)
{
NEWPROCESS *p;
/* free memory,selectors */
for (p = &FIRST_PROCESS; p != NULL && p <= &LAST_PROCESS; p++)
free_process(p);
if (opt_printall)
printf("clock: %lu ticks = %lu sec\n", time_tic, time_tic * 10 / 182);
#ifdef CONFIG_KDEB
if (opt_kdeb)
KDEB_disable_breakpoints();
#endif
/* clean_up ints,exceptions,... */
clean_up();
/* leave protected mode */
protected_to_real(exit_code);
}
/*
** get more memory from DPMI-Server
*/
DWORD getmem(DWORD bytes, NEWPROCESS * p)
{ /* ret: old break value */
DWORD retv, pagealign;
DWORD newaddress, newhandle;
if (bytes <= p->pagefree) {
retv = p->brk_value;
p->brk_value += bytes;
p->pagefree -= bytes;
} else {
if (p->p_flags & PF_DJGPP_FILE)
pagealign = (bytes + 0xFFFF) & 0xFFFF0000L;
else
pagealign = (bytes + 0xFFF) & 0xFFFFF000L;
if (ResizeMem(p->membytes + pagealign, p->memhandle,
&newhandle, &newaddress))
return -1L;
p->membytes += pagealign;
retv = p->brk_value;
p->brk_value += bytes;
p->pagefree += (pagealign - bytes);
if (!opt_memaccess && !(p->options & OPT_MEMACCESS))
SetLimit(p->data32sel, p->membytes - 1);
if (p->memhandle != newhandle) {
p->memhandle = newhandle;
}
if (p->memaddress != newaddress) {
p->memaddress = newaddress;
SetBaseAddress(p->code32sel, p->memaddress);
SetBaseAddress(p->data32sel, p->memaddress);
SetBaseAddress(p->data32sel + sel_incr, p->memaddress);
if (opt_memaccess && opt_printall)
puts("warning: memaccess pointer is not valid");
}
/* dammed! djgpp (gcc.exe) cause gp-fault, if not */
if ((p->p_flags & PF_DJGPP_FILE) || opt_zero)
bzero32(p->data32sel, retv, pagealign);
}
return retv;
}
/*
** exit process and switch to father
*/
int do_exit4c(int bysig)
{
NEWPROCESS *father;
int i;
unsigned retval;
retval = AX & 0xFF;
/* close all files */
for (i = 0; i <= N_FILES; i++)
if (npz->filp[i])
sys_close(i);
/* get parent */
father = npz->pptr;
npz->wait_return = (bysig) ? bysig : retval << 8;
npz->p_status = PS_ZOMBIE;
npz->p_flags |= PF_WAIT_WAIT; /* allow wait() for father */
npz->p_flags &= ~PF_MATH_USED; /* don't save mathe state */
free_process(npz);
free_kernel_stack(npz->kstack);
/* if father process is Extender */
if (father->p_flags & PF_EXTENDER)
shut_down(retval);
if (father->p_status == PS_WAIT)
father->p_status = PS_RUN;
send_signal(father, SIGCLD);
switch_context(father);
puts("RSX: end of do_exit4c() should never reached");
shut_down(0);
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -