操作系统Marking02进程切换代码

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

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   //进程队列长度
#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   //子进程
    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 ;
}


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 ;
}

 

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   ;
  newprocessPtr->priority HIGH_PRIORITY ;
  newprocessPtr->remainingcputime =  ;
  newprocessPtr->mbytes    ;
  newprocessPtr->req.printers   ;
  newprocessPtr->req.scanners    ;
  newprocessPtr->req.modems   ;
  newprocessPtr->req.cds    ;
  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 ;
 }
 return p;       //队列为空,则返回p
}



PcbPtr suspendPcb(PcbPtr p)
{
 int status ;
 kill(p->pid , SIGTSTP) ;
 waitpid(p->pid , &status ,WUNTRACED) ;
 p->status = PCB_SUSPENDED ;
 return ;
}

 

PcbPtr terminatePcb(PcbPtr p)
{
 int status ;
 kill(p->pid,SIGINT) ;
 waitpid(p->pid,&status,WUNTRACED) ;
 p->status = PCB_TERMINATED ;
 return ;
}


PcbPtr deqPcb(PcbPtr * p)
{
 PcbPtr h = *p  ;//h指向对头元素
 if(*p)
 {
  *p = (*p)->next  ;
 }
 else
 {
  return NULL ;
 }
 return ;
}

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

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  //用来指示下个队头时间
 
 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 = ;


   //根据优先级确定在哪个队列 
   if(process->priority == 0)
   {
    process->QueNum //表明QueNum在实时队列
    inputqueueRQNow = enqPcb(inputqueueRQNow,process) //0优先级将进程加入实时队列
   }
   else if(process->priority == 1)
   {
    process->QueNum ;
    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 = ;
    }

 

    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 ;
   }


   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 = ;
   }

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值