[模拟] 简单的进程调度模拟

原创 2007年09月12日 17:35:00
简单的进程调度模拟
roadtang 2007/09/12

在论坛上见到的这个,正好有兴趣,也有时间,就写了下, 分别有抢占和非抢占的proc_schedule ,代码里加了注释.
仅仅是为了示例用,调度规则就是  优先级大的先执行.


原问题链接
http://community.csdn.net/Expert/TopicView3.asp?id=5752551

注意: 这个垃圾程序 没有执行出口, 呵呵.

============  Code start ==================

/*
Simple Operating System Process Schedule Simulation


http://community.csdn.net/Expert/TopicView3.asp?id=5752551

roadtang 2007/09/12
*/


#include <stdlib.h>
#include <stdio.h>
#include <string.h>


/* ------- VM (cpu , interrupt)  ----------*/

#define REG_NUM 20
#define CPU_HZ 1000000

typedef struct vcpu_s {
  int reg[20];
  int flag;
  long long tick;
  double time;
  void *eip;    // pointer to execution process.
} vcpu_t;



#define INT_SIZE  1024
#define INT_TIME  5
#define INT_IDLE  6
typedef void (*func)(void);
typedef struct vm_s {
  vcpu_t  cpu;
  func    int_tab[INT_SIZE];  // virtual machine interrupt table
#define tick cpu.tick
#define eip  cpu.eip
} vm_t;

vm_t  vm;

void cpu_frame();

void vm_init();
void vm_start();
void vm_stop();


/* ------- OS simulation (process schedule) -----------*/

/*
  OS timer mechanism
*/
#define STIME_FREE 0
#define STIME_ACTIVE 1

#define STIME_SIZE  1024
typedef struct tm_ent_s{
  int flag;
  int time;
  func fn;
} tm_ent_t;

tm_ent_t  timers[STIME_SIZE];  // operating system tiemrs hooks

void timeridle_init();
int register_timer(int time, func f);  //success return id, failure return -1
int unregister_timer(int id);
void os_timer_vmhandle();

/*
idle mechanism
*/
void os_idle_vmhandle(void);

/*
  OS process schedule
*/
#define PF_FREE     0
#define PF_READY    1
#define PF_RUNNING  2
#define PF_DONE     3
typedef struct proc_s {
  int flag;  /* PF_ */
  char name;
  int prio;
  int exet;
  int exed;
  int freq;  /* if freq > 0, it's cycle task */
  func fn;
  /*
  struct proc_s *prev;
  struct proc_s *next;
  */
} proc_t;
/*
#define PROCHEAD_INIT(p) do {  p->prev = p; p->next = p; } while(0)

struct proc_s ready;   
struct proc_s running;
struct proc_s done;
*/

#define PROCESS_SIZE   64
#define SCHED_INTERVAL 1
proc_t procs[PROCESS_SIZE];

int create_proc(char name, int prio, int exet, int freq, func f);
void release_proc(int id);
void proc_schedule_handle_preempt(void);
void proc_schedule_handle_nonpreempt(void);

/*
single user operation  and misc &
*/

void user_init();

void print(char c);









/*=========================================================================================================

   The Implementation is following

=========================================================================================================*/


/*
simulate cpu one exection
*/
void cpu_frame(vcpu_t *cpu)
{
  func ifp, idp;

  ++ vm.tick;

 
  /* in our vm, the hardware timer interrupt is triggered every cpu pulse, (i.e.veryfast) */
  ifp = vm.int_tab[INT_TIME];
  if (ifp)
    ifp();

  if (vm.eip)
    ((func)(vm.eip))();
  else /* idle */
    if (idp = vm.int_tab[INT_IDLE])
      idp();
}


/*
VM initialization
including:
  OS initialize.,
  user initialize operation.
*/
void vm_init()
{
  /* clear every thing */
  memset (&vm, 0, sizeof(vm));
  memset (timers, 0, sizeof(timers));
  memset (procs, 0 , sizeof(procs));

  /* os init
     init os timers modules
     init task schedule modeuls
  */

  timeridle_init();
  register_timer(SCHED_INTERVAL,  proc_schedule_handle_nonpreempt);

  /*
    user init,  push root thread ,or something etc.
  */
  user_init();

}

void vm_start()
{
  while(1)
    cpu_frame(0);
}

void vm_stop()
{
}


/*
  OS timer & idle
*/

void timeridle_init()
{
  vm.int_tab[INT_TIME] = &os_timer_vmhandle;
  vm.int_tab[INT_IDLE] = &os_idle_vmhandle;
}
 
int register_timer(int time, func f)  //success return id, failure return -1
{
  int i;
  for (i = 0; i < STIME_SIZE; ++i)
    if (timers[i].flag==STIME_FREE){
      timers[i].flag = STIME_ACTIVE;
      timers[i].time = time;
      timers[i].fn = f;
      return i;
    }
  return -1;
}

int unregister_timer(int id){
  memset(&timers[id], 0 , sizeof(timers[0]));
}

/**
  
 */
void os_timer_vmhandle()
{
  int i;

  for (i=0; i<STIME_SIZE; ++i)
    if (timers[i].flag == STIME_ACTIVE
    && vm.tick % timers[i].time ==0)
    timers[i].fn();
}

void os_idle_vmhandle()
{


}



/*
 
  OS  process schedule simulation

 */


int create_proc(char name, int prio, int exet, int freq, func f)
{
  int i;
  for (i = 0; i < PROCESS_SIZE; ++i)
    if (procs[i].flag == PF_FREE)
      {
    proc_t *p = &procs[i];
    p->flag = PF_READY;
    p->name = name;
    p->prio = prio;
    p->exet = exet;
    p->freq = freq;
    p->fn    = f;
    return i;
      }
  return -1;
}

void release_proc(int id)
{
  memset(&procs[id], 0, sizeof(proc_t));
}

/*
The primary method for process schedule
*/
void proc_schedule_handle_preempt(void)
{
  /* does:
     1. calculate the exetime of the running procs
     2.(preempt) schedule a new procs to execution
     3. terminate the non-cycle finished proc, mark dead. and purge them.
     4. reset the cycle proc to ready status for next
   */
  int i;
  proc_t *p;
  proc_t *sch = 0; int prio = 0;

  static long long base_tck;
  if (!base_tck)
    base_tck = vm.tick;

  /* cal tick */
  for (i = 0; i < PROCESS_SIZE; ++i)
    {
      p = &procs[i];

      switch(p->flag)
    {
    case PF_FREE:  /* skip for empty node */
      continue;

    case PF_RUNNING: 
      p->exed += (vm.tick - base_tck);
      base_tck = vm.tick;
      if (p->exed >= p->exet)
        p->flag = PF_DONE;
      else
        p->flag = PF_READY;  /* take part in next schedule */
      break;

    case PF_DONE:
      if (p->freq <= 0)
        release_proc(i);
      else if (vm.tick% p->freq == 0)
        {   /* cycle task, reset  */
          p->flag = PF_READY;
          p->exed = 0;
        }
      break;

    case PF_READY:/* get max priority proc , store it in  (proc_t*)sch */
      if (p->prio > prio)
        {
          sch = p;
          prio = p->prio;
        }
      break;
    }
    }

  /* schedule */
  if (sch)
    {
      vm.eip = sch->fn;
      sch->flag = PF_RUNNING;
      print(sch->name);
    }
  else
    print('/');
}



