您的位置:首页 > 其它

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

2007-09-12 17:35 381 查看
简单的进程调度模拟
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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: