操作系统上机(os上机)

操作系统课程上机内容,可以查看源代码和阅读注释进行了解。
完成过程中查询了包括但不限于课本、别人博文、相关资料,侵删。

实验一

//hello.c
#include <stdio.h>

int main() {
    printf("hello world");
    return 0;
}

//scripts.sh
echo "Mem Usage:" | tee -a f1
free -h | tee -a f1

echo "Path:" | tee -a f2
pwd | tee -a f2

echo "Details:" | tee -a f3
ls -l > f3

实验二


//mutex-ex.c
#include <stdio.h>
#include <pthread.h>

int sum = 0;
pthread_mutex_t mutex;

void thread(void){
  int i;
  for(i = 0;i < 10000000;i++){
    pthread_mutex_lock(&mutex);
    sum += 1;
    pthread_mutex_unlock(&mutex);
  }
}

int main(void) {
  pthread_t tid1,tid2;
  pthread_mutex_init(&mutex,NULL);
  
  pthread_create(&tid1,NULL,thread,NULL);
  pthread_create(&tid2,NULL,thread,NULL);
  pthread_join(tid1,NULL);
  pthread_join(tid2,NULL);
  
  printf("10000000 + 10000000 = %d\n",sum);
  return 0;
}


//nosyoc-ex.c
#include <stdio.h>
#include <pthread.h>

int sum = 0;

void thread(void){
  int i = 0;
  for(i = 0;i < 10000000;i++){
    sum += 1;
  }
}

int main(void) {
  pthread_t tid1,tid2;
  
  pthread_create(&tid1,NULL,thread,NULL);
  pthread_create(&tid2,NULL,thread,NULL);
  pthread_join(tid1,NULL);
  pthread_join(tid2,NULL);
  
  printf("10000000 + 10000000 = %d\n",sum);
  return (0);
}


// sem-ex.c
#include <stdio.h>
#include <pthread.h>
#include <semaphore.h>

int sum = 0;
sem_t sem;

void thread(void){
  int i;
  for(i = 0;i < 10000000;i++){
    sem_wait(&sem);
    sum += 1;
    sem_post(&sem);
  }
}

int main(void) {
  pthread_t tid1,tid2;
  sem_init(&sem,0,1);
  
  pthread_create(&tid1,NULL,thread,NULL);
  pthread_create(&tid2,NULL,thread,NULL);
  pthread_join(tid1,NULL);
  pthread_join(tid2,NULL);
  
  printf("10000000 + 10000000 = %d\n",sum);
  return 0;
}

实验三


//forkexp1.c
#include <sys/types.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>
int main(int argc, char *argv[]) {
/* fork a child process */
pid_t pid = fork();
if (pid < 0) { /* error occurred */
fprintf(stderr, "Fork Failed");
return 1;
}
else if (pid == 0) { /* child process */
printf("I'm the child \n"); /* you can execute some commands here */
}
else { /* parent process */
/* parent will wait for the child to complete */
wait(NULL);
/* When the child is ended, then the parent will continue to execute its code */
printf("Child Complete \n");
}
}

//forkhello.c
#include <stdio.h> 
#include <sys/types.h> 
#include <unistd.h> 
int main() 
{ 
/* fork a process */
fork(); 
printf("Hello world!\n"); 
return 0; 
}

// forkhello2.c
#include <stdio.h> 
#include <sys/types.h> 
#include <unistd.h> 
#include <stdlib.h>

int main() 
{ 
fork(); 
fork(); 
fork(); 

printf("Hello world!\n");
return 0; 
}

// forkhello3.c
#include <stdio.h> 
#include <sys/types.h> 
#include <unistd.h> 
#include <stdlib.h>

int doWork(){
fork();
fork();
printf("Hello world!\n");
}
int main() {
doWork();
printf("Hello world!\n");
exit(0);
}

//pipe.c
#include <stdio.h>
#include <unistd.h>
#define MSGSIZE 1024
char *msg1= "hello, world #1";
char *msg2= "hello, world #2";
char *msg3= "hello, world #3";
int main(){
char inbuf[MSGSIZE];
int fd[2], j, rv;

if (pipe(fd) == -1) {perror("pipe call"); exit(1);}

write(fd[1] , msg1, MSGSIZE);
write(fd[1], msg2, MSGSIZE);
write(fd[1], msg3, MSGSIZE);
for (j = 0; j < 3; j++) {
rv = read(fd[0], inbuf, MSGSIZE); 
inbuf[rv]=0;
//printf("%d\n",rv);
printf("%s\n", inbuf);
} 
}
//pipe2.c
#include <stdio.h>
#include <unistd.h>
#define MSGSIZE 1024
char *msg1= "hello, world #1";
char *msg2= "hello, world #2";
char *msg3= "hello, world #3";

int main(){
char inbuf[MSGSIZE];
int fd[2], j;
pid_t pid;
if (pipe(fd) == -1) {perror("pipe call"); exit(1);}
switch(pid = fork()) {
case -1 : perror("fork error"); exit(1);
case 0 : write(fd[1], msg1, MSGSIZE);
write(fd[1], msg2, MSGSIZE);
write(fd[1], msg3, MSGSIZE); break;
default : for (j = 0; j < 3; j++) {
read(fd[0], inbuf, MSGSIZE);
// inbuf[rv] = 0; 
printf("%s\n", inbuf);
}
wait(NULL);
} 
}

实验四

//ipc.h
/* 
 * Filename : ipc.h 
 * copyright : (C) 2006 by zhonghonglie 
 * Function : 声明 IPC 机制的函数原型和全局变量 
*/ 
#include <stdio.h> 
#include <stdlib.h> 
#include <sys/types.h> 
#include <sys/ipc.h> 
#include <sys/shm.h> 
#include <sys/sem.h> 
#include <sys/msg.h> 
#define BUFSZ 256 
 
//建立或获取 ipc 的一组函数的原型说明
int get_ipc_id(char *proc_file,key_t key); 
char *set_shm(key_t shm_key,int shm_num,int shm_flag); 
int set_msq(key_t msq_key,int msq_flag); 
int set_sem(key_t sem_key,int sem_val,int sem_flag); 
int down(int sem_id);
int up(int sem_id); 

/*信号灯控制用的共同体*/ 
typedef union semuns { 
 int val; 
} Sem_uns; 
/* 消息结构体*/ 
typedef struct msgbuf { 
 long mtype; 
 char mtext[1]; 
} Msg_buf; 
//生产消费者共享缓冲区即其有关的变量
static key_t buff_key; 
static int buff_num; 
static char *buff_ptr; 
//生产者放产品位置的共享指针
static key_t pput_key; 
static int pput_num; 
static int *pput_ptr; 
//消费者取产品位置的共享指针
static key_t cget_key; 
static int cget_num; 
static int *cget_ptr; 
//生产者有关的信号量
static key_t prod_key; 
static key_t pmtx_key; 
static int prod_sem; 
static int pmtx_sem; 
//消费者有关的信号量
static key_t cons_key; 
static key_t cmtx_key; 
static int cons_sem; 
static int cmtx_sem; 
 
static int sem_val; 
static int sem_flg; 
static int shm_flg; 


//ipc.c
/*
* Filename : ipc.c 
 * copyright : (C) 2006 by zhonghonglie 
 * Function : 一组建立 IPC 机制的函数 
*/ 
#include "ipc.h" 
/* 
 * get_ipc_id() 从/proc/sysvipc/文件系统中获取 IPC 的 id 号
 * pfile: 对应/proc/sysvipc/目录中的 IPC 文件分别为
 * msg-消息队列,sem-信号量,shm-共享内存
 * key: 对应要获取的 IPC 的 id 号的键值
*/ 
int get_ipc_id(char *proc_file,key_t key) 
{ 
 FILE *pf; 
 int i,j; 
 char line[BUFSZ],colum[BUFSZ]; 
 if((pf = fopen(proc_file,"r")) == NULL){ 
 perror("Proc file not open"); 
 exit(EXIT_FAILURE); 
 } 
 fgets(line, BUFSZ,pf); 
 while(!feof(pf)){ 
 i = j = 0; 
 fgets(line, BUFSZ,pf); 
 while(line[i] == ' ') i++; 
 while(line[i] !=' ') colum[j++] = line[i++]; 
 colum[j] = '\0'; 
 if(atoi(colum) != key) continue; 
 j=0; 
 while(line[i] == ' ') i++; 
 while(line[i] !=' ') colum[j++] = line[i++]; 
 colum[j] = '\0'; 
 i = atoi(colum); 
 fclose(pf); 
 return i; 
 } 
 fclose(pf); 
 return -1; 
} 
/* 
 * 信号灯上的 down/up 操作
 * semid:信号灯数组标识符
 * semnum:信号灯数组下标
 * buf:操作信号灯的结构
*/ 
int down(int sem_id)
{ 
 struct sembuf buf; 
 buf.sem_op = -1; 
 buf.sem_num = 0; 
 buf.sem_flg = SEM_UNDO; 
 if((semop(sem_id,&buf,1)) <0) { 
 perror("down error "); 
 exit(EXIT_FAILURE); 
 } 
 return EXIT_SUCCESS; 
} 
int up(int sem_id) 
{ 
 struct sembuf buf; 
 buf.sem_op = 1; 
 buf.sem_num = 0; 
 buf.sem_flg = SEM_UNDO; 
 if((semop(sem_id,&buf,1)) <0) { 
 perror("up error "); 
 exit(EXIT_FAILURE); 
 } 
 return EXIT_SUCCESS; 
} 
/* 
* set_sem 函数建立一个具有 n 个信号灯的信号量
* 如果建立成功,返回 一个信号灯数组的标识符 sem_id 
* 输入参数:
* sem_key 信号灯数组的键值
* sem_val 信号灯数组中信号灯的个数
* sem_flag 信号等数组的存取权限
*/ 
int set_sem(key_t sem_key,int sem_val,int sem_flg) 
{ 
 int sem_id; 
 Sem_uns sem_arg; 
 //测试由 sem_key 标识的信号灯数组是否已经建立
 if((sem_id = get_ipc_id("/proc/sysvipc/sem",sem_key)) < 0 ) 
 { 
 //semget 新建一个信号灯,其标号返回到 sem_id 
 if((sem_id = semget(sem_key,1,sem_flg)) < 0) 
 { 
 perror("semaphore create error"); 
 exit(EXIT_FAILURE); 
 }
 //设置信号灯的初值
 sem_arg.val = sem_val; 
 if(semctl(sem_id,0,SETVAL,sem_arg) <0) 
 { 
 perror("semaphore set error"); 
 exit(EXIT_FAILURE); 
 } 
 } 
 return sem_id; 
} 
/* 
* set_shm 函数建立一个具有 n 个字节 的共享内存区
* 如果建立成功,返回 一个指向该内存区首地址
* 的指针   shm_buf 
* 输入参数:
* shm_key 共享内存的键值
* shm_val 共享内存字节的长度
* shm_flag 共享内存的存取权限
*/ 
char * set_shm(key_t shm_key,int shm_num,int shm_flg) 
{ 
 int i,shm_id; 
 char * shm_buf; 
 //测试由 shm_key 标识的共享内存区是否已经建立
 if((shm_id = get_ipc_id("/proc/sysvipc/shm",shm_key)) < 0 ) 
 { 
 //shmget 新建 一个长度为 shm_num 字节的共享内存,其标号返回到 shm_id 
 if((shm_id = shmget(shm_key,shm_num,shm_flg)) <0) 
 { 
 perror("shareMemory set error"); 
 exit(EXIT_FAILURE); 
 } 
 //shmat 将由 shm_id 标识的共享内存附加给指针   shm_buf 
 if((shm_buf = (char *)shmat(shm_id,0,0)) < (char *)0) 
 { 
 perror("get shareMemory error"); 
 exit(EXIT_FAILURE); 
 } 
 for(i=0; i<shm_num; i++) shm_buf[i] = 0; //初始为 0 
 } 
 //shm_key 标识的共享内存区已经建立,将由 shm_id 标识的共享内存附加给指针  shm_buf 
 if((shm_buf = (char *)shmat(shm_id,0,0)) < (char *)0) 
 { 
 perror("get shareMemory error");
 exit(EXIT_FAILURE); 
 } 
 return shm_buf; 
} 
/* 
* set_msq 函数建立一个消息队列
* 如果建立成功,返回 一个消息队列的标识符 msq_id 
* 输入参数:
* msq_key 消息队列的键值
* msq_flag 消息队列的存取权限
*/ 
int set_msq(key_t msq_key,int msq_flg) 
{ 
 int msq_id; 
 //测试由 msq_key 标识的消息队列是否已经建立
 if((msq_id = get_ipc_id("/proc/sysvipc/msg",msq_key)) < 0 ) 
 { 
 //msgget 新建一个消息队列,其标号返回到 msq_id 
 if((msq_id = msgget(msq_key,msq_flg)) < 0) 
 { 
 perror("messageQueue set error"); 
 exit(EXIT_FAILURE); 
 } 
 } 
 return msq_id; 
} 

