对Minix3中进程模型的简要分析

简单介绍

Minix(Mini UNIX)原来是荷兰阿姆斯特丹的Vrije大学计算机科学系的Andrew S. Tanenbaum教授所发展的一个类Unix操作系统。

目前的Minix版本为Minix 3,是一个免费、开源的操作系统,设计目标是实现高可靠性、灵活性及安全性。

其系统主要包括在核心模式下运作的微核心和在用户模式下作为一系列独立、受保护的进程运行的其余所有操作系统组件。

Minix3的整体认识

MINIX3本身就是一组进程的集合

第一层的主要功能是为上层驱动程序和服务器提供一组特权内核调用。进程都潜在具有一定特权,这是另外三层的不同之处。

第二层拥有最多特权。第二层内的称为设备驱动程序(device driver)。

第三层包含了服务器,有两个服务器不可少,进程管理器(Process Manager,PM)和文件系统(File System,FS),

还有信息服务器(information server,IS),再生服务器(reincarnation server,RS),

在一个网络操作系统上还可能有网络服务器(network server,inet)。

Minix3是怎么组织进程

进程的定义

以下是来自《现代操作系统》中对进程的一些描述      
        进程是对正在运行程序的一个抽象
        进程本质是正在执行的一个程序
        一个进程就是一个正在执行程序的实例,包括程序计数器、寄存器和变量的当前值

进程的数据结构

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可以更改,以创建一个能够处理更多进程的系统(如在一个大型服务器上)。

进程状态如何转换

进程状态

一个进程从创建而产生至撤销而消亡的整个生命期间,

有时占有处理器执行,有时虽可运行但分不到处理器、有时虽有空闲处理器但因等待某个事件的发生而无法执行,

这一切都说明进程和程序不相同,它是活动的且有状态变化的,这可以用一组状态加以刻画。

为了便于管理进程,一般来说,按进程在执行过程中的不同情况至少要定义三种不同的进程状态:

  (1)运行(running)态:进程占有处理器正在运行。

  (2)就绪(ready)态:进程具备运行条件,等待系统分配处理器以便运行。

  (3)等待(wait)态:又称为阻塞(blocked)态或睡眠(sleep)态,指进程不具备运行条件,正在等待某个事件的完成。

进程状态转换

进程是如何调度的

当进程被中断(被输入输出设备或时钟等),或进程执行软中断指令,或进程结束时,系统将决定接下来运行哪个进程。

队列优先级

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的进程模型,其中主要包括:操作系统是怎么组织进程的、 进程状态如何转换以及进程是如何调度的;

MINIX3 的进程调度还是非常简单的,调度算法是非常短小的,其目的就是体现 了一个简单和高效的设计原则,当然简单和高效其实很难并存,

整体而言,就是 一个多队列调度算法,根据优先级来放到相应的位置。

原文地址:https://www.cnblogs.com/xiaoyufafeng/p/8976391.html

时间: 2024-08-29 05:16:30

对Minix3中进程模型的简要分析的相关文章

Android --- Zygote和System进程启动过程简要分析

Android --- Zygote和System进程启动过程简要分析 在看过<Android情景源代码>的Zygote启动章节后,作如下简要总结.Zygote进程在init进程启动过程中被以service服务的形式启动: service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server class main socket zygote stream 660 root syste

php守护进程创建和简要分析

