📄 system.c
字号:
/* This task handles the interface between the kernel and user-level servers. * System services can be accessed by doing a system call. System calls are * transformed into request messages, which are handled by this task. By * convention, a sys_call() is transformed in a SYS_CALL request message that * is handled in a function named do_call(). * * A private call vector is used to map all system calls to the functions that * handle them. The actual handler functions are contained in separate files * to keep this file clean. The call vector is used in the system task's main * loop to handle all incoming requests. * * In addition to the main sys_task() entry point, which starts the main loop, * there are several other minor entry points: * get_priv: assign privilege structure to user or system process * send_sig: send a signal directly to a system process * cause_sig: take action to cause a signal to occur via PM * umap_local: map virtual address in LOCAL_SEG to physical * umap_remote: map virtual address in REMOTE_SEG to physical * umap_bios: map virtual address in BIOS_SEG to physical * virtual_copy: copy bytes from one virtual address to another * get_randomness: accumulate randomness in a buffer * * Changes: * Aug 04, 2005 check if system call is allowed (Jorrit N. Herder) * Jul 20, 2005 send signal to services with message (Jorrit N. Herder) * Jan 15, 2005 new, generalized virtual copy function (Jorrit N. Herder) * Oct 10, 2004 dispatch system calls from call vector (Jorrit N. Herder) * Sep 30, 2004 source code documentation updated (Jorrit N. Herder) */#include "kernel.h"#include "system.h"#include <stdlib.h>#include <signal.h>#include <unistd.h>#include <sys/sigcontext.h>#if (CHIP == INTEL)#include <ibm/memory.h>#include "protect.h"#endif/* Declaration of the call vector that defines the mapping of system calls * to handler functions. The vector is initialized in sys_init() with map(), * which makes sure the system call numbers are ok. No space is allocated, * because the dummy is declared extern. If an illegal call is given, the * array size will be negative and this won't compile. */PUBLIC int (*call_vec[NR_SYS_CALLS])(message *m_ptr);#define map(call_nr, handler) \ {extern int dummy[NR_SYS_CALLS>(unsigned)(call_nr-KERNEL_CALL) ? 1:-1];} \ call_vec[(call_nr-KERNEL_CALL)] = (handler) FORWARD _PROTOTYPE( void initialize, (void));/*===========================================================================* * sys_task * *===========================================================================*/PUBLIC void sys_task(){/* Main entry point of sys_task. Get the message and dispatch on type. */ static message m; register int result; register struct proc *caller_ptr; unsigned int call_nr; int s; /* Initialize the system task. */ initialize(); while (TRUE) { /* Get work. Block and wait until a request message arrives. */ receive(ANY, &m); call_nr = (unsigned) m.m_type - KERNEL_CALL; caller_ptr = proc_addr(m.m_source); /* See if the caller made a valid request and try to handle it. */ if (! (priv(caller_ptr)->s_call_mask & (1<<call_nr))) {#if DEBUG_ENABLE_IPC_WARNINGS kprintf("SYSTEM: request %d from %d denied.\n", call_nr,m.m_source);#endif result = ECALLDENIED; /* illegal message type */ } else if (call_nr >= NR_SYS_CALLS) { /* check call number */#if DEBUG_ENABLE_IPC_WARNINGS kprintf("SYSTEM: illegal request %d from %d.\n", call_nr,m.m_source);#endif result = EBADREQUEST; /* illegal message type */ } else { result = (*call_vec[call_nr])(&m); /* handle the system call */ } /* Send a reply, unless inhibited by a handler function. Use the kernel * function lock_send() to prevent a system call trap. The destination * is known to be blocked waiting for a message. */ if (result != EDONTREPLY) { m.m_type = result; /* report status of call */ if (OK != (s=lock_send(m.m_source, &m))) { kprintf("SYSTEM, reply to %d failed: %d\n", m.m_source, s); } } }}/*===========================================================================* * initialize * *===========================================================================*/PRIVATE void initialize(void){ register struct priv *sp; int i; /* Initialize IRQ handler hooks. Mark all hooks available. */ for (i=0; i<NR_IRQ_HOOKS; i++) { irq_hooks[i].proc_nr = NONE; } /* Initialize all alarm timers for all processes. */ for (sp=BEG_PRIV_ADDR; sp < END_PRIV_ADDR; sp++) { tmr_inittimer(&(sp->s_alarm_timer)); } /* Initialize the call vector to a safe default handler. Some system calls * may be disabled or nonexistant. Then explicitely map known calls to their * handler functions. This is done with a macro that gives a compile error * if an illegal call number is used. The ordering is not important here. */ for (i=0; i<NR_SYS_CALLS; i++) { call_vec[i] = do_unused; } /* Process management. */ map(SYS_FORK, do_fork); /* a process forked a new process */ map(SYS_EXEC, do_exec); /* update process after execute */ map(SYS_EXIT, do_exit); /* clean up after process exit */ map(SYS_NICE, do_nice); /* set scheduling priority */ map(SYS_PRIVCTL, do_privctl); /* system privileges control */ map(SYS_TRACE, do_trace); /* request a trace operation */ /* Signal handling. */ map(SYS_KILL, do_kill); /* cause a process to be signaled */ map(SYS_GETKSIG, do_getksig); /* PM checks for pending signals */ map(SYS_ENDKSIG, do_endksig); /* PM finished processing signal */ map(SYS_SIGSEND, do_sigsend); /* start POSIX-style signal */ map(SYS_SIGRETURN, do_sigreturn); /* return from POSIX-style signal */ /* Device I/O. */ map(SYS_IRQCTL, do_irqctl); /* interrupt control operations */ map(SYS_DEVIO, do_devio); /* inb, inw, inl, outb, outw, outl */ map(SYS_SDEVIO, do_sdevio); /* phys_insb, _insw, _outsb, _outsw */ map(SYS_VDEVIO, do_vdevio); /* vector with devio requests */ map(SYS_INT86, do_int86); /* real-mode BIOS calls */ /* Memory management. */ map(SYS_NEWMAP, do_newmap); /* set up a process memory map */ map(SYS_SEGCTL, do_segctl); /* add segment and get selector */ map(SYS_MEMSET, do_memset); /* write char to memory area */ /* Copying. */ map(SYS_UMAP, do_umap); /* map virtual to physical address */ map(SYS_VIRCOPY, do_vircopy); /* use pure virtual addressing */ map(SYS_PHYSCOPY, do_physcopy); /* use physical addressing */ map(SYS_VIRVCOPY, do_virvcopy); /* vector with copy requests */ map(SYS_PHYSVCOPY, do_physvcopy); /* vector with copy requests */ /* Clock functionality. */ map(SYS_TIMES, do_times); /* get uptime and process times */ map(SYS_SETALARM, do_setalarm); /* schedule a synchronous alarm */ /* System control. */ map(SYS_ABORT, do_abort); /* abort MINIX */ map(SYS_GETINFO, do_getinfo); /* request system information */ map(SYS_IOPENABLE, do_iopenable); /* Enable I/O */ map(SYS_CHRT, do_chrt); /* Enable I/O */}/*===========================================================================* * get_priv * *===========================================================================*/PUBLIC int get_priv(rc, proc_type)register struct proc *rc; /* new (child) process pointer */int proc_type; /* system or user process flag */{/* Get a privilege structure. All user processes share the same privilege * structure. System processes get their own privilege structure. */ register struct priv *sp; /* privilege structure */ if (proc_type == SYS_PROC) { /* find a new slot */ for (sp = BEG_PRIV_ADDR; sp < END_PRIV_ADDR; ++sp) if (sp->s_proc_nr == NONE && sp->s_id != USER_PRIV_ID) break; if (sp->s_proc_nr != NONE) return(ENOSPC); rc->p_priv = sp; /* assign new slot */ rc->p_priv->s_proc_nr = proc_nr(rc); /* set association */ rc->p_priv->s_flags = SYS_PROC; /* mark as privileged */ } else { rc->p_priv = &priv[USER_PRIV_ID]; /* use shared slot */ rc->p_priv->s_proc_nr = INIT_PROC_NR; /* set association */ rc->p_priv->s_flags = 0; /* no initial flags */ } return(OK);}/*===========================================================================* * get_randomness * *===========================================================================*/PUBLIC void get_randomness(source)int source;{/* On machines with the RDTSC (cycle counter read instruction - pentium * and up), use that for high-resolution raw entropy gathering. Otherwise, * use the realtime clock (tick resolution). * * Unfortunately this test is run-time - we don't want to bother with * compiling different kernels for different machines. * * On machines without RDTSC, we use read_clock(). */ int r_next; unsigned long tsc_high, tsc_low; source %= RANDOM_SOURCES; r_next= krandom.bin[source].r_next; if (machine.processor > 486) { read_tsc(&tsc_high, &tsc_low); krandom.bin[source].r_buf[r_next] = tsc_low; } else {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -