system.c
来自「MINIX2.0操作系统源码 MINIX2.0操作系统源码」· C语言 代码 · 共 1,159 行 · 第 1/3 页
C
1,159 行
/* This task handles the interface between file system and kernel as well as
* between memory manager and kernel. System services are obtained by sending
* sys_task() a message specifying what is needed. To make life easier for
* MM and FS, a library is provided with routines whose names are of the
* form sys_xxx, e.g. sys_xit sends the SYS_XIT message to sys_task. The
* message types and parameters are:
*
* SYS_FORK informs kernel that a process has forked
* SYS_NEWMAP allows MM to set up a process memory map
* SYS_GETMAP allows MM to get a process' memory map
* SYS_EXEC sets program counter and stack pointer after EXEC
* SYS_XIT informs kernel that a process has exited
* SYS_GETSP caller wants to read out some process' stack pointer
* SYS_TIMES caller wants to get accounting times for a process
* SYS_ABORT MM or FS cannot go on; abort MINIX
* SYS_FRESH start with a fresh process image during EXEC (68000 only)
* SYS_SENDSIG send a signal to a process (POSIX style)
* SYS_SIGRETURN complete POSIX-style signalling
* SYS_KILL cause a signal to be sent via MM
* SYS_ENDSIG finish up after SYS_KILL-type signal
* SYS_COPY request a block of data to be copied between processes
* SYS_VCOPY request a series of data blocks to be copied between procs
* SYS_GBOOT copies the boot parameters to a process
* SYS_MEM returns the next free chunk of physical memory
* SYS_UMAP compute the physical address for a given virtual address
* SYS_TRACE request a trace operation
*
* Message types and parameters:
*
* m_type PROC1 PROC2 PID MEM_PTR
* ------------------------------------------------------
* | SYS_FORK | parent | child | pid | |
* |------------+---------+---------+---------+---------|
* | SYS_NEWMAP | proc nr | | | map ptr |
* |------------+---------+---------+---------+---------|
* | SYS_EXEC | proc nr | traced | new sp | |
* |------------+---------+---------+---------+---------|
* | SYS_XIT | parent | exitee | | |
* |------------+---------+---------+---------+---------|
* | SYS_GETSP | proc nr | | | |
* |------------+---------+---------+---------+---------|
* | SYS_TIMES | proc nr | | buf ptr | |
* |------------+---------+---------+---------+---------|
* | SYS_ABORT | | | | |
* |------------+---------+---------+---------+---------|
* | SYS_FRESH | proc nr | data_cl | | |
* |------------+---------+---------+---------+---------|
* | SYS_GBOOT | proc nr | | | bootptr |
* |------------+---------+---------+---------+---------|
* | SYS_GETMAP | proc nr | | | map ptr |
* ------------------------------------------------------
*
* m_type m1_i1 m1_i2 m1_i3 m1_p1
* ----------------+---------+---------+---------+--------------
* | SYS_VCOPY | src p | dst p | vec siz | vc addr |
* |---------------+---------+---------+---------+-------------|
* | SYS_SENDSIG | proc nr | | | smp |
* |---------------+---------+---------+---------+-------------|
* | SYS_SIGRETURN | proc nr | | | scp |
* |---------------+---------+---------+---------+-------------|
* | SYS_ENDSIG | proc nr | | | |
* -------------------------------------------------------------
*
* m_type m2_i1 m2_i2 m2_l1 m2_l2
* ------------------------------------------------------
* | SYS_TRACE | proc_nr | request | addr | data |
* ------------------------------------------------------
*
*
* m_type m6_i1 m6_i2 m6_i3 m6_f1
* ------------------------------------------------------
* | SYS_KILL | proc_nr | sig | | |
* ------------------------------------------------------
*
*
* m_type m5_c1 m5_i1 m5_l1 m5_c2 m5_i2 m5_l2 m5_l3
* --------------------------------------------------------------------------
* | SYS_COPY |src seg|src proc|src vir|dst seg|dst proc|dst vir| byte ct |
* --------------------------------------------------------------------------
* | SYS_UMAP | seg |proc nr |vir adr| | | | byte ct |
* --------------------------------------------------------------------------
*
*
* m_type m1_i1 m1_i2 m1_i3
* |------------+----------+----------+----------
* | SYS_MEM | mem base | mem size | tot mem |
* ----------------------------------------------
*
* In addition to the main sys_task() entry point, there are 5 other minor
* entry points:
* cause_sig: take action to cause a signal to occur, sooner or later
* inform: tell MM about pending signals
* numap: umap D segment starting from process number instead of pointer
* umap: compute the physical address for a given virtual address
* alloc_segments: allocate segments for 8088 or higher processor
*/
#include "kernel.h"
#include <signal.h>
#include <unistd.h>
#include <sys/sigcontext.h>
#include <sys/ptrace.h>
#include <minix/boot.h>
#include <minix/callnr.h>
#include <minix/com.h>
#include "proc.h"
#if (CHIP == INTEL)
#include "protect.h"
#endif
/* PSW masks. */
#define IF_MASK 0x00000200
#define IOPL_MASK 0x003000
PRIVATE message m;
FORWARD _PROTOTYPE( int do_abort, (message *m_ptr) );
FORWARD _PROTOTYPE( int do_copy, (message *m_ptr) );
FORWARD _PROTOTYPE( int do_exec, (message *m_ptr) );
FORWARD _PROTOTYPE( int do_fork, (message *m_ptr) );
FORWARD _PROTOTYPE( int do_gboot, (message *m_ptr) );
FORWARD _PROTOTYPE( int do_getsp, (message *m_ptr) );
FORWARD _PROTOTYPE( int do_kill, (message *m_ptr) );
FORWARD _PROTOTYPE( int do_mem, (message *m_ptr) );
FORWARD _PROTOTYPE( int do_newmap, (message *m_ptr) );
FORWARD _PROTOTYPE( int do_sendsig, (message *m_ptr) );
FORWARD _PROTOTYPE( int do_sigreturn, (message *m_ptr) );
FORWARD _PROTOTYPE( int do_endsig, (message *m_ptr) );
FORWARD _PROTOTYPE( int do_times, (message *m_ptr) );
FORWARD _PROTOTYPE( int do_trace, (message *m_ptr) );
FORWARD _PROTOTYPE( int do_umap, (message *m_ptr) );
FORWARD _PROTOTYPE( int do_xit, (message *m_ptr) );
FORWARD _PROTOTYPE( int do_vcopy, (message *m_ptr) );
FORWARD _PROTOTYPE( int do_getmap, (message *m_ptr) );
#if (SHADOWING == 1)
FORWARD _PROTOTYPE( int do_fresh, (message *m_ptr) );
#endif
/*===========================================================================*
* sys_task *
*===========================================================================*/
PUBLIC void sys_task()
{
/* Main entry point of sys_task. Get the message and dispatch on type. */
register int r;
while (TRUE) {
receive(ANY, &m);
switch (m.m_type) { /* which system call */
case SYS_FORK: r = do_fork(&m); break;
case SYS_NEWMAP: r = do_newmap(&m); break;
case SYS_GETMAP: r = do_getmap(&m); break;
case SYS_EXEC: r = do_exec(&m); break;
case SYS_XIT: r = do_xit(&m); break;
case SYS_GETSP: r = do_getsp(&m); break;
case SYS_TIMES: r = do_times(&m); break;
case SYS_ABORT: r = do_abort(&m); break;
#if (SHADOWING == 1)
case SYS_FRESH: r = do_fresh(&m); break;
#endif
case SYS_SENDSIG: r = do_sendsig(&m); break;
case SYS_SIGRETURN: r = do_sigreturn(&m); break;
case SYS_KILL: r = do_kill(&m); break;
case SYS_ENDSIG: r = do_endsig(&m); break;
case SYS_COPY: r = do_copy(&m); break;
case SYS_VCOPY: r = do_vcopy(&m); break;
case SYS_GBOOT: r = do_gboot(&m); break;
case SYS_MEM: r = do_mem(&m); break;
case SYS_UMAP: r = do_umap(&m); break;
case SYS_TRACE: r = do_trace(&m); break;
default: r = E_BAD_FCN;
}
m.m_type = r; /* 'r' reports status of call */
send(m.m_source, &m); /* send reply to caller */
}
}
/*===========================================================================*
* do_fork *
*===========================================================================*/
PRIVATE int do_fork(m_ptr)
register message *m_ptr; /* pointer to request message */
{
/* Handle sys_fork(). m_ptr->PROC1 has forked. The child is m_ptr->PROC2. */
#if (CHIP == INTEL)
reg_t old_ldt_sel;
#endif
register struct proc *rpc;
struct proc *rpp;
if (!isoksusern(m_ptr->PROC1) || !isoksusern(m_ptr->PROC2))
return(E_BAD_PROC);
rpp = proc_addr(m_ptr->PROC1);
rpc = proc_addr(m_ptr->PROC2);
/* Copy parent 'proc' struct to child. */
#if (CHIP == INTEL)
old_ldt_sel = rpc->p_ldt_sel; /* stop this being obliterated by copy */
#endif
*rpc = *rpp; /* copy 'proc' struct */
#if (CHIP == INTEL)
rpc->p_ldt_sel = old_ldt_sel;
#endif
rpc->p_nr = m_ptr->PROC2; /* this was obliterated by copy */
#if (SHADOWING == 0)
rpc->p_flags |= NO_MAP; /* inhibit the process from running */
#endif
rpc->p_flags &= ~(PENDING | SIG_PENDING | P_STOP);
/* Only 1 in group should have PENDING, child does not inherit trace status*/
sigemptyset(&rpc->p_pending);
rpc->p_pendcount = 0;
rpc->p_pid = m_ptr->PID; /* install child's pid */
rpc->p_reg.retreg = 0; /* child sees pid = 0 to know it is child */
rpc->user_time = 0; /* set all the accounting times to 0 */
rpc->sys_time = 0;
rpc->child_utime = 0;
rpc->child_stime = 0;
#if (SHADOWING == 1)
rpc->p_nflips = 0;
mkshadow(rpp, (phys_clicks)m_ptr->m1_p1); /* run child first */
#endif
return(OK);
}
/*===========================================================================*
* do_newmap *
*===========================================================================*/
PRIVATE int do_newmap(m_ptr)
message *m_ptr; /* pointer to request message */
{
/* Handle sys_newmap(). Fetch the memory map from MM. */
register struct proc *rp;
phys_bytes src_phys;
int caller; /* whose space has the new map (usually MM) */
int k; /* process whose map is to be loaded */
int old_flags; /* value of flags before modification */
struct mem_map *map_ptr; /* virtual address of map inside caller (MM) */
/* Extract message parameters and copy new memory map from MM. */
caller = m_ptr->m_source;
k = m_ptr->PROC1;
map_ptr = (struct mem_map *) m_ptr->MEM_PTR;
if (!isokprocn(k)) return(E_BAD_PROC);
rp = proc_addr(k); /* ptr to entry of user getting new map */
/* Copy the map from MM. */
src_phys = umap(proc_addr(caller), D, (vir_bytes) map_ptr, sizeof(rp->p_map));
if (src_phys == 0) panic("bad call to sys_newmap", NO_NUM);
phys_copy(src_phys, vir2phys(rp->p_map), (phys_bytes) sizeof(rp->p_map));
#if (SHADOWING == 0)
#if (CHIP != M68000)
alloc_segments(rp);
#else
pmmu_init_proc(rp);
#endif
old_flags = rp->p_flags; /* save the previous value of the flags */
rp->p_flags &= ~NO_MAP;
if (old_flags != 0 && rp->p_flags == 0) lock_ready(rp);
#endif
return(OK);
}
/*===========================================================================*
* do_getmap *
*===========================================================================*/
PRIVATE int do_getmap(m_ptr)
message *m_ptr; /* pointer to request message */
{
/* Handle sys_getmap(). Report the memory map to MM. */
register struct proc *rp;
phys_bytes dst_phys;
int caller; /* where the map has to be stored */
int k; /* process whose map is to be loaded */
struct mem_map *map_ptr; /* virtual address of map inside caller (MM) */
/* Extract message parameters and copy new memory map to MM. */
caller = m_ptr->m_source;
k = m_ptr->PROC1;
map_ptr = (struct mem_map *) m_ptr->MEM_PTR;
if (!isokprocn(k))
panic("do_getmap got bad proc: ", m_ptr->PROC1);
rp = proc_addr(k); /* ptr to entry of the map */
/* Copy the map to MM. */
dst_phys = umap(proc_addr(caller), D, (vir_bytes) map_ptr, sizeof(rp->p_map));
if (dst_phys == 0) panic("bad call to sys_getmap", NO_NUM);
phys_copy(vir2phys(rp->p_map), dst_phys, sizeof(rp->p_map));
return(OK);
}
/*===========================================================================*
* do_exec *
*===========================================================================*/
PRIVATE int do_exec(m_ptr)
register message *m_ptr; /* pointer to request message */
{
/* Handle sys_exec(). A process has done a successful EXEC. Patch it up. */
register struct proc *rp;
reg_t sp; /* new sp */
phys_bytes phys_name;
char *np;
#define NLEN (sizeof(rp->p_name)-1)
if (!isoksusern(m_ptr->PROC1)) return E_BAD_PROC;
/* PROC2 field is used as flag to indicate process is being traced */
if (m_ptr->PROC2) cause_sig(m_ptr->PROC1, SIGTRAP);
sp = (reg_t) m_ptr->STACK_PTR;
rp = proc_addr(m_ptr->PROC1);
rp->p_reg.sp = sp; /* set the stack pointer */
#if (CHIP == M68000)
rp->p_splow = sp; /* set the stack pointer low water */
#ifdef FPP
/* Initialize fpp for this process */
fpp_new_state(rp);
#endif
#endif
rp->p_reg.pc = (reg_t) m_ptr->IP_PTR; /* set pc */
rp->p_alarm = 0; /* reset alarm timer */
rp->p_flags &= ~RECEIVING; /* MM does not reply to EXEC call */
if (rp->p_flags == 0) lock_ready(rp);
/* Save command name for debugging, ps(1) output, etc. */
phys_name = numap(m_ptr->m_source, (vir_bytes) m_ptr->NAME_PTR,
(vir_bytes) NLEN);
if (phys_name != 0) {
phys_copy(phys_name, vir2phys(rp->p_name), (phys_bytes) NLEN);
for (np = rp->p_name; (*np & BYTE) >= ' '; np++) {}
*np = 0;
}
return(OK);
}
/*===========================================================================*
* do_xit *
*===========================================================================*/
PRIVATE int do_xit(m_ptr)
message *m_ptr; /* pointer to request message */
{
/* Handle sys_xit(). A process has exited. */
register struct proc *rp, *rc;
struct proc *np, *xp;
int parent; /* number of exiting proc's parent */
int proc_nr; /* number of process doing the exit */
phys_clicks base, size;
parent = m_ptr->PROC1; /* slot number of parent process */
proc_nr = m_ptr->PROC2; /* slot number of exiting process */
if (!isoksusern(parent) || !isoksusern(proc_nr)) return(E_BAD_PROC);
rp = proc_addr(parent);
rc = proc_addr(proc_nr);
lock();
rp->child_utime += rc->user_time + rc->child_utime; /* accum child times */
rp->child_stime += rc->sys_time + rc->child_stime;
unlock();
rc->p_alarm = 0; /* turn off alarm timer */
if (rc->p_flags == 0) lock_unready(rc);
#if (SHADOWING == 1)
rmshadow(rc, &base, &size);
m_ptr->m1_i1 = (int)base;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?