守护进程可 由系统启动脚本 /etc/rc.local crontab任务, 用户shell 方式运行 具体概念可参考c的 进程守护化基本步骤 1.创建子进程,终止父进程 (pcntl_fork,exit) 2.在子进程中创建新会话 (posix_setsid) 3.改变工作目录(默认继承了父进程的当前工作目录) (chdir('/')) 4.重设文件掩码(默认继承了父进程的) (umask(0) 改变当前的umask为最宽松掩码) 5.关闭文件描述符(默认继承了父进程打开的文件描述符) (fc

oracle中的替换函数简要分析

replace就是一般意义上的字符串替换 replace(c1,c2[,c3]) 在字符串c1中找到字符串c2,替换成c3.若c3为空,则在c1中删除所有c2. update jd set id = replace(id,'1','2'); 含义就是将jd表中id列中的所有1换为2. translate只是一个字符替换对应的一个字符 TRANSLATE ( expr , from_string , to_string ) 简单的说就是对expr内容,用to_string中的字符逐一替换from_

linux中curl指令的简要分析

curl是一种命令行工具,作用是发出网络请求,然后得到和提取数据,显示在"标准输出"(stdout)上面. 它支持多种协议,下面举例讲解如何将它用于网站开发. 一.查看网页源码 直接在curl命令后加上网址,就可以看到网页源码.我们以网址www.sina.com为例(选择该网址,主要因为它的网页代码较短): $ curl www.sina.com <!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN"> <

SEAndroid安全机制中的进程安全上下文关联分析

前面一篇文章分析了文件安全上下文关联过程.但是在SEAndroid中,除了要给文件关联安全上下文外,还需要给进程关联安全上下文,因为只有当进程和文件都关联安全上下文之后,SEAndroid安全策略才能发挥作用.也就是说,当一个进程试图访问一个文件时,SEAndroid会将进程和文件的安全上下文提取出来,根据安全策略规则,决定是否允许访问.本文就详细分析SEAndroid的进程安全上下文的关联过程. 老罗的新浪微博:http://weibo.com/shengyangluo,欢迎关注! 在传统的L

nginx源码分析--框架设计 &amp; master-worker进程模型

Nginx的框架设计-进程模型 在这之前,我们首先澄清几点事实: nginx作为一个高性能服务器的特点,其实这也是所有的高性能服务器的特点,依赖epoll系统调用的高效(高效是相对select/poll这些系统调用的,底层有一个链表和红黑树,避免了轮询,减少了用户空间和系统空间之间的数据传递等),非阻塞(所有的操作都是非阻塞,这样),多进程(master-slave进程模型),这些事实使得nginx成为一个高性能服务器的前提条件. 既然作为一个软件(http服务器),相对于一个网络库而言肯定有更

第一次作业:基于Orange&#39;s OS系统的进程模型分析与心得体会

1一. 操作系统进程概念模型与进程控制块概念浅析 1. 什么是进程? 图 1 - 1 (WIN10系统任务管理器对进程管理的图形化界面) 计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础. --百度百科 应用程序的实例.对正在运行的程序的抽象. --<现代操作系统> 2. 什么是进程控制块? 进程控制块(Processing Control Block),是操作系统核心中一种数据结构,主要表示进程状态.其作用是使一个在多道程序环境下不能独立

第一次作业:Linux 2.6.32的进程模型与调度器分析

1.前言 本文分析的是Linux 2.6.32版的进程模型以及调度器分析.在线查看 源码下载 本文主要讨论以下几个问题: 什么是进程?进程是如何产生的?进程都有那些? 在操作系统中,进程是如何被管理以及它们是怎样被调用的? 2.进程模型 2.1进程的概念 在我的理解中,一个程序就相当于一个进程,程序的启动意味着产生了一个新的进程,程序的关闭也就意味着一个进程的消亡. 那么专业定义应该是: 在计算中,进程是正在执行的计算机程序的一个实例. 它包含程序代码及其当前活动. 根据操作系统(OS),一个进

第一次作业:基于Linux0.01深入源码分析进程模型

一.前言 本文主要基于Linux0.01源代码分析进程模型.Linux 0.01虽然是Linux的第一个发行版本,但是却基本具备了操作系统中最重要的组成部分,同时Linux 0.01只有8500行左右的代码,对于初学者而言学习起来比较简单一点. Linux 0.01源代码下载地址: https://mirrors.edge.kernel.org/pub/linux/kernel/Historic/ 二.进程的定义 进程是程序执行的基本单位.(其中,进程和程序的区别:程序指的是由若干函数组成的可执