📄 main.c
字号:
/* This file contains the main program of the process manager and some related * procedures. When MINIX starts up, the kernel runs for a little while, * initializing itself and its tasks, and then it runs PM and FS. Both PM * and FS initialize themselves as far as they can. PM asks the kernel for * all free memory and starts serving requests. * * The entry points into this file are: * main: starts PM running * setreply: set the reply to be sent to process making an PM system call */#include "pm.h"#include <minix/keymap.h>#include <minix/callnr.h>#include <minix/com.h>#include <signal.h>#include <stdlib.h>#include <fcntl.h>#include <sys/resource.h>#include <string.h>#include "mproc.h"#include "param.h"#include "../../kernel/const.h"#include "../../kernel/config.h"#include "../../kernel/type.h"#include "../../kernel/proc.h"FORWARD _PROTOTYPE( void get_work, (void) );FORWARD _PROTOTYPE( void pm_init, (void) );FORWARD _PROTOTYPE( int get_nice_value, (int queue) );FORWARD _PROTOTYPE( void get_mem_chunks, (struct memory *mem_chunks) );FORWARD _PROTOTYPE( void patch_mem_chunks, (struct memory *mem_chunks, struct mem_map *map_ptr) );#define click_to_round_k(n) \ ((unsigned) ((((unsigned long) (n) << CLICK_SHIFT) + 512) / 1024))/*===========================================================================* * main * *===========================================================================*/PUBLIC int main(){/* Main routine of the process manager. */ int result, s, proc_nr; struct mproc *rmp; sigset_t sigset; pm_init(); /* initialize process manager tables */ /* This is PM's main loop- get work and do it, forever and forever. */ while (TRUE) { get_work(); /* wait for an PM system call */ /* Check for system notifications first. Special cases. */ if (call_nr == SYN_ALARM) { pm_expire_timers(m_in.NOTIFY_TIMESTAMP); result = SUSPEND; /* don't reply */ } else if (call_nr == SYS_SIG) { /* signals pending */ sigset = m_in.NOTIFY_ARG; if (sigismember(&sigset, SIGKSIG)) (void) ksig_pending(); result = SUSPEND; /* don't reply */ } /* Else, if the system call number is valid, perform the call. */ else if ((unsigned) call_nr >= NCALLS) { result = ENOSYS; } else { result = (*call_vec[call_nr])(); } /* Send the results back to the user to indicate completion. */ if (result != SUSPEND) setreply(who, result); swap_in(); /* maybe a process can be swapped in? */ /* Send out all pending reply messages, including the answer to * the call just made above. The processes must not be swapped out. */ for (proc_nr=0, rmp=mproc; proc_nr < NR_PROCS; proc_nr++, rmp++) { /* In the meantime, the process may have been killed by a * signal (e.g. if a lethal pending signal was unblocked) * without the PM realizing it. If the slot is no longer in * use or just a zombie, don't try to reply. */ if ((rmp->mp_flags & (REPLY | ONSWAP | IN_USE | ZOMBIE)) == (REPLY | IN_USE)) { if ((s=send(proc_nr, &rmp->mp_reply)) != OK) { panic(__FILE__,"PM can't reply to", proc_nr); } rmp->mp_flags &= ~REPLY; } } } return(OK);}/*===========================================================================* * get_work * *===========================================================================*/PRIVATE void get_work(){/* Wait for the next message and extract useful information from it. */ if (receive(ANY, &m_in) != OK) panic(__FILE__,"PM receive error", NO_NUM); who = m_in.m_source; /* who sent the message */ call_nr = m_in.m_type; /* system call number */ /* Process slot of caller. Misuse PM's own process slot if the kernel is * calling. This can happen in case of synchronous alarms (CLOCK) or or * event like pending kernel signals (SYSTEM). */ mp = &mproc[who < 0 ? PM_PROC_NR : who];}/*===========================================================================* * setreply * *===========================================================================*/PUBLIC void setreply(proc_nr, result)int proc_nr; /* process to reply to */int result; /* result of call (usually OK or error #) */{/* Fill in a reply message to be sent later to a user process. System calls * may occasionally fill in other fields, this is only for the main return * value, and for setting the "must send reply" flag. */ register struct mproc *rmp = &mproc[proc_nr]; rmp->mp_reply.reply_res = result; rmp->mp_flags |= REPLY; /* reply pending */ if (rmp->mp_flags & ONSWAP) swap_inqueue(rmp); /* must swap this process back in */}/*===========================================================================* * pm_init * *===========================================================================*/PRIVATE void pm_init(){/* Initialize the process manager. * Memory use info is collected from the boot monitor, the kernel, and * all processes compiled into the system image. Initially this information * is put into an array mem_chunks. Elements of mem_chunks are struct memory, * and hold base, size pairs in units of clicks. This array is small, there * should be no more than 8 chunks. After the array of chunks has been built * the contents are used to initialize the hole list. Space for the hole list * is reserved as an array with twice as many elements as the maximum number * of processes allowed. It is managed as a linked list, and elements of the * array are struct hole, which, in addition to storage for a base and size in * click units also contain space for a link, a pointer to another element.*/ int s; static struct boot_image image[NR_BOOT_PROCS]; register struct boot_image *ip; static char core_sigs[] = { SIGQUIT, SIGILL, SIGTRAP, SIGABRT, SIGEMT, SIGFPE, SIGUSR1, SIGSEGV, SIGUSR2 }; static char ign_sigs[] = { SIGCHLD, SIGWINCH }; static char mess_sigs[] = { SIGTERM, SIGHUP, SIGABRT, SIGQUIT }; register struct mproc *rmp; register int i; register char *sig_ptr; phys_clicks total_clicks, minix_clicks, free_clicks; message mess; struct mem_map mem_map[NR_LOCAL_SEGS]; struct memory mem_chunks[NR_MEMS]; /* Initialize process table, including timers. */ for (rmp=&mproc[0]; rmp<&mproc[NR_PROCS]; rmp++) { tmr_inittimer(&rmp->mp_timer); } /* Build the set of signals which cause core dumps, and the set of signals * that are by default ignored. */ sigemptyset(&core_sset); for (sig_ptr = core_sigs; sig_ptr < core_sigs+sizeof(core_sigs); sig_ptr++) sigaddset(&core_sset, *sig_ptr); sigemptyset(&ign_sset); for (sig_ptr = ign_sigs; sig_ptr < ign_sigs+sizeof(ign_sigs); sig_ptr++) sigaddset(&ign_sset, *sig_ptr); /* Obtain a copy of the boot monitor parameters and the kernel info struct. * Parse the list of free memory chunks. This list is what the boot monitor * reported, but it must be corrected for the kernel and system processes. */ if ((s=sys_getmonparams(monitor_params, sizeof(monitor_params))) != OK) panic(__FILE__,"get monitor params failed",s); get_mem_chunks(mem_chunks); if ((s=sys_getkinfo(&kinfo)) != OK) panic(__FILE__,"get kernel info failed",s); /* Get the memory map of the kernel to see how much memory it uses. */ if ((s=get_mem_map(SYSTASK, mem_map)) != OK) panic(__FILE__,"couldn't get memory map of SYSTASK",s); minix_clicks = (mem_map[S].mem_phys+mem_map[S].mem_len)-mem_map[T].mem_phys; patch_mem_chunks(mem_chunks, mem_map); /* Initialize PM's process table. Request a copy of the system image table
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -