⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 system.c

📁 操作系统课程设计 在minix3下实现实时进程
💻 C
📖 第 1 页 / 共 2 页
字号:
/* 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 + -