void proc_schedule_handle_nonpreempt(void)
{
  /* does:
     1. calculate the exetime of the running procs
     2.(nonpreempt) remain the running proc execute if it doesn't finish. otherwise schedule a new proc
     3. terminate the non-cycle finished proc, mark dead. and purge them.
     4. reset the cycle proc to ready status for next
   */
  int i;
  proc_t *p;
  proc_t *sch = 0; int prio = 0;
  static proc_t *running = 0;   /* store the running proc, if exist, */

  static long long base_tck;
  if (!base_tck)
    base_tck = vm.tick;

  /* cal tick */
  for (i = 0; i < PROCESS_SIZE; ++i)
    {
      p = &procs[i];

      switch(p->flag)
    {
    case PF_FREE:  /* skip for empty node */
      continue;

    case PF_RUNNING: 
      running = p;
      p->exed += (vm.tick - base_tck);
      base_tck = vm.tick;
      if (p->exed >= p->exet)
        {
          p->flag = PF_DONE;
          running = 0;
        }
      break;

    case PF_DONE:
      if (p->freq <= 0)
        release_proc(i);
      else if (vm.tick% p->freq == 0)
        {   /* cycle task, reset  */
          p->flag = PF_READY;
          p->exed = 0;
        }
      break;

    case PF_READY:/* get max priority proc , store it in  (proc_t*)sch */
      if (p->prio > prio)
        {
          sch = p;
          prio = p->prio;
        }
      break;
    }
    }

  /* schedule */
  if (running)
    sch = running;

  if (sch)
    {
      vm.eip = sch->fn;
      sch->flag = PF_RUNNING;
      print(sch->name);
    }
  else
    print('/');
}

/*
single user operation
*/
void dummy()
{
}
void user_init()
{
  create_proc('A', 3, 1, 0, dummy);
  create_proc('B', 5, 1, 100, dummy);
  create_proc('C', 4, 2, 200, dummy);
  create_proc('D', 2, 1, 100, dummy);
  create_proc('E', 1, 1, 100, dummy);

}

void print(char ch)
{
  static char c = 0;

  if (c != '/'){
    putchar (ch);
    putchar ('|');
  }
  c = ch;

}

/*
 */
main()
{
  vm_init();
  vm_start();
}



=======  Code end  ====================================


输出结果:
B|C|C|A|D|E|/|D|E|/|C|C|D|E|/|D|E|/|C|C|D|E|/|D|E|/|C|C|D|E|/|D|E|/|C|C|D|E|/|D|
E|/|C|C|D|E|/|D|E|/|C|C|D|E|/|D|E|/|C|C|D|E|/|D|E|/|C|C|D|E|/|D|E|/|C|C|D|E|/|D|
E|/|C|C|D|E|/|D|E|/|C|C|D|E|/|D|E|/|C|C|D|E|/|D|E|/|C|C|D|E|/|D|E|/|C|C|D|E|/|D|
E|/|C|C|D|E|/|D|E|/|C|C|D|E|/|D|E|/|C|C|D|E|/|D|E|/|C|C|D|E|/|D|E|/|C|C|D|E|/|D|
E|/|C|C|D|E|/|D|E|/|C|C|D|E|/|D|E|/|C|C|D|E|/|D|E|/|C|C|D|E|/|D|E|/|C|C|D|E|/|D|
E|/|C|C|D|E|/|D|E|/|C|C|D|E|/|D|E|/|C|C|D|E|/|D|E|/|C|C|D|E|/|D|E|/|C|C|D|E|/|D|
E|/|C|C|D|E|/|D|E|/|C|C|D|E|/|D|E|/|C|C|D|E|/|D|E|/|C|C|D|E|/|D|E|/|C|C|D|E|/|D|
E|/|C|C|D|E|/|D|E|/|C|C|D|E|/|D|E|/|C|C|D|E|/|D|E|/|C|C|D|E|/|D|E|/|C|C|D|E|/|D
版权声明:本文为博主原创文章,未经博主允许不得转载。 举报

相关文章推荐

模拟简单进程调度实验

一、实验目的及要求 1. 用C语言编写和调试一个模拟进程调度程序,以加深对进程的概念及进程调度算法的理解,模拟过程的数据结构和算法符合主流操作系统的进程调度规则(从第2点开始给出过程规则)。 2. 进...
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)