>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
1.首先是编译文件makefile:
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
Makefile
#=====================================================
#Makefile For Lzy's
#=====================================================
#Programs , flags ,etc
CC = g++
CFLAGS = -c -fno-builtin -fno-stack-protector
#This Program
LZYSHELL = hostd
OBJS = Pcb.o hostd.o
#All phony Targets
.PHONY:everything clean
everything : $(LZYSHELL) clean
clean :
rm -f $(OBJS)
$(LZYSHELL) : $(OBJS)
$(CC) -o $(LZYSHELL) $(OBJS)
hostd.o:hostd.c
$(CC) $(CFLAGS) -o $@ $<
Pcb.o:Pcb.c
$(CC) $(CFLAGS) -o $@ $<
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
2.头文件hostd.h:
hostd.h
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
#ifndef GHOST_H
#define GHOST_H
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <unistd.h>
#include "Pcb.h" //自己定义
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
3.头文件Pcb.h:
Pcb.h
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
#ifndef PCB_H
#define PCB_H
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <unistd.h>
#ifndef FALSE
#define FALSE 0
#endif
#ifndef TRUE
#define TRUE 1
#endif
#define DEFAULT_NAME "hostd"
#define QUANTUM 1
#endif
#define MAXARGS 3
#define DEFAULT_PROCESS "./process"
#define N_QUEUES 4 //进程队列长度
#define RT_PRIORITY 0
#define MID_PRIORITY 2
#define HIGH_PRIORITY 1
#define LOW_PRIORITY (N_QUEUES - 1)
#define PCB_UNINITIALIZED 0
#define PCB_INITIALIZED 1
#define PCB_READY 2
#define PCB_RUNNING 3
#define PCB_SUSPENDED 4
#define PCB_TERMINATED 5
struct rsrc
{
int printers;
int scanners;
int modems ;
int cds ;
};//资源需求
typedef struct rsrc Rsrc ;
typedef Rsrc * RsrcPtr ;
struct pcb
{
pid_t pid ; // 系统进程ID
int Num ; //进程代号
char *args[MAXARGS] ; //进程名
int arrivaltime ; //到达时间
int priority ;
int remainingcputime ; //处理时间
int mbytes ;
Rsrc req ;
int status ;
struct pcb *next ; //指向下一个进程体的指针
int QueNum ;
};
typedef struct pcb Pcb;
typedef Pcb *PcbPtr ;
PcbPtr startPcb(PcbPtr) ;
PcbPtr suspendPcb(PcbPtr) ;
PcbPtr terminatePcb(PcbPtr) ;
PcbPtr printPcb(PcbPtr,FILE *) ;
void printPcbHdr(FILE *) ;
PcbPtr createnullPcb() ;
PcbPtr enqPcb(PcbPtr,PcbPtr) ;
PcbPtr deqPcb(PcbPtr*) ;
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
4.C文件Pcb.c
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
#include "Pcb.h"
PcbPtr startPcb(PcbPtr p)
{
if(p->pid == 0)
{//此时还未有start
switch(p->pid = fork())
{ //所以开始start
case -1 :
perror("startPcb") ;
exit(1) ;
case 0 : //子进程
p->pid = getpid() ;
p->status = PCB_RUNNING ;
printPcbHdr(stdout) ; //输出这是在子进程
printPcb(p,stdout) ; //迫使缓冲块数据立即写盘并更新超级块
fflush(stdout) ;
execvp(p->args[0],p->args) ; //运行在p结构体中的进程
perror(p->args[0]) ; //错误则显示错误信息
exit(2) ;
}
}
else
{ //已经start & 挂起了 于是继续 sigcont为继续标志
printf("current is %d",p->Num) ;
kill(p->pid,SIGCONT) ;
}
p->status = PCB_RUNNING ;
return p ;
}
PcbPtr printPcb(PcbPtr p,FILE * iostream)
{
fprintf(iostream,"current %d is running %7d%7d%7d%7d ",p->Num,
(int) p->pid,p->arrivaltime,p->priority,
p->remainingcputime) ;
//p->memoryblock->offset,p->mbytes,
//p->req.printers,p->req.scanners,p->req.modems,p->req.cds ;
switch(p->status)
{
case PCB_UNINITIALIZED :
fprintf(iostream,"UNINITIALLIZED");
break ;
case PCB_INITIALIZED :
fprintf(iostream,"INITIALIZED");
break ;
case PCB_READY :
fprintf(iostream,"READY");
break ;
case PCB_RUNNING :
fprintf(iostream,"SUSPENDED") ;
break ;
case PCB_TERMINATED :
fprintf(iostream,"PCB_TERMINATED") ;
break ;
default :
fprintf(iostream,"UNKNOWN") ;
}
fprintf(iostream,"\n") ;
return p ;
}
PcbPtr createnullPcb()
{
PcbPtr newprocessPtr ; //创建新的Pcb结构体
if((newprocessPtr = (PcbPtr) malloc (sizeof(Pcb)))) //为结构体分配内存
{
newprocessPtr->pid = 0 ;
newprocessPtr->args[0] = DEFAULT_PROCESS ;
newprocessPtr->args[1] = NULL ;
newprocessPtr->arrivaltime = 0 ;
newprocessPtr->priority = HIGH_PRIORITY ;
newprocessPtr->remainingcputime = 0 ;
newprocessPtr->mbytes = 0 ;
newprocessPtr->req.printers = 0 ;
newprocessPtr->req.scanners = 0 ;
newprocessPtr->req.modems = 0 ;
newprocessPtr->req.cds = 0 ;
newprocessPtr->status = PCB_UNINITIALIZED ;
newprocessPtr->next = NULL ;
return newprocessPtr ;
}
perror("allocating memory for new process");
return NULL ; //分配内存没有成功
}
void printPcbHdr(FILE * iostream)
{
fprintf(iostream," pid arrive prior cpu status\n") ;
}
PcbPtr enqPcb(PcbPtr q,PcbPtr p)
{
PcbPtr h = q ; //h为队头
p->next = NULL ;
if(q)
{
while(q->next) q=q->next ;//找到最后的队中元素
q->next = p; //将p挂在最后队中元素的后面
return h ;
}
return p; //队列为空,则返回p
}
PcbPtr suspendPcb(PcbPtr p)
{
int status ;
kill(p->pid , SIGTSTP) ;
waitpid(p->pid , &status ,WUNTRACED) ;
p->status = PCB_SUSPENDED ;
return p ;
}
PcbPtr terminatePcb(PcbPtr p)
{
int status ;
kill(p->pid,SIGINT) ;
waitpid(p->pid,&status,WUNTRACED) ;
p->status = PCB_TERMINATED ;
return p ;
}
PcbPtr deqPcb(PcbPtr * p)
{
PcbPtr h = *p ;//h指向对头元素
if(*p)
{
*p = (*p)->next ;
}
else
{
return NULL ;
}
return h ;
}
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
5.最后为主程式hostd .c
#include "hostd.h"
#define VERSION "1.0"
char *StripPath(char*) ;
void PrintUsage(FILE*,char *) ;
void SysErrMsg(char *,char *) ;
void ErrMsg(char * ,char * ) ;
int main(int argc , char *argv[])
{
char * inputfile ; //输入文件指针
FILE * inputliststream ; //输入文件流
PcbPtr inputqueueRQNow = NULL ; //实时队列,优先级为0的队列
PcbPtr inputqueueRQ0 = NULL ; //输入队列RQ0
PcbPtr inputqueueRQ1 = NULL ; //输入队列RQ1
PcbPtr inputqueueRQ2 = NULL ; //输入队列RQ2
int NextTime = 0 ; //用来指示下个队头时间
PcbPtr currentprocess = NULL ; //现在的进程
PcbPtr process = NULL ;
int timer = 0 ; // 调度计时器
// 分析命令是否符合语法
if(argc == 2) inputfile = argv[1] ; //如果参数为两个,则将第二个参数给文件指针
else PrintUsage(stderr , argv[0]) ; //不符合语法,则打印错误信息
//初始化 调度队列
//已经在上面的任务中初始化完毕
//从调度文件列表中将调度队列填入
if(!(inputliststream = fopen(inputfile,"r")))
{
exit(2) ;
}
while(!feof(inputliststream))
{
//将进程加载入进程表
process = createnullPcb() ; //创建不活跃的进程
if(fscanf(inputliststream,"%d,%d,%d,%d,%d,%d,%d,%d,%d", //返回变量数,没的话返回EOF
&(process->Num), //进程代号
&(process->arrivaltime),&(process->priority),
&(process->remainingcputime),&(process->mbytes),
&(process->req.printers),&(process->req.scanners),
&(process->req.modems),&(process->req.cds))!=9){
free(process) ;
continue ;
}
process->status = PCB_INITIALIZED ; //进程状态设置为已经初始化
process->QueNum = 0 ;
//根据优先级确定在哪个队列
if(process->priority == 0)
{
process->QueNum = 3 ; //表明QueNum在实时队列
inputqueueRQNow = enqPcb(inputqueueRQNow,process) ; //0优先级将进程加入实时队列
}
else if(process->priority == 1)
{
process->QueNum = 0 ;
inputqueueRQ0 = enqPcb(inputqueueRQ0,process) ; //1优先级加入队列0
}
else if(process->priority == 2) //2优先级加入队列1
{
process->QueNum = 1 ;
inputqueueRQ1 = enqPcb(inputqueueRQ1,process) ;
}
else if(process->priority == 3)
{
process->QueNum = 2 ; //3优先级加入队列2
inputqueueRQ2 = enqPcb(inputqueueRQ2,process) ;
}
}
//开始调度计时器
//上面计时器已经初始化为0
//在当前队列不为空或者现在又进程正在运行的时候 ;
while( inputqueueRQNow || inputqueueRQ0 || inputqueueRQ1 || inputqueueRQ2 || currentprocess)
{
//如果有个进程在运行
if(currentprocess)
{
//a.减少进程运行时间 ;
currentprocess->remainingcputime -=QUANTUM ;
//c.如果时间到了
if(currentprocess->remainingcputime <= 0)
{
//A.发出信号去终结这个进程 ;
printf("current %d end\n",currentprocess->Num) ;
terminatePcb(currentprocess) ;
//B.释放进程体所占内存
free(currentprocess) ;
//printf("This %d end",currentprocess->arrivaltime) ;
currentprocess = NULL ;
}
}
if(currentprocess) //确定currentprocess即将前往哪个队列
{
//先挂起当前队列
if(NextTime >timer) //如果当前队列存在,且到达时间大于当前时间
{
//则维持在原队列
}
else if(currentprocess->QueNum == 3) //即现在所处为实时队列,应该立即实行,采取先进先出方式
{
//实时队列不需挂起
}
else if(currentprocess->QueNum ==0) //即现在所在队列为0队列,将到1队列
{
suspendPcb(currentprocess) ; //挂起当前队列
currentprocess->QueNum++ ;
inputqueueRQ1 = enqPcb(inputqueueRQ1,currentprocess) ;
}
else if(currentprocess->QueNum ==1) //即现在所在的队列为1队列,将到2队列
{
suspendPcb(currentprocess) ; //挂起当前队列
currentprocess->QueNum++ ;
inputqueueRQ2 = enqPcb(inputqueueRQ2,currentprocess) ;
}
else if(currentprocess->QueNum ==2) //即现在所在的队列为2队列,将回到2队列
{
suspendPcb(currentprocess) ; //挂起当前队列
inputqueueRQ2 = enqPcb(inputqueueRQ2,currentprocess) ;
}
}
if(currentprocess && NextTime > timer) //如果当前进程存在
{ //且队头到达时间大于当前时间
startPcb(currentprocess) ; //则继续执行当前进程
}
else if( !currentprocess && NextTime > timer) //如果队列存在
{ //且队头到达时间大于当前时间
//等待
}
else if(inputqueueRQNow && !currentprocess ) // 实时队列不为空,则采用先进先出方式运行。
{
currentprocess = deqPcb(&inputqueueRQNow) ;
if(inputqueueRQNow) //读取下一个到达时间
{
NextTime = inputqueueRQNow->arrivaltime ;
}
else if(inputqueueRQ0)
{
NextTime = inputqueueRQ0->arrivaltime ;
}
else if(inputqueueRQ1)
{
NextTime = inputqueueRQ1->arrivaltime ;
}
else if(inputqueueRQ2)
{
NextTime = inputqueueRQ2->arrivaltime ;
}
else
{
NextTime = 0 ;
}
startPcb(currentprocess) ;
}
else if(!inputqueueRQNow && currentprocess && inputqueueRQ0 && inputqueueRQ1 && inputqueueRQ2 && currentprocess->QueNum == 3)
{
startPcb(currentprocess) ; //这个else if仅用来解决实时队列边界问题
}
else if(!inputqueueRQNow && inputqueueRQ0 )//&& inputqueueRQ0->arrivaltime<=timer)//如果实时队列为空,而且第一队列不为空
{
//a.将进程出队 然后启动这个进程(fork & exec)
//b.将之设置为运行中的进程
currentprocess = deqPcb(&inputqueueRQ0) ; //decPcb返回的是头队列指针
if(inputqueueRQ0) //读取下一个到达时间
{
NextTime = inputqueueRQ0->arrivaltime ;
}
else if(inputqueueRQ1)
{
NextTime = inputqueueRQ1->arrivaltime ;
}
else if(inputqueueRQ2)
{
NextTime = inputqueueRQ2->arrivaltime ;
}
else
{
NextTime = 0 ;
}
startPcb(currentprocess) ; //启动当时的进程
}
//如果实时队列空,第一个队列已空,而且第二个队列不为空,则执行第二个队列
else if(!inputqueueRQNow && !inputqueueRQ0 && inputqueueRQ1 )//&& inputqueueRQ1->arrivaltime<=timer)
{
currentprocess = deqPcb(&inputqueueRQ1) ;
if(inputqueueRQ1) //读取下一个到达时间
{
NextTime = inputqueueRQ1->arrivaltime ;
}
else if(inputqueueRQ2)
{
NextTime = inputqueueRQ2->arrivaltime ;
}
else
{
NextTime = 0 ;
}
startPcb(currentprocess) ;
}
//如果实时队列空,用户前两个队列都为空,第三个队列不为空,则执行第三个对列
else if(!inputqueueRQNow && !inputqueueRQ0 && !inputqueueRQ1 && inputqueueRQ2)// &&inputqueueRQ2->arrivaltime<=timer )
{
currentprocess =deqPcb(&inputqueueRQ2) ;
if(inputqueueRQ2) //读取下一个到达时间
{
NextTime = inputqueueRQ2->arrivaltime ;
}
else
{
NextTime = 0 ;
}
startPcb(currentprocess) ;
}
//等待1秒,然后确定下一个调度
sleep(QUANTUM) ;
//增加调度时间 ;
timer += QUANTUM ;
printf(" time = %d \n",timer) ;
//Go back to 4 ;
}
//如果没有进程而且所有的队列都为空,则结束
printf("\n\n\n ALL END \n") ;
//Exit 正常返回
exit(0) ;
}
char * StripPath(char * pathname)
{
char *filename = pathname ;
if(filename && *filename) //名字和指针都存在
{
filename = strrchr(filename,'/') ; //寻找最后一个'/',返回之后的文件名
if(filename) //有这个指针,strrchr返回正确
if(*(++filename)) //'/'后面的文件名
return filename ;
else return NULL ; //目录 return NULL
else return pathname ; //strrchr返回不正确,则返回路径名
}
return NULL ; //文件名不存在则返回NULL
}
void PrintUsage(FILE * stream,char * progname)
{
if(!(progname = StripPath(progname))) //文件不存在
progname = DEFAULT_NAME ;
fprintf(stream,"\n","You are SB") ;
exit(127) ;
}
void ErrMsg(char *msg1 , char *msg2)
{
if(msg2) fprintf(stderr,"error - %s %s \n",msg1,msg2) ;
else fprintf(stderr,"error - %s\n",msg1);
return ;
}
void SysErrMsg(char * msg1,char * msg2)
{
if(msg2) fprintf(stderr,"Error- %s %s;",msg1,msg2) ;
else fprintf(stderr,"Error - %s;",msg1) ;
perror(NULL) ;
return ;
}
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
6.list
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
1,0,0,3,64,0,0,0,0
2,2,1,6,128,1,0,0,1
3,4,3,4,128,1,0,1,2
4,6,3,5,128,0,0,0,0
5,8,0,2,128,0,0,0,0
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
用法:将这6个文件放在linux同一个文件夹内,在命令行内敲入make,编译好后执行./hostd list
就可以看到效果,当然 list里面的值是可以随便改的,但要注意格式!