//producer.c
/* 
 * Filename : producer.c 
 * copyright : (C) 2006 by zhonghonglie 
 * Function : 建立并模拟生产者进程
*/ 
#include "ipc.h" 
int main(int argc,char *argv[]) 
{ 
 int rate; 
 int producerid=atoi(argv[1]);
 //可在在命令行第一参数指定一个进程睡眠秒数,以调解进程执行速度
 if(argv[1] != NULL) rate = atoi(argv[1]); 
 else rate = 3; //不指定为 3 秒
 //共享内存使用的变量
buff_key = 101;//缓冲区任给的键值
 buff_num = 8;//缓冲区任给的长度
 pput_key = 102;//生产者放产品指针的键值
 pput_num = 1; //指针数
 shm_flg = IPC_CREAT | 0644;//共享内存读写权限
 //获取缓冲区使用的共享内存,buff_ptr 指向缓冲区首地址
 buff_ptr = (char *)set_shm(buff_key,buff_num,shm_flg); 
 //获取生产者放产品位置指针 pput_ptr 
 pput_ptr = (int *)set_shm(pput_key,pput_num,shm_flg); 
 
 //信号量使用的变量
 prod_key = 201;//生产者同步信号灯键值
 pmtx_key = 202;//生产者互斥信号灯键值
 cons_key = 301;//消费者同步信号灯键值
 cmtx_key = 302;//消费者互斥信号灯键值
 sem_flg = IPC_CREAT | 0644; 
 //生产者同步信号灯初值设为缓冲区最大可用量
 sem_val = buff_num; 
 //获取生产者同步信号灯,引用标识存 prod_sem 
 prod_sem = set_sem(prod_key,sem_val,sem_flg); 
 //消费者初始无产品可取,同步信号灯初值设为 0 
 sem_val = 0; 
 //获取消费者同步信号灯,引用标识存 cons_sem 
 cons_sem = set_sem(cons_key,sem_val,sem_flg); 
 //生产者互斥信号灯初值为 1 
 sem_val = 1; 
 //获取生产者互斥信号灯,引用标识存 pmtx_sem 
 pmtx_sem = set_sem(pmtx_key,sem_val,sem_flg); 
 
  if(producerid==0){
  buff_ptr[0]='D';
  *pput_ptr=0;
 }
 //循环执行模拟生产者不断放产品 
 while(1){ 
 //如果缓冲区满则生产者阻塞
 //down(prod_sem); 
 //如果另一生产者正在放产品,本生产者阻塞
 //down(pmtx_sem); 
 //用写一字符的形式模拟生产者放产品,报告本进程号和放入的字符及存放的位置
 //buff_ptr[*pput_ptr] = 'A'+ *pput_ptr; 
 //sleep(rate); 
 //printf("%d producer put: %c to Buffer[%d]\n",getpid(),buff_ptr[*pput_ptr],*pput_ptr);
 //存放位置循环下移
 //*pput_ptr = (*pput_ptr+1) % buff_num; 
 //唤醒阻塞的生产者
 //up(pmtx_sem); 
 //唤醒阻塞的消费者
 //up(cons_sem); 
 
 
   if(buff_ptr[0]-'D'==producerid){
   down(prod_sem);
   down(pmtx_sem);
   *pput_ptr = (*pput_ptr+1)%3;
   if(*pput_ptr==0){
    buff_ptr[0] = 'A';
    printf("%d The producer gives tobacco and paper\n",getpid());
   }
   if(*pput_ptr==1){
    buff_ptr[0] = 'B';
    printf("%d The producer gives tobacco and glue\n",getpid());
   }
   if(*pput_ptr==2){
    buff_ptr[0] = 'C';
    printf("%d The producer gives glue and paper\n",getpid());
   }
   sleep(rate);
   up(pmtx_sem);
   up(cons_sem);
  }
 
 } 
 return EXIT_SUCCESS; 
} 
//smoker.c
/* 
 Filename : consumer.c 
 copyright : (C) by zhanghonglie 
 Function : 建立并模拟smoker进程
*/ 
#include "ipc.h" 
int main(int argc,char *argv[]) 
{ 
 int rate; 
 //可在在命令行第一参数指定一个进程睡眠秒数,以调解进程执行速度
 if(argv[1] != NULL) rate = atoi(argv[1]); 
 else rate = 3; //不指定为 3 秒
 //共享内存 使用的变量
 buff_key = 101; //缓冲区任给的键值
 buff_num = 8; //缓冲区任给的长度
 cget_key = 103; //消费者取产品指针的键值
 cget_num = 1; //指针数
 shm_flg = IPC_CREAT | 0644; //共享内存读写权限
 //获取缓冲区使用的共享内存,buff_ptr 指向缓冲区首地址
 buff_ptr = (char *)set_shm(buff_key,buff_num,shm_flg); 
 //获取消费者取产品指针,cget_ptr 指向索引地址
 cget_ptr = (int *)set_shm(cget_key,cget_num,shm_flg); 
 //信号量使用的变量
 prod_key = 201; //生产者同步信号灯键值
 pmtx_key = 202; //生产者互斥信号灯键值
 cons_key = 301; //消费者同步信号灯键值
 cmtx_key = 302; //消费者互斥信号灯键值
 sem_flg = IPC_CREAT | 0644; //信号灯操作权限
//生产者同步信号灯初值设为缓冲区最大可用量
 sem_val = buff_num; 
 //获取生产者同步信号灯,引用标识存 prod_sem 
 prod_sem = set_sem(prod_key,sem_val,sem_flg); 
 //消费者初始无产品可取,同步信号灯初值设为 0 
 sem_val = 0; 
 //获取消费者同步信号灯,引用标识存 cons_sem 
 cons_sem = set_sem(cons_key,sem_val,sem_flg); 
 //消费者互斥信号灯初值为 1 
 sem_val = 1; 
 //获取消费者互斥信号灯,引用标识存 pmtx_sem 
 cmtx_sem = set_sem(cmtx_key,sem_val,sem_flg); 
 
 /**
  if(consumerid==0)
  *cget_ptr=0;
 */
 
 //循环执行模拟消费者不断取产品 
 while(1){ 
 //如果无产品消费者阻塞
 down(cons_sem); 
 //如果另一消费者正在取产品,本消费者阻塞
 down(cmtx_sem); 
 //用读一字符的形式模拟消费者取产品,报告本进程号和获取的字符及读取的位置
 
 sleep(rate); 
 //printf("%d consumer get: %c from B Buffer[%d]\n",getpid(),buff_ptr[*cget_ptr],*cget_ptr); 
 //读取位置循环下移
 //*cget_ptr = (*cget_ptr+1) % buff_num; 
 
 
   if(buff_ptr[0]-'A'==consumerid){
   down(cons_sem);
   down(cmtx_sem);
   sleep(rate);
   if(buff_ptr[0]=='A'){
    printf("%d The consumer has 胶水.\nThe consumer gets 烟草 and paper\n",getpid());
   }
   if(buff_ptr[0]=='B'){
    printf("%d The smoker has 纸.\nThe consumer gets 烟草 and glue\n",getpid());
   }
            if(buff_ptr[0]=='C'){
    printf("%d The consumer has 烟草.\nThe consumer gets glue and paper\n",getpid());
   }
   *cget_ptr = (*cget_ptr+1);
   if(*cget_ptr%2==0)
    buff_ptr[0]='D';
   else
    buff_ptr[0]='E';
 
 
 //唤醒阻塞的消费者
 up(cmtx_sem); 
 //唤醒阻塞的生产者
 up(prod_sem); 
 } 
 }
 return EXIT_SUCCESS; 
}


//ipc.h
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/sem.h>
#include <sys/msg.h>

#define BUFSZ   256    //建立或获取 ipc 的一组函数的原型说明

int get_ipc_id(char *proc_file,key_t key);
char *set_shm(key_t shm_key,int shm_num,int shm_flag);
int set_msq(key_t msq_key,int msq_flag);
int set_sem(key_t sem_key,int sem_val,int sem_flag);
int down(int sem_id);
int up(int sem_id);

/*信号灯控制用的共同体*/
typedef union semuns {
    int val;
} Sem_uns;

/* 消息结构体*/
typedef struct msgbuf {
    long mtype;
    char mtext[1];
} Msg_buf;

//生产消费者共享缓冲区即其有关的变量
static key_t buff_key;  static int buff_num;  static char *buff_ptr;

//生产者放产品位置的共享指针
static key_t pput_key;  static int pput_num;
static int *pput_ptr;

//消费者取产品位置的共享指针
static key_t cget_key;
static int cget_num;
static int *cget_ptr;
static int buff_num;
static int pput_num;
static int buff_number;
static int pput_number;
static int cget_number;

static key_t pput_h;
static key_t prod_h;
static key_t pmtx_h;
static key_t cons_h;
static key_t cmtx_h;

static key_t buff_h;
static key_t cget_h;

//生产者有关的信号量
static key_t prod_key;
static key_t pmtx_key;
static int prod_sem;
static int pmtx_sem;

//消费者有关的信号量
static key_t cons_key;
static key_t cmtx_key;
static int cons_sem;
static int cmtx_sem;
static int sem_val;
static int sem_flg;
static int shm_flg;


//ipc.c
/*
* Filename : ipc.c 
 * copyright : (C) 2006 by zhonghonglie 
 * Function : 一组建立 IPC 机制的函数 
*/ 
#include "ipc.h" 
/* 
 * get_ipc_id() 从/proc/sysvipc/文件系统中获取 IPC 的 id 号
 * pfile: 对应/proc/sysvipc/目录中的 IPC 文件分别为
 * msg-消息队列,sem-信号量,shm-共享内存
 * key: 对应要获取的 IPC 的 id 号的键值
*/ 
int get_ipc_id(char *proc_file,key_t key) 
{ 
 FILE *pf; 
 int i,j; 
 char line[BUFSZ],colum[BUFSZ]; 
 if((pf = fopen(proc_file,"r")) == NULL){ 
 perror("Proc file not open"); 
 exit(EXIT_FAILURE); 
 } 
 fgets(line, BUFSZ,pf); 
 while(!feof(pf)){ 
 i = j = 0; 
 fgets(line, BUFSZ,pf); 
 while(line[i] == ' ') i++; 
 while(line[i] !=' ') colum[j++] = line[i++]; 
 colum[j] = '\0'; 
 if(atoi(colum) != key) continue; 
 j=0; 
 while(line[i] == ' ') i++; 
 while(line[i] !=' ') colum[j++] = line[i++]; 
 colum[j] = '\0'; 
 i = atoi(colum); 
 fclose(pf); 
 return i; 
 } 
 fclose(pf); 
 return -1; 
} 
/* 
 * 信号灯上的 down/up 操作
 * semid:信号灯数组标识符
 * semnum:信号灯数组下标
 * buf:操作信号灯的结构
*/ 
int down(int sem_id)
{ 
 struct sembuf buf; 
 buf.sem_op = -1; 
 buf.sem_num = 0; 
 buf.sem_flg = SEM_UNDO; 
 if((semop(sem_id,&buf,1)) <0) { 
 perror("down error "); 
 exit(EXIT_FAILURE); 
 } 
 return EXIT_SUCCESS; 
} 
int up(int sem_id) 
{ 
 struct sembuf buf; 
 buf.sem_op = 1; 
 buf.sem_num = 0; 
 buf.sem_flg = SEM_UNDO; 
 if((semop(sem_id,&buf,1)) <0) { 
 perror("up error "); 
 exit(EXIT_FAILURE); 
 } 
 return EXIT_SUCCESS; 
} 
/* 
* set_sem 函数建立一个具有 n 个信号灯的信号量
* 如果建立成功,返回 一个信号灯数组的标识符 sem_id 
* 输入参数:
* sem_key 信号灯数组的键值
* sem_val 信号灯数组中信号灯的个数
* sem_flag 信号等数组的存取权限
*/ 
int set_sem(key_t sem_key,int sem_val,int sem_flg) 
{ 
 int sem_id; 
 Sem_uns sem_arg; 
 //测试由 sem_key 标识的信号灯数组是否已经建立
 if((sem_id = get_ipc_id("/proc/sysvipc/sem",sem_key)) < 0 ) 
 { 
 //semget 新建一个信号灯,其标号返回到 sem_id 
 if((sem_id = semget(sem_key,1,sem_flg)) < 0) 
 { 
 perror("semaphore create error"); 
 exit(EXIT_FAILURE); 
 }
 //设置信号灯的初值
 sem_arg.val = sem_val; 
 if(semctl(sem_id,0,SETVAL,sem_arg) <0) 
 { 
 perror("semaphore set error"); 
 exit(EXIT_FAILURE); 
 } 
 } 
 return sem_id; 
} 
/* 
* set_shm 函数建立一个具有 n 个字节 的共享内存区
* 如果建立成功,返回 一个指向该内存区首地址
* 的指针   shm_buf 
* 输入参数:
* shm_key 共享内存的键值
* shm_val 共享内存字节的长度
* shm_flag 共享内存的存取权限
*/ 
char * set_shm(key_t shm_key,int shm_num,int shm_flg) 
{ 
 int i,shm_id; 
 char * shm_buf; 
 //测试由 shm_key 标识的共享内存区是否已经建立
 if((shm_id = get_ipc_id("/proc/sysvipc/shm",shm_key)) < 0 ) 
 { 
 //shmget 新建 一个长度为 shm_num 字节的共享内存,其标号返回到 shm_id 
 if((shm_id = shmget(shm_key,shm_num,shm_flg)) <0) 
 { 
 perror("shareMemory set error"); 
 exit(EXIT_FAILURE); 
 } 
 //shmat 将由 shm_id 标识的共享内存附加给指针   shm_buf 
 if((shm_buf = (char *)shmat(shm_id,0,0)) < (char *)0) 
 { 
 perror("get shareMemory error"); 
 exit(EXIT_FAILURE); 
 } 
 for(i=0; i<shm_num; i++) shm_buf[i] = 0; //初始为 0 
 } 
 //shm_key 标识的共享内存区已经建立,将由 shm_id 标识的共享内存附加给指针  shm_buf 
 if((shm_buf = (char *)shmat(shm_id,0,0)) < (char *)0) 
 { 
 perror("get shareMemory error");
 exit(EXIT_FAILURE); 
 } 
 return shm_buf; 
} 
/* 
* set_msq 函数建立一个消息队列
* 如果建立成功,返回 一个消息队列的标识符 msq_id 
* 输入参数:
* msq_key 消息队列的键值
* msq_flag 消息队列的存取权限
*/ 
int set_msq(key_t msq_key,int msq_flg) 
{ 
 int msq_id; 
 //测试由 msq_key 标识的消息队列是否已经建立
 if((msq_id = get_ipc_id("/proc/sysvipc/msg",msq_key)) < 0 ) 
 { 
 //msgget 新建一个消息队列,其标号返回到 msq_id 
 if((msq_id = msgget(msq_key,msq_flg)) < 0) 
 { 
 perror("messageQueue set error"); 
 exit(EXIT_FAILURE); 
 } 
 } 
 return msq_id; 
} 

//consumer.c
#include "ipc.h"
int main(int argc,char *argv[]) {
 int rate = 1;
 int consumerid=atoi(argv[1]);
 
 buff_h = 101;
 buff_number = 8;
 cget_h = 103;
 cget_number = 1;
 shm_flg = IPC_CREAT | 0644;
 
 buff_ptr = (char *)set_shm(buff_h,buff_number,shm_flg);
 cget_ptr = (int *)set_shm(cget_h,cget_number,shm_flg);
 
 prod_h = 201;
 pmtx_h = 202;
 cons_h = 301;
 cmtx_h = 302;
 sem_flg = IPC_CREAT | 0644;
 
 sem_val = buff_number;
 prod_sem = set_sem(prod_h,sem_val,sem_flg);
 sem_val = 0;
 cons_sem = set_sem(cons_h,sem_val,sem_flg);
 sem_val = 1;
 cmtx_sem = set_sem(cmtx_h,sem_val,sem_flg);
 
 if(consumerid==0)
  *cget_ptr=0;
 while(1){
  if(buff_ptr[0]-'A'==consumerid){
   down(cons_sem);
   down(cmtx_sem);
   sleep(rate);
   if(buff_ptr[0]=='A'){
    printf("%d 第一个smoker拥有烟草,producer给纸和胶水,卷烟吸烟\n",getpid());
   }
   if(buff_ptr[0]=='B'){
    printf("%d 第二个smoker拥有纸张,拿着producer给的烟草和胶水,卷烟吸烟\n",getpid());
   }
   if(buff_ptr[0]=='C'){
    printf("%d 第三个smoker拥有胶水,拿着producer给的纸和烟草,卷烟吸烟\n",getpid());
   }
   *cget_ptr = (*cget_ptr+1);
   if(*cget_ptr%2==0)
    buff_ptr[0]='D';
   else
    buff_ptr[0]='E';
   up(cmtx_sem);
   up(prod_sem);
  }
 }
 return EXIT_SUCCESS;
}


//producer.c
#include "ipc.h"
int main(int argc,char *argv[]){
 int rate=1;
 int producerid=atoi(argv[1]);
 
 buff_h=101;
 buff_number=8;
 pput_h=102;
 pput_number=1;
 shm_flg=IPC_CREAT|0644;
 
 buff_ptr = (char *)set_shm(buff_h,buff_number,shm_flg);
 pput_ptr = (int *)set_shm(pput_h,pput_number,shm_flg);
 prod_h = 201;
 pmtx_h = 202;
 cons_h = 301;
 cmtx_h = 302;
 sem_flg = IPC_CREAT|0644;
 
 sem_val = buff_number;
 prod_sem = set_sem(prod_h,sem_val,sem_flg);
 sem_val = 0;
 cons_sem = set_sem(cons_h,sem_val,sem_flg);
 sem_val = 1;
 pmtx_sem = set_sem(pmtx_h,sem_val,sem_flg);
 if(producerid==0){
  buff_ptr[0]='D';
  *pput_ptr=0;
 }
 while(1){
  if(buff_ptr[0]-'D'==producerid){
   down(prod_sem);
   down(pmtx_sem);
   *pput_ptr = (*pput_ptr+1)%3;
   if(*pput_ptr==0){
    buff_ptr[0] = 'A';
    printf("%d producer提供烟草和纸\n",getpid());
   }
   if(*pput_ptr==1){
    buff_ptr[0] = 'B';
    printf("%d producer提供烟草和胶水\n",getpid());
   }
   if(*pput_ptr==2){
    buff_ptr[0] = 'C';
    printf("%d producer提供纸和胶水\n",getpid());
   }
   sleep(rate);
   up(pmtx_sem);
   up(cons_sem);
  }
 }
 return EXIT_SUCCESS;
}
//makefile
hdrs = ipc.h 
opts = -g -c 
c_src = consumer.c ipc.c 
c_obj = consumer.o ipc.o 
p_src = producer.c ipc.c 
p_obj = producer.o ipc.o 
all: producer consumer 
consumer: $(c_obj) 
	gcc $(c_obj) -o consumer 
consumer.o: $(c_src) $(hdrs) 
	gcc $(opts) $(c_src) 
 
producer: $(p_obj) 
	gcc $(p_obj) -o producer 
producer.o: $(p_src) $(hdrs) 
	gcc $(opts) $(p_src) 
clean: 
	rm consumer producer *.o 

实验五

//vmrp.cc

#include <iostream>
#include <stdlib.h>
using namespace std;
void LFU_Agorithm();
double Page_Loss_Rate(int, int);
int Find_Exist(int*, int, int);
int Find_LeastInteviewTime(int, int, int*, int);
void Update_InHereTime(int*, int, int);
int Find_LeastNotUseTime(int, int, int*);
int Find_LeastNotInterviewTime(int, int*);
void Print_Frame(int*, int);
void Print_Menu();

int main()
{

	LFU_Agorithm();
	return 0;
}

/*
* 用于遍历 save_Frame[] 的 n 个存储页框, 是否有 “待定地址 -> addr”
* 如果有就返回 ture, 否则返回 false
*/
int Find_Exist(int* save_Frame, int n, int addr)
{
	for (int i = 0; i < n; i++)
	{
		if (save_Frame[i] == addr)
		{
			return i;
		}
	}
	return -1;
}

void Print_Menu()
{
	/* 输入模块 */
	cout << "+---------------------------------------+" << endl;
	cout << "|\t***算法清单***\t\t\t|" << endl;
	cout << "|\t1.最佳置换算法(OPT)\t\t|" << endl << "|\t2.先进先出算法(FIFO)\t\t|" << endl;
	cout << "|\t3.最近最久未使用算法(LRU)\t|" << endl << "|\t4.最不经常使用算法(LFU)\t\t|" << endl;
	cout << "|\t0.退出\t\t\t\t|" << endl;
	cout << "+---------------------------------------+" << endl;
}

void Print_Frame(int* save_Frame, int n)
{
	cout << "\t";
	for (int i = 0; i < n; i++)
	{
		if (i == 0)
		{
			if (save_Frame[i] == -999)
				cout << "/ /";
			else
				cout << "/" << save_Frame[i] << "/";
		}
		else
		{
			if (save_Frame[i] == -999)
				cout << " /";
			else
				cout << save_Frame[i] << "/";
		}
	}
	cout << endl;
}
void Init(int* n, int* len, int*& save_Frame, int*& interview_Array)
{
	cout << "请输入页帧数 n :";
	cin >> *n;
	save_Frame = new int[*n];
	for (int i = 0; i < *n; i++)
		save_Frame[i] = -999;

	cout << "请输入引用页数:";
	cin >> *len;
	cout << "请输入引用串:";
	interview_Array = new int[*len];
	for (int i = 0; i < *len; i++)
		cin >> interview_Array[i];
}

/*
* 缺页中断率:
* 假设进程 P 在运行中成功的内存访问次数为 s
* 不成功的访问次数为 F,则缺页中断率为 R = F/(S+F)
*/
double Page_Loss_Rate(int S, int F)
{
	double ans = 1.0 * F / (1.0 * S + 1.0 * F) * 100;
	return ans;
}

int Find_LeastInteviewTime(int sta, int addr, int* interview_Array, int len)
{
	for (int i = sta; i < len; i++)
	{
		if (interview_Array[i] == addr)
		{
			return i - sta;
		}
	}
	return 99999;
}

void Update_InHereTime(int* in_HereTime, int n, int ind)
{
	for (int i = 0; i < n; i++)
	{
		in_HereTime[i]++;
	}
	if (ind != -1)
		in_HereTime[ind] = 0;
}

int Find_LeastNotUseTime(int end, int addr, int* interview_Array)
{
	for (int i = end - 1; i >= 0; i--)
	{
		if (interview_Array[i] == addr)
		{
			// cout << " i = " << i << endl;
			return end - i;
		}
	}
	return 99999;
}

