[模拟] 简单的进程调度模拟
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
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
相关文章推荐
- OS之子进程简单模拟shell解释环境
- OS之子进程简单模拟shell解释环境(再次)
- 操作系统进程调度简单模拟
- 模拟简单进程调度实验
- 用C语言实现对N个进程的简单时间片轮转法Round Robin的调度模拟
- 模拟简单进程调度实验
- 模拟进程调度(简单实现)
- base64转码(简单的get方式图片上传,模拟app接收图片)
- java网络编程一:Socket用法,简单模拟一对一聊天
- 简单模拟操作系统中的文件操作(2)
- 使用java简单模拟ping和telnet的实现
- [C++ && Python]简单模拟代码评测系统
- 使用动态优先权的进程调度算法的模拟
- 六十 如何写一个简单的守护(精灵)进程原型
- 简单的几句Python语句,模拟《骇客帝国》中的滚屏
- 传智播客-Ajax(2)-利用jQuery简单模拟实现股票信息的实时显示
- java CountDownLatch 模拟多并发线程简单例子
- 实验三 进程调度模拟程序
- HDU-1031- Design T-Shirt(c++ && 简单模拟)
- Operating Systems: Three Easy Pieces(操作系统:三个简单方面)5穿插章节:进程API/5.1系统调用:fork()