⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 os.c

📁 进程模拟
💻 C
字号:
#include "stdio.h"
#define MAXPRI 100
#define NLL -1

struct messagetp   /*消息块类型(信息,指针,发送者号)*/
{int num;
 struct messagetp *next;
 int pro;
 } ;

struct procb     /*PCB类型*/
{int id;             /*进程号*/
 char   status;       /*进程状态*/
 int    nextwr;         /*等待号*/
 int    priority;      /*优先数*/
 struct messagetp *mess;     /*消息队指针*/
 int    inum;                /*运行次数*/
 char   addr;            /*返回地址*/
 };   /*procb结构体*/


struct semaphorel  /*信号量类型(信号量,等待队头号)*/
{int value;
 int firstwr;
 } ;

struct procb pcb[4];     /*PCB表*/
struct semaphorel sem[3];    /*信号量表*/
char addr;         /*当前进程地址*/
int i,seed=0,exe;    /*运行次数,随机变量,当前运行进程号*/
int style;
int s1,s2;


void  send(int sender,int receiver,int snum)   /*发送*/
{struct messagetp *p,*q;   /*工作指针*/
p=(struct messagetp*)malloc(sizeof(struct messagetp));
 p->num=snum; /*申请消息块,写入缓冲*/
 p->next=NULL; /*下一指针置空*/
 p->pro=sender;    /*置发送者*/
 printf("send message to  process %d\n",receiver);
 printf("process %d already run %d times\n",sender,snum);

 q=pcb[receiver].mess;   /*q指向接收者消息等待队列首*/
  if(q==NULL) pcb[receiver].mess=p;   /*q空则p插入队首*/
   else
    {while(q->next!=NULL)
      q=q->next;       /*q移到队尾*/
     q->next=p;
     }
 }

void  receive(int receiver)
{struct messagetp *p,*q;   /*工作指针*/
 p=pcb[receiver].mess;       /*p指向接收者消息等待队列首  */
while(p!=NULL)    /*显示发送者和接收者信息 */
    {printf("\n");
     printf("receive message from process %d\n",p->pro);
     printf("process %d is already run %d times\n",p->pro,p->num);
     printf("\n");
     q=p;           /* 陆续将接收过的的消息块删除并释放  */
     p=p->next;
    free(q);
     }
  pcb[receiver].mess=NULL;     /*接收完后消息等待队列置空*/
 }

void  init()    /* 初始化*/
{int f,j;        /*初始化各进程控制块*/
 for(j=1;j<=3;j++)
 {pcb[j].id=j;
  pcb[j].status='r';          /*进程号,进程状态*/
  pcb[j].nextwr=NLL;       /*等待指针*/
  printf("process %d priority?",j);
  scanf("%d",&f);      /*读入优先数*/
  pcb[j].priority=f;
  pcb[j].mess=NULL;
  pcb[j].inum=0;
  pcb[j].addr='0';      /* 运行次数, 地址*/
  }
 sem[1].value=1;
 sem[1].firstwr=NLL;       /*对信号量初始化*/
 sem[2].value=1;
 sem[2].firstwr=NLL;
 exe=NLL;      /*当前执行进程号置为空*/
 }


float random1()    /* 产生0~1之间的随机数 */
{int m;           /* seed为int 型,实际值在-32768到32767之间*/
 if(seed<0)  m=-seed;
  else m=seed;
  seed=(25173*seed+13849)%65536;
 return(m/32767.0);
 }

 
int find()     /*选进程*/
{int j,pd,w;
 pd=NLL;
 w=MAXPRI;
 for(j=1;j<=3;j++)       /*先在高就绪态中找优先数最小的进程*/
  if(pcb[j].status=='r')
    if(pcb[j].priority<w)
      {w=pcb[j].priority;
       pd=j;
       }
  if(pd==NLL)
   for(j=1;j<=3;j++)     /* 再在低就绪态中找优先数最小的进程 */
    if(pcb[j].status=='t')
      if(pcb[j].priority<w)
          {w=pcb[j].priority;
           pd=j;
           }
  return  pd;             /* 返回进程号*/
 }

