文件比较多!
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
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里面的值是可以随便改的,但要注意格式!