Minix(Mini UNIX)原來是荷蘭阿姆斯特丹的Vrije大學計算機科學系的Andrew S. Tanenbaum教授所發展的一個類Unix操做系統。算法
目前的Minix版本爲Minix 3,是一個免費、開源的操做系統,設計目標是實現高可靠性、靈活性及安全性。數組
其系統主要包括在覈心模式下運做的微核心和在用戶模式下做爲一系列獨立、受保護的進程運行的其他全部操做系統組件。安全
MINIX3自己就是一組進程的集合服務器
第一層的主要功能是爲上層驅動程序和服務器提供一組特權內核調用。進程都潛在具備必定特權,這是另外三層的不一樣之處。網絡
第二層擁有最多特權。第二層內的稱爲設備驅動程序(device driver)。數據結構
第三層包含了服務器,有兩個服務器不可少,進程管理器(Process Manager,PM)和文件系統(File System,FS),app
還有信息服務器(information server,IS),再生服務器(reincarnation server,RS),ide
在一個網絡操做系統上還可能有網絡服務器(network server,inet)。函數
如下是來自《現代操做系統》中對進程的一些描述
進程是對正在運行程序的一個抽象
進程本質是正在執行的一個程序
一個進程就是一個正在執行程序的實例,包括程序計數器、寄存器和變量的當前值this
kernel/proc.h定義了內核進程表,進程表中的每一項被定義爲一個proc進程:
struct proc { struct stackframe_s p_reg; /*process' registers saved in stack frame */ reg_t p_ldt_sel; /*selector in gdt with ldt base and limit */ struct segdesc_sp_ldt[2+NR_REMOTE_SEGS]; /* CS, DS and remote segments */ proc_n r_tp_nr; /* numberof this process (for fast access) */ struct priv *p_priv; /*system privileges structure */ char p_rts_flags; /*SENDING, RECEIVING, etc. */ char p_priority; /*current scheduling priority */ char p_max_priority; /*maximum scheduling priority */ char p_ticks_left; /*number of scheduling ticks left */ char p_quantum_size; /*quantum size in ticks */ struct mem_mapp_memmap[NR_LOCAL_SEGS]; /* memory map (T, D, S) */ clock_t p_user_time; /*user time in ticks */ clock_t p_sys_time; /*sys time in ticks */ struct proc *p_nextready; /*pointer to next ready process */ struct proc *p_caller_q; /*head of list of procs wishing to send */ struct proc *p_q_link; /*link to next proc wishing to send */ message* p_messbuf; /*pointer to passed message buffer */ proc_n r_tp_getfrom; /*from whom does process want to receive? */ proc_n r_tp_sendto; /* towhom does process want to send? */ sigset_t p_pending; /*bit map for pending kernel signals */ char p_name[P_NAME_LEN]; /*name of the process, including \0 */ };
每一項包括進程寄存器、棧指針、狀態值、內存映射、棧限制、進程號、計數值、alarm時間以及消息信息。
進程表自己被定義爲一個proc結構體的數組proc[NR_TASKS+NR_PROCS],
常量 NR_TASKS 在include/minix/com.h中被定義爲4,
常量 NR_PROCS 在include/minix/congfig.h中被定義爲64。
若是須要,NR_PROCS能夠更改,以建立一個可以處理更多進程的系統(如在一個大型服務器上)。
當進程被中斷(被輸入輸出設備或時鐘等),或進程執行軟中斷指令,或進程結束時,系統將決定接下來運行哪一個進程。
Minix的進程調度使用多級隊列,每一個隊列的優先級不一樣。
見 kernel/proc.h 中:
/* Scheduling priorities for p_priority. Values must start at zero (highest * priority) and increment. Priorities of the processes in the boot image * can be set in table.c. IDLE must have a queue for itself, to prevent low * priority user processes to run round-robin with IDLE. */ #define NR_SCHED_QUEUES 16 /* MUST equal minimum priority + 1 */ #define TASK_Q 0 /* highest, used for kernel tasks */ #define MAX_USER_Q 0 /* highest priority for user processes */ #define USER_Q 7 /* default (should correspond to nice 0) */ #define MIN_USER_Q 14 /* minimum priority for user processes */ #define IDLE_Q 15 /* lowest, only IDLE process goes here */
EXTERN struct proc *rdy_head[NR_SCHED_QUEUES]; /* ptrs to ready list headers */ EXTERN struct proc *rdy_tail[NR_SCHED_QUEUES]; /* ptrs to ready list tails */
服務進程所用的隊列一般比用戶進程所用的隊列優先級更高;而驅動進程所用的隊列一般比服務進程所用的隊列優先級更高;
而時鐘和系統任務使用的隊列,是全部隊列中優先級最高的。
見 /kernel/clock.c 中:
PRIVATE int clock_handler(hook) irq_hook_t *hook; { /* This executes on each clock tick (i.e., every time the timer chip generates * an interrupt). It does a little bit of work so the clock task does not have * to be called on every tick. The clock task is called when: * * (1) the scheduling quantum of the running process has expired, or ...... */ ...... /* Check if do_clocktick() must be called. Done for alarms and scheduling. ...... */ if ( ...... || (proc_ptr->p_ticks_left <= 0)) { prev_ptr = proc_ptr; /* store running process */ lock_notify(HARDWARE, CLOCK); /* send notification */ } ...... }
上面函數clock_handler()中的lock_notify()將致使下面的函數do_clocktick()被調用。
見 /kernel/clock.c 中:
PRIVATE int do_clocktick(m_ptr) message *m_ptr; /* pointer to request message */ { ...... /* A process used up a full quantum. The interrupt handler stored this * process in 'prev_ptr'. First make sure that the process is not on the * scheduling queues. Then announce the process ready again. Since it has * no more time left, it gets a new quantum and is inserted at the right * place in the queues. As a side-effect a new process will be scheduled. */ if (prev_ptr->p_ticks_left <= 0 && priv(prev_ptr)->s_flags & PREEMPTIBLE) { lock_dequeue(prev_ptr); /* take it off the queues */ lock_enqueue(prev_ptr); /* and reinsert it again */ } ...... }
上面函數do_clocktick()中的lock_enqueue()實際調用了下面的函數enqueue(),從而選擇下一個進程運行。
見 /kernel/proc.c 中:
PRIVATE void enqueue(rp) register struct proc *rp; /* this process is now runnable */ { /* Add 'rp' to one of the queues of runnable processes. This function is * responsible for inserting a process into one of the scheduling queues. * The mechanism is implemented here. The actual scheduling policy is * defined in sched() and pick_proc(). */ int q; /* scheduling queue to use */ int front; /* add to front or back */ /* Determine where to insert to process. */ sched(rp, &q, &front); /* Now add the process to the queue. */ if (rdy_head[q] == NIL_PROC) { /* add to empty queue */ rdy_head[q] = rdy_tail[q] = rp; /* create a new queue */ rp->p_nextready = NIL_PROC; /* mark new end */ } else if (front) { /* add to head of queue */ rp->p_nextready = rdy_head[q]; /* chain head of queue */ rdy_head[q] = rp; /* set new queue head */ } else { /* add to tail of queue */ rdy_tail[q]->p_nextready = rp; /* chain tail of queue */ rdy_tail[q] = rp; /* set new queue tail */ rp->p_nextready = NIL_PROC; /* mark new end */ } /* Now select the next process to run. */ pick_proc(); }
本文基於Minix3源代碼簡要的分析了Minix3的進程模型,其中主要包括:操做系統是怎麼組織進程的、 進程狀態如何轉換以及進程是如何調度的;
MINIX3 的進程調度仍是很是簡單的,調度算法是很是短小的,其目的就是體現 了一個簡單和高效的設計原則,固然簡單和高效其實很難並存,
總體而言,就是 一個多隊列調度算法,根據優先級來放到相應的位置。