int Find_LeastNotInterviewTime(int n, int* interview_Time)
{
	int min_Time = 99999;
	int ind;
	for (int i = 0; i < n; i++)
	{
		if (interview_Time[i] < min_Time)
		{
			min_Time = interview_Time[i];
			ind = i;
		}
	}
	return ind;
}
/*
* 最不经常使用算法(LFU):
* 即选择最近一段时间内最长时间没有被访问过的页面进行置换
* 数据结构:数组
* 第一行输入参数:n ,代表存储页框数
* 第二行输入参数:a_1、a_2、...、a_n,代表访问地址的走向
* 输出要求:输出内存驻留的页面集合,缺页次数以及缺页率;
*/
void LFU_Agorithm()
{
	int n, len, * save_Frame = NULL, * interview_Array = NULL;
	Init(&n, &len, save_Frame, interview_Array);

	int* interview_Time = new int[n];
	for (int i = 0; i < n; i++)
		interview_Time[i] = 0;

	// 测试样例一:4 3 12 2 3 2 1 5 2 4 5 3 2 5 2
	// 测试样例二:4 3 12 2 3 2 1 2 1 5 4 2 4 4 6
	int addr;
	int cnt = 0;
	int score = 0;
	int fail_time = 0;
	int iter = 0;
	while (iter < len)
	{
		cout << endl << "第" << iter << "轮:";
		addr = interview_Array[iter];
		iter++;
		if (cnt < n)
		{
			if (Find_Exist(save_Frame, cnt, addr) != -1)
			{
				score++;
				cout << "\"" << addr << "\" 被命中了\t\t------->";
				Print_Frame(save_Frame, n);
				int ind = Find_Exist(save_Frame, cnt, addr);
				interview_Time[ind]++;
			}
			else // 未命中,但有空间
			{
				fail_time++;
				cout << "未命中," << "\"" << addr << "\" 被装入 \t------->";
				save_Frame[cnt] = addr;
				Print_Frame(save_Frame, n);
				cnt++;
			}
		}
		else
		{
			if (Find_Exist(save_Frame, n, addr) != -1)
			{
				score++;
				cout << "\"" << addr << "\" 被命中了\t\t------->";
				Print_Frame(save_Frame, n);
				int ind = Find_Exist(save_Frame, n, addr);
				interview_Time[ind]++;
			}
			else // 未命中,但没了空间
			{
				fail_time++;
				int index = Find_LeastNotInterviewTime(n, interview_Time);
				cout << "\"" << addr << "\" 替换了 \"" << save_Frame[index] << "\"\t\t------->";
				save_Frame[index] = addr;
				interview_Time[index] = 0;
				Print_Frame(save_Frame, n);
			}
		}
	}
	cout << endl;
	cout << "缺页次数为:" << fail_time << endl;
	cout << "缺页中断率 R = " << Page_Loss_Rate(score, fail_time) << "%" << endl;
	delete[] save_Frame;
	delete[] interview_Array;
	delete[] interview_Time;
}

//vmrp2.cc
//改进:
#include <iostream>
#include <time.h>
 
using namespace std;
 
//封装页面帧
struct Tem {
	int data;
	int sign;
};
//计算缺页率
double count(double sum,int num) {
	//其中sum为缺页总次数,num为引用串页面的总数
	return sum / num * 100;//将其乘以100,得到百分比的大小
}
//FIFO页面置换算法
double fifo(int* page, Tem* tem, int num, int size) {
	//page数组表示页帧块组,tem数组表示页面引用串
	//num表示页面引用串的页面总数,size表示页面帧的数量
	int n = 0, s = 0,res,flag;
	//n用来记录已占用的页面帧的数量,s用来给页面的标志位赋值,代表来到页面帧的顺序
	//flag标志在页面帧中是否存在,1表示存在,0表示不存在;
	//res用来表示当页面帧满时,FIFO页面置换算法将要换掉的页面帧标号
	double sum = 0;//sum为缺页总数,先初始化为0
	for (int i = 0; i < num; i++) {
		flag = 0;
		//当已占用的页面帧的数量为0,不用去判断页面是否存在
		if (n == 0) {    
			tem[i].data = page[i];
			tem[i].sign = s;
			n++;
			s++;
			cout << endl << "此时存在一些页帧为空,页面" << page[i] << "放入第" << n << "个页帧中" << endl;
			sum++;
		}
		else {//页面帧中已有页面存在
			//循环遍历看页面是否已存在
			for (int j = 0; j < n; j++) {
				if (tem[j].data == page[i]) {
					flag = 1;
					cout << endl << "页面" << page[i] << "已存在" << endl;
					break;
				}
			}
			//页面不在页面帧中
			if (flag == 0) {
				//判断页面帧是否还有空
				if (n < size) {  //页面帧中还有空余帧
					tem[n].data = page[i];
					tem[n].sign = s;
					n++;
					s++;
					cout << endl << "此时存在一些页帧为空,页面" << page[i] << "放入第" << n << "个页帧中" << endl;
					sum++;
				}
				else {//页面帧没有空余帧,需要进行换页
					Tem* t = new Tem;
					int min=1000;
					//循环遍历页面帧中页面的标志位,标志越小表示越早到达页面帧
					for (int p = 0; p < n ; p++) {
						if (tem[p].sign < min) {
							min=tem[p].sign;
							res = p;
						}
						t = &tem[res];
					}
					cout << endl << "此时各页帧均满,换出页面" << t->data << ",并将页面" << page[i] << "放入第" << res + 1 << "个页帧中" << endl;
					sum++;
					t->data = page[i];
					t->sign = s;
					s++;
				}
			}
		}
	}
	return sum;
}
//LRU页面置换算法
double lru(int* page, Tem* tem, int num, int size){
	//page数组表示页帧块组,tem数组表示页面引用串
	//num表示页面引用串的页面总数,size表示页面帧的数量
	int n = 0, s = 0, flag;
	//n用来记录已占用的页面帧的数量,s用来给页面的标志位赋值,代表来到页面帧的顺序
	//flag标志在页面帧中是否存在,1表示存在,0表示不存在;
	double sum = 0;
	for (int i = 0; i < num; i++) {
		//当已占用的页面帧的数量为0,不用去判断页面是否存在
		flag = 0;
		if (n == 0) {
			tem[i].data = page[i];
			n++;
			cout << endl << "此时存在一些页帧为空,页面" << page[i] << "放入第" << n << "个页帧中" << endl;
			sum++;
		}
		else {//页面帧中已有页面存在
			//循环遍历看页面是否已存在
			for (int j = 0; j < n; j++) {
				if (tem[j].data == page[i]) {
					flag = 1;
					cout << endl << "页面" << page[i] << "已存在" << endl;
					break;
				}
			}
			//页面不在页面帧中
			if (flag == 0) {
				//判断页面帧是否还有空
				if (n < size) {         //页面帧中还有空余帧
					tem[n].data = page[i];
					n++;
					cout << endl << "此时存在一些页帧为空,页面" << page[i] << "放入第" << n << "个页帧中" << endl;
					sum++;
				}
				else {      //页面帧没有空余帧,需要进行换
					int ren = 0, m;
					for (int p = 0; p < size; p++)    //循环将页面帧中的页面标志位置为0,默认为前面未使用
						tem[p].sign = 0;
					//从当前页面前面开始循环遍历之前的页面引用串
					for (int q = i - 1; q >= 0; q--) {
						for (m = 0; m < size; m++) {
							//比较页面串和页面帧中的数据是否相等且标志位是否为0
							if (page[q] == tem[m].data && tem[m].sign == 0) {
								tem[m].sign = 1;
								ren++;
								break;
							}
						}
						//当发现页面帧中的某个页面是页面串之前最早使用到的,退出循环遍历
						if (ren == size)
							break;
					}
					//当遍历循环结束,发现页面帧中的某些页面是页面串中之前没有使用到的
				if (ren < size) {
						//循环遍历页面帧中第一个在之前没有使用到的页面
						for (m = 0; m < size; m++) {
							if (tem[m].sign == 0)
								break;
						}
					}
					cout << endl << "此时各页帧均满,换出页面" << tem[m].data << ",并将页面" << page[i] << "放入第" << m + 1 << "个页帧中" << endl;
					tem[m].data = page[i];
					sum++;
				}
			}
		}
	}
	return sum;
}
 