int scheduler()     /*调度*/
{int pd;
  pd=find();                 /*找优先进程 */
  if(pd==NLL&&exe==NLL)  return(NLL);
   else {if(pd!=NLL)        /*若有就绪进程则*/
   {if(exe==NLL)     /* 若当前没有进程执行则 */
     {pcb[pd].status='e';     /*新进程置执行态 */
      exe=pd;
      printf("process %d is executing:\n",exe);
      }
      else if(pcb[pd].priority<pcb[exe].priority)
            {pcb[exe].status='r';     /*原执行进程置高就绪态 */
              printf("process %d enter into ready\n",exe);
              pcb[pd].status='e';       /*新进程置执行态 */
              exe=pd;
              printf("process %d is executing\n",exe);
             }}
i=pcb[exe].inum;        /*恢复现场*/
addr=pcb[exe].addr;
return  exe ;       /*返回当前执行进程号  */
   }
}

void block(int se)
{int w;          /*工作指针*/
 printf("process %d is blocked\n",exe);
 pcb[exe].status='w';     /*置阻塞态*/
 pcb[exe].nextwr=NLL;
 w=sem[se].firstwr;       /*信号量等待队列头指针赋给w */
 printf("sem %d first=%d",se,sem[se].firstwr);
 printf("pcb%d=%d",w,pcb[w].nextwr);
 if(w==NLL)  sem[se].firstwr=exe;     /*空则当前进程作队头*/
  else 
  {while(pcb[w].nextwr!=NLL)
   w=pcb[w].nextwr;   /*指针后退到队尾*/
   pcb[w].nextwr=exe;       /*当前进程链接到队尾*/
   }
}


int p(int se,char ad)      /*wait操作*/
{sem[se].value=sem[se].value-1;         /*信号量减1 */
 if(sem[se].value>=0) 
  return (0);       /* 有资源不等待*/
  else
  {block(se);      /* 阻塞到 se 等待队列 */
   pcb[exe].inum=i;
   pcb[exe].addr=ad;      /*保护现场  */
   exe=NLL;
   return(1);    /*  执行进程置空,等待标志置真 */
   }
 }

void wakeup(int se)
{int w;
 w=sem[se].firstwr;    /* 队列头指针赋给w*/ 
 if(w!=NLL)     /*非空则摘下首块*/
  sem[se].firstwr=pcb[w].nextwr;   /*重链接 */
  pcb[w].status='r';    /*置为高就绪态      */
  printf("process %d is waken up\n",w);  
}

int v(int se,char ad)     /*  signal操作*/
{sem[se].value=sem[se].value+1;  /* 信号量加1*/
 if(sem[se].value>0)
 return (0);       /*无等待不重新调度*/
  else
   {wakeup(se);      /* 有等待唤醒 se 等待队列的进程*/
    pcb[exe].inum=i;
    pcb[exe].addr=ad;      /*保护现场*/
    return (1);      /*要重新调度 */
    }
}

int timeint(char ad,int k)     /*模拟时间片中断*/
{float x;               /*x为0~1之间的随机数*/
 x=random1();
 if(x<0.33&&exe==1)  return (0);  /*若在各自的时间片不产生中断*/
   else if(x<0.66&&exe==2)  return(0);
     else if(x<1.00&&exe==3)  return (0);
       else           /*否则产生时间片中断*/
        {pcb[exe].inum=i;     /*保护现场*/
         pcb[exe].addr=ad;
         pcb[exe].status='t';  /*置为低就绪态*/
         sem[k].value=sem[k].value+1;
         pcb[exe].nextwr=NLL;
         sem[k].firstwr=exe;
         printf("sem %d first=%d",k,sem[k].firstwr);
         printf("Times silce interrupt:\n");
         printf("process %d enter into ready\n",exe);
         exe=NLL ;    /*执行进程置空*/
         return (1);       /*中断标志置真*/
         }
 }

void eexit(int n)
{pcb[n].status='c';
 printf("process %d is completed\n",n);
 exe=NLL;
 }

