实验一

1
2
3
4
5
6
7
8
//hello.c
#include <stdio.h>

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

1
2
3
4
5
6
7
8
9
//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

实验二

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

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

实验三

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

//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");
}
}

1
2
3
4
5
6
7
8
9
10
11
12
//forkhello.c
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main()
{
/* fork a process */
fork();
printf("Hello world!\n");
return 0;
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// 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;
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 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);
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
//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);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
//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);
}
}

实验四

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
//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;


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
//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;
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
//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;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
//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;
}


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
//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;


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
//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;
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
//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;
}


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
//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;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//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

实验五

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
//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;
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
//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;
}

实验六

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
//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;//磁头调头数
};

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
//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();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
//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