int main() {
	int num, size;
	double sum, percent;
	cout << "请输入页面应用串的大小:";
	cin >> num;
	int page[30];
	Tem tem[7];
	srand((unsigned int)time(NULL));
	for (int i = 0; i < num; i++) {
		page[i] = rand() % 10;
	}
	cout << "随机产生的页面引用串为:";
	for (int i = 0; i < num; i++)
		cout << page[i] << " ";
	cout <<endl<< "页帧数为:";
	cin >> size;
	cout << endl << "*****************FIFO页面置换算法******************" << endl;
	sum=fifo(page, tem, num, size);
	cout << endl << "缺页次数为:" << sum << endl;
	cout << endl << "缺页率为:" << count(sum, num) <<"%"<< endl;
	cout << endl << "*****************LRU页面置换算法******************" << endl;
	sum = lru(page, tem, num, size);
	cout << endl << "缺页次数为:" << sum << endl;
	cout << endl << "缺页率为:" << count(sum, num) << "%" << endl;
	return 0;
}

实验六

//dask.h
/*
*Filename: dask.h
*copyright: (C)2006 by zhonghonglie
*Function︰声明磁盘移臂调度类 98 183 37 122 14 124 65 67
*/
#include <iostream>
#include <iomanip>
#include <malloc.h>

class DiskArm{
public:
  DiskArm();
  ~DiskArm();
  void InitSpace(char * MethodName);//初始化寻道记录
  void Report(void);//报告算法执行情况
  void Fcfs(void); //先来先服务算法
  void Sstf(void);//最短寻道时间优先算法
  void Scan(void); //电梯调度算法
  void CScan(void);//均匀电梯调度算法 循环扫描算法
  void Look(void); //LOOK调度算法
private:
  int *Request;//磁盘请求道号
  int *Cylinder;//工作柱面道号号
  int RequestNumber;//磁盘请求数
  int CurrentCylinder;//当前道号
  int SeekDirection;//磁头方向 输入 0 表示向小道号移动,1 表示向大道号移动
  int SeekNumber;//移臂总数
  int SeekChang;//磁头调头数
};

//dask.cc
/*
*Filename: dask.cc
*copyright: (C)2006 by zhonghonglie
*Function:磁盘移臂调度算法
*/
#include "dask.h"
using namespace std;

// 排序
void sort(int array[],int len)
{
    int i = 0, j = 0;
    int temp = 0;
    for (i = 0; i < len-1; i++)
    {
        for (j = i+1; j < len; j++)
        {
            if (array[j]<array[i])
            {
                temp = array[i];
                array[i] = array[j];
                array[j] = temp;
            }
        }
    }
}
/*
//随机生成内容
DiskArm::DiskArm(){

  srand(time(0));
  int i;
  //输入当前道号
  //cout<<"Please input Current cylinder :";
  CurrentCylinder = (rand() % (1000-0+1)) + 0;//0—1000闭区间
  //磁头方向,输入0表示向小道号移动,1表示向大道号移动
  //cout<< "Please input Current Direction (O/1) :" ;
  SeekDirection = rand()%2;
  //输入磁盘请求数,请求道号
  //cout<<"Please input Request Numbers :";
  RequestNumber = (rand() % (20-0+1))+ 0;//0-20
  //cout<< "Please input Request cylinder string :";
  Request = new int[sizeof(int)* RequestNumber];
  Cylinder = new int[sizeof(int)* RequestNumber];
  for (i= 0; i< RequestNumber; i++){
    Request[i] = (rand() % (1000-0+1))+ 0;//0-1000
  }
  cout<<"随机生成的当前道号:"<<CurrentCylinder<<"随机生成的词头方向(0 表示向小道号移动,1 表示向大道号移动):"<<SeekDirection<<endl;
  cout<<"随机生成的磁盘请求数:"<<RequestNumber<<endl<<"随机生成的磁盘请求道号数组:";
  for(i = 0;i < RequestNumber;i++){
  cout<<Request[i]<<" ";}
  cout<<endl;
}
*/

//需要输入的构造函数
DiskArm::DiskArm(){
  int i;
  //输入当前道号
  cout<<"Please input Current cylinder :";
  cin>> CurrentCylinder;
  //磁头方向,输入0表示向小道号移动,1表示向大道号移动
  cout<< "Please input Current Direction (O/1) :" ;
  cin >> SeekDirection;
  //输入磁盘请求数,请求道号
  cout<<"Please input Request Numbers :";
  cin >> RequestNumber;
  cout<< "Please input Request cylinder string :";
  Request = new int[sizeof(int)* RequestNumber];
  Cylinder = new int[sizeof(int)* RequestNumber];
  for (i= 0; i< RequestNumber; i++)
    cin >> Request[i];
}


DiskArm::~DiskArm(){}

//初始化道号,寻道记录
void DiskArm::InitSpace(char * MethodName)
{
  int i;
  cout <<endl <<MethodName <<endl;
  SeekNumber= 0;
  SeekChang = 0;
  for (i= 0; i< RequestNumber; i++)
  Cylinder[i]=Request[i];
}

//统计报告算法执行情况
void DiskArm::Report(void){
  cout << endl;
  cout <<"Seek Number: " << SeekNumber << endl;
  cout <<"Chang Direction: " <<SeekChang <<endl <<endl;
}

//先来先服务算法
void DiskArm::Fcfs(void){
  int Current = CurrentCylinder;
  int Direction = SeekDirection;
  InitSpace("FCFS");
  
  cout <<Current;
  for(int i=0;i<RequestNumber; i++){
    if(((Cylinder[i]>=Current)&&!Direction)
      ||((Cylinder[i]<Current)&&Direction)){
        //需要调头
        SeekChang++;//调头数加1
        Direction =!Direction;//改变方向标志
        //报告当前响应的道号
        cout<<endl<< Current<<"->"<<Cylinder[i];
  }
  else //不需调头,报告当前响应的道号
  cout<<"->"<<Cylinder[i];
  //累计寻道数,响应过的道号变为当前道号
  SeekNumber += abs(Current -Cylinder[i]);
  Current = Cylinder[i];
  }
  //报告磁盘移臂调度的情况
  Report();
}

//最短寻道时间优先算法
void DiskArm::Sstf(void)
{
  int Shortest;
  int Distance = 999999;
  int Direction= SeekDirection;
  int Current = CurrentCylinder;
  InitSpace("SSTF");
  cout << Current;
  for(int i=0; i<RequestNumber; i++){
    //查找当前最近道号
    for(int j=0; j<RequestNumber; j++){
      if(Cylinder[j]== -1) continue;//-1表示已经响应过了
        if(Distance>abs(Current-Cylinder[j])){
        //到下一道号比当前距离近,下—道号为当前距离
        Distance = abs(Current-Cylinder[j]);
        Shortest = j;
        }
      }
      if(((Cylinder[Shortest] >=Current)&&!Direction)
        || ((Cylinder[Shortest]< CurrentCylinder)&& Direction)){
      //需要调头
      SeekChang++;//调头数加1
      Direction= !Direction;//改变方向标志
      //报告当前响应的道号
      cout<<endl <<Current <<"->"<<Cylinder[Shortest];
      }
      else //不需调头,报告当前响应的道号
      cout<<"->"<<Cylinder[Shortest] ;
      //累计寻道数,响应过的道号变为当前道号
      SeekNumber += abs(Current -Cylinder[Shortest]);
      Current= Cylinder[Shortest];
      //恢复最近距离,销去响应过的道号
      Distance = 999999;
      Cylinder[Shortest]=-1;
    }
    Report();
}

//电梯调度算法 到达一端后从到达点向回走
void DiskArm::Scan(void)
{
  int Current = CurrentCylinder;
  int Direction = SeekDirection;
  int maxIndex = 0,max = -65523;
  int minIndex = 0,min = 65523;
  for(int i=0;i < RequestNumber; i++){
    if(max<Request[i]){
      maxIndex = i;
      max = Request[i]; 
    }
    if(min>Request[i]){
      minIndex = i;
      min = Request[i];
    }
  }
  sort(Request, RequestNumber);//排序
  InitSpace("Scan");
  int nextIndex = 0;
  for(int i=0;i<RequestNumber;i++){//找到下一个比起始位置大的坐标
    if(Cylinder[i]>=Current){
      nextIndex = i;
      break;
    }
  }

  cout<<Current;
  if(!Direction){
    for(int i=nextIndex;i<RequestNumber; i++){
      if((Cylinder[i])<=max){
        //不需调头,报告当前响应的道号
        cout<<"->"<<Cylinder[i];
        //累计寻道数,响应过的道号变为当前道号
        SeekNumber += abs(Current -Cylinder[i]);
        Current = Cylinder[i];
      }
      if(Cylinder[i]==max)
      {
        SeekChang++;//调头数加1
        Direction =!Direction;//改变方向标志
        //报告当前响应的道号 
        int j = nextIndex-1;
        cout<<endl<<Current;
        while(j >= 0){
          cout<<"->"<<Cylinder[j];
          SeekNumber += abs(Current -Cylinder[j]);
          Current = Cylinder[j];
          j--;
        }
      } 
    }
    }else{
      for(int i=nextIndex-1;i>=0; i--){
      if((Cylinder[i])>=min){
        //不需调头,报告当前响应的道号
        cout<<"->"<<Cylinder[i];
        //累计寻道数,响应过的道号变为当前道号
        SeekNumber += abs(Current -Cylinder[i]);
        Current = Cylinder[i];
      }
      if(Cylinder[i]==min){
        SeekChang++;//调头数加1
        Direction =!Direction;//改变方向标志
        //报告当前响应的道号 
        int j = nextIndex+1;
        cout<<endl<<Current;
        while(j <= RequestNumber-nextIndex+1){
          cout<<"->"<<Cylinder[j];
          SeekNumber += abs(Current -Cylinder[j]);
          Current = Cylinder[j];
          j++;
        }} 
    }}
  //报告磁盘移臂调度的情况
  Report();
}


//均匀电梯调度算法 到达另一端后从头开始
void DiskArm::CScan(void)
{
  int Current = CurrentCylinder;
  int Direction = SeekDirection;
  int maxIndex = 0,max = -65523;
  int minIndex = 0,min = 65523;
  for(int i=0;i < RequestNumber; i++){
    if(max<Request[i]){
      maxIndex = i;
      max = Request[i]; 
    }
    if(min>Request[i]){
      minIndex = i;
      min = Request[i];
    }
  }
  sort(Request, RequestNumber);//排序
  InitSpace("CScan");
  int nextIndex = 0;
  for(int i=0;i<RequestNumber;i++){//找到下一个比起始位置大的坐标
    if(Cylinder[i]>=Current){
      nextIndex = i;
      break;
    }
  }

  cout<<Current;
  if(!Direction){
    for(int i=nextIndex;i<RequestNumber; i++){
      if((Cylinder[i])<=max){
        //不需调头,报告当前响应的道号
        cout<<"->"<<Cylinder[i];
        //累计寻道数,响应过的道号变为当前道号
        SeekNumber += abs(Current -Cylinder[i]);
        Current = Cylinder[i];
      }
      if(Cylinder[i]==max)
      {
        SeekChang++;//调头数加1
        Direction =!Direction;//改变方向标志
        //报告当前响应的道号 
        int j = 0;
        cout<<endl<<Current;
        while(j <= nextIndex-1){
          cout<<"->"<<Cylinder[j];
          SeekNumber += abs(Current -Cylinder[j]);
          Current = Cylinder[j];
          j++;
        }
      } 
    }
    }else{
      for(int i=nextIndex-1;i>=0; i--){
      if((Cylinder[i])>=min){
        //不需调头,报告当前响应的道号
        cout<<"->"<<Cylinder[i];
        //累计寻道数,响应过的道号变为当前道号
        SeekNumber += abs(Current -Cylinder[i]);
        Current = Cylinder[i];
      }
      if(Cylinder[i]==min){
        SeekChang++;//调头数加1
        Direction =!Direction;//改变方向标志
        //报告当前响应的道号 
        int j = RequestNumber-1;
        cout<<endl<<Current;
        while(j >= nextIndex){
          cout<<"->"<<Cylinder[j];
          SeekNumber += abs(Current -Cylinder[j]);
          Current = Cylinder[j];
          j--;
        }} 
    }}
  //报告磁盘移臂调度的情况
  Report();
}


//LOOK调度算法
void DiskArm::Look(void)
{
    int Current = CurrentCylinder;
  int Direction = SeekDirection;
  int maxIndex = 0,max = -65523;
  int minIndex = 0,min = 65523;
  for(int i=0;i < RequestNumber; i++){
    if(max<Request[i]){
      maxIndex = i;
      max = Request[i]; 
    }
    if(min>Request[i]){
      minIndex = i;
      min = Request[i];
    }
  }
  sort(Request, RequestNumber);//排序
  InitSpace("Look");
  int nextIndex = 0;
  for(int i=0;i<RequestNumber;i++){//找到下一个比起始位置大的坐标
    if(Cylinder[i]>=Current){
      nextIndex = i;
      break;
    }
  }

  cout<<Current;
  if(!Direction){
    for(int i=nextIndex;i<RequestNumber; i++){
      if((Cylinder[i])<=max){
        //不需调头,报告当前响应的道号
        cout<<"->"<<Cylinder[i];
        //累计寻道数,响应过的道号变为当前道号
        SeekNumber += abs(Current -Cylinder[i]);
        Current = Cylinder[i];
      }
      if(Cylinder[i]==max)
      {
        SeekChang++;//调头数加1
        Direction =!Direction;//改变方向标志
        //报告当前响应的道号 
        int j = nextIndex-1;
        cout<<endl<<Current;
        while(j >= 0){
          cout<<"->"<<Cylinder[j];
          SeekNumber += abs(Current -Cylinder[j]);
          Current = Cylinder[j];
          j--;
        }
      } 
    }
    }else{
      for(int i=nextIndex-1;i>=0; i--){
      if((Cylinder[i])>=min){
        //不需调头,报告当前响应的道号
        cout<<"->"<<Cylinder[i];
        //累计寻道数,响应过的道号变为当前道号
        SeekNumber += abs(Current -Cylinder[i]);
        Current = Cylinder[i];
      }
      if(Cylinder[i]==min){
        SeekChang++;//调头数加1
        Direction =!Direction;//改变方向标志
        //报告当前响应的道号 
        int j = nextIndex+1;
        cout<<endl<<Current;
        while(j <= RequestNumber-nextIndex+1){
          cout<<"->"<<Cylinder[j];
          SeekNumber += abs(Current -Cylinder[j]);
          Current = Cylinder[j];
          j++;
        }} 
    }}
  //报告磁盘移臂调度的情况
  Report();
}
//程序启动入口
int main(int argc,char *argv[]){
  //建立磁盘移臂调度类
  DiskArm *dask = new DiskArm();
  //比较和分析FCFS和SSTF两种调度算法的性能

  dask->Fcfs();
  dask->Sstf();
  dask->Scan();
  dask->CScan();
  dask->Look();
}
//makefile
head = dask.h
srcs = dask.cc
objs = dask.o
opts= -w -g -c
all:dask
dask:	$(objs)
	g++ $(objs) -o dask
dask.o:	$(srcs) $(head)
	g++ $(opts) $(srcs)
clean:
	rm dask *.o
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ljl2107

感谢我能帮助到你

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值