void process1()     /*模拟并发进程1*/
{  
if(addr=='a')   goto a1;
 if(addr=='b')   goto b1;
 if(addr=='c')   goto c1;
 if(addr=='d')   goto d1;
 if(addr=='e')   goto e1;
 if(addr=='f')   goto f1;
 while(i<5)
 {receive(1);   /*1号进程接收消息,无消息继续  */
  printf("process1 calls P on semaphore1:\n");
   if(p(1,'a'))        goto stop1;   /*对信号量1进行P操作返回'a'地址*/
 a1:;
 printf("process1 is executing on its cretical section1\n");   /*入临界区*/
 if(timeint('b',1))    goto stop1;   /*若时间片到则重新调度*/
 b1:;
 s1=s1+1;
 printf("s1=%d",s1);     /*s1是临界资源不是信号量*/
 printf("process1 calls V on semaphore1 and quit  cretical setion1:\n");
  if(v(1,'c'))       goto stop1;      /* 对信号量1进行V操作,出临界区*/
 c1:;
 printf("process1 calls P on semaphore2:\n");
  if(p(2,'d'))       goto stop1;        /*对信号量2进行P操作返回'd'地址*/
 d1:;
  printf("process1 is execting cretical section2:\n");
  if(timeint('e',2))   goto stop1;
 e1:;
  s2=s2+1;
  printf("s2=%d",s2);
  printf("process1 calls V on semaphore2 and quit cretical section2:\n");
   if(v(2,'f'))      goto stop1;
  f1:;
  printf("process 1 cyclen count=%d:\n",i+1);
  i=i+1; 
  send(1,2,i);
  send(1,3,i);
/*;*/
 }
  stop1: if(i<5) goto end1;
  eexit(1);
  end1:;     /* 5次循环后本进程结束*/
}

void process2()    /*模拟并发进程2 */
{
 if(addr=='a')    goto a2;
   if(addr=='b')    goto b2;
   if(addr=='c')    goto c2;
   if(addr=='d')    goto d2;
   if(addr=='e')    goto e2;
   if(addr=='f')    goto f2;
while(i<5)
 {receive(2);
  printf("process2 calls P on semaphore2:\n");
  if(p(2,'a'))   goto stop2;
 a2:;
 printf("process2 is executing on its cretical section2:\n");
 if(timeint('b',2))    goto stop2;
 b2:;
 s2=s2+1;
 printf("s2=%d",s2);
 printf("process2 calls V on semaphore2 and quit  cretical setion2:\n");
  if(v(2,'c'))       goto stop2;
 c2:;
 printf("process2 calls P on semaphore1:\n");
  if(p(1,'d'))       goto stop2;
 d2:;
  printf("process2 is execting cretical section1:\n");
  if(timeint('e',1))   goto stop2;
 e2:;
  s1=s1+1;
  printf("s1=%d",s1);
  printf("process1 calls V on semaphore1 and quit cretical section1:\n");
   if(v(1,'f'))      goto stop2;
  f2:;
  printf("process 2 cyclen count=%d:\n",i+1);
  i=i+1; 
  send(2,1,i);
  send(2,3,i);
/*;*/
 }
  stop2: if(i<5)  goto end2;
  eexit(2);
  end2:;
}


void process3()    /*模拟并发进程3*/
{ 
if(addr=='a')    goto a3;
   if(addr=='b')    goto b3;
   if(addr=='c')    goto c3;
while(i<5)
 {receive(3);
  printf("process3 calls P on semaphore2:\n");
  if(p(2,'a'))   goto stop3;
a3:;
 printf("process3 is executing on its cretical section2:\n");
 if(timeint('b',2))    goto stop3;
b3:;
 s2=s2+1;
 printf("s2=%d",s2);
 printf("process3 calls V on semaphore2 and quit  cretical setion2:\n");
  if(v(2,'c'))       goto stop3;
c3:;
 printf("process3 cyclen count=%d",i+1);
 i=i+1;
send(3,1,i);
send(3,2,i);
/*;*/
}
stop3:
 if(i<5)   goto end3;
 eexit(3);
 end3:;
}

 void main()
{int k;

printf("                    C.O.S   Example  one");
printf("\n");
init();
s1=0;s2=0;
printf("s1=%d,s2=%d",s1,s2);
printf("process1,process2,process3 are all in ready!\n");;
label100: k=scheduler();   /*调用调度程序返回选中进程号*/
  printf("k=%d",k);
 if(k!=NLL)
 switch(k)
 {case 1:  process1();  goto label100;
  case 2: process2(); goto label100;
  case 3:  process3(); goto label100;
  }
else printf("process identifer error!\n");
 
printf("\n\n");
printf("s1=%d,s2=%d",s1,s2);
printf("\n\n");
printf("            COMPLETED!");
getch();
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -