HUST操作系统实验2

本文最后更新于:2022年1月13日 下午

OS实验二:进程管理与死锁

1.创建父子进程

test1要求

创建测试程序,让父进程提前结束:

创建子进程测试代码

测试结果:

test1

2. 实现生产者-消费者模式

2.1 使用条件变量实现

人麻了,改了一下午的代码其实并没有问题,只是因为主线程没有等两个子线程执行完就退出了,所以命令行看不到子线程打印的数据,加上join函数就可以了!!!😣😣😣😣

具体代码如下:

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
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
pthread_mutex_t mutex;
pthread_cond_t fill,empty;
#define MAX 100
#define FULL 10
#define ZERO 0
int count=0 ;
void *producer(void* args){
int i=0;
for(i=0;i<MAX;i++){
pthread_mutex_lock(&mutex);
while(count==FULL){
pthread_cond_wait(&empty,&mutex);
}
count++;
printf("生产者%d,生产:%d\n",pthread_self(),count);
pthread_cond_signal(&fill);
pthread_mutex_unlock(&mutex);
}
pthread_exit(0);
}

void* consumer(void* args){
int i=0;
for(i = 0;i<MAX;i++){
pthread_mutex_lock(&mutex);
while(count==ZERO){
pthread_cond_wait(&fill,&mutex);
}
printf("消费者%d,消费:%d\n",pthread_self(),count);
count--;
pthread_cond_signal(&empty);
pthread_mutex_unlock(&mutex);
}
pthread_exit(0);
}

int main(){
pthread_t p1,p2,s1,s2; //两个消费者,两个生产者
pthread_mutex_init(&mutex,0);
pthread_cond_init(&empty,0);
pthread_cond_init(&fill,0);
count = 0;
pthread_create(&p1,NULL,producer,0);
pthread_create(&s1,NULL,consumer,0);
pthread_create(&p2,NULL,producer,0);
pthread_create(&s2,NULL,consumer,0);
pthread_join(p1,0);
pthread_join(p2,0);
pthread_join(s1,0);
pthread_join(s2,0);

pthread_mutex_destroy(&mutex);
pthread_cond_destroy(&empty);
pthread_cond_destroy(&fill);

return 0;
}

测试结果如下:

条件变量解决生产者消费者问题

2.2 使用信号量实现

具体代码如下:

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
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#include <semaphore.h>

#define MAX_PRO 2
#define MAX 10
int count = 0;
sem_t empty,fill,mutex;

void *producer(void* args){
int i = 0;
for(i = 0;i<=100;i++){
sem_wait(&empty);
sem_wait(&mutex);
count++;
printf("生产者%d,生产:%d\n",pthread_self(),count);
sem_post(&mutex);
sem_post(&fill);
}
pthread_exit(0);
}

void *consumer(void* args){
int i = 0;
for(i = 0;i<=100;i++){
sem_wait(&fill);
sem_wait(&mutex);
printf("消费者%d,消费:%d\n",pthread_self(),count);
count--;
sem_post(&mutex);
sem_post(&empty);
}
pthread_exit(0);

}

int main(){
pthread_t p1,p2,s1,s2;
sem_init(&mutex,0,1);//保证操作count时,互斥
sem_init(&fill,0,0);//fill初始为0,表示还没有产品
sem_init(&empty,0,MAX_PRO);//初始为最大的生产者数量
pthread_create(&p1,0,producer,0);
pthread_create(&p2,0,producer,0);
pthread_create(&s1,0,consumer,0);
pthread_create(&s2,0,consumer,0);
pthread_join(p1,0);
pthread_join(p2,0);
pthread_join(s1,0);
pthread_join(s2,0);

return 0;
}

测试结果:

信号量测试

3.哲学家问题

3.1死锁情况

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
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>

pthread_mutex_t lock[5];

void lock_init(){
int i;
for(i = 0;i<=4;i++){
pthread_mutex_init(&lock[i],0);
}
}

void lock_des(){
int i;
for(i = 0;i<=4;i++){
pthread_mutex_destroy(&lock[i]);
}
}

void *person(void* args){
int x= *(int*)args;
int left = x;
int right=(x+1)%5;
int i;
for(i = 0;i<=9;i++){
printf("哲学家%d,开始思考\n",x);
sleep(5);
pthread_mutex_lock(&lock[left]);
printf("哲学家%d,拿起左边的%d号筷子\n",x,x);
pthread_mutex_lock(&lock[right]);
printf("哲学家%d,拿起右边的%d号筷子\n",x,right);
printf("哲学家%d,开始吃饭\n",x);
sleep(10);
printf("哲学家%d,吃完了\n",x);
pthread_mutex_unlock(&lock[left]);
printf("哲学家%d,放下左边的%d号筷子",x,x);
pthread_mutex_unlock(&lock[right]);
printf("哲学及%d,放下右手的%d号筷子",x,right);
sleep(10);
}
}


int main(){
lock_init();
pthread_t p0,p1,p2,p3,p4;
int i0 = 0,i1=1,i2=2,i3=3,i4=4;
pthread_create(&p0,0,person,&i0);
pthread_create(&p1,0,person,&i1);
pthread_create(&p2,0,person,&i2);
pthread_create(&p3,0,person,&i3);
pthread_create(&p4,0,person,&i4);

pthread_join(p0,0);
pthread_join(p1,0);
pthread_join(p2,0);
pthread_join(p3,0);
pthread_join(p4,0);

lock_des();
}

上述代码中,由于所有哲学家都是先去拿左边的筷子,会导致出现所有人都拿到了左边的筷子,而再也拿不到右边的筷子而导致死锁

哲学家死锁

3.2 不死锁情况

避免死锁的方式有多种:

  • 一次获取两个锁,两只筷子都能拿则拿,否则都不拿
  • 有五位哲学家,规定其中一位必须先拿右边的筷子,再拿左边的,其他四位先拿左边的,再拿右边的

第二种方式代码:

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
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>

pthread_mutex_t lock[5];

void lock_init(){
int i;
for(i = 0;i<=4;i++){
pthread_mutex_init(&lock[i],0);
}
}

void lock_des(){
int i;
for(i = 0;i<=4;i++){
pthread_mutex_destroy(&lock[i]);
}
}
void *person(void* args){
int x= *(int*)args;
int left = x;
int right=(x+1)%5;
int i;
if(x==4){
for(i = 0;i<=9;i++){
printf("哲学家%d,开始思考\n",x);
sleep(2);
pthread_mutex_lock(&lock[right]);
printf("哲学家%d,拿起右边的%d号筷子\n",x,right);
pthread_mutex_lock(&lock[left]);
printf("哲学家%d,拿起左边的%d号筷子\n",x,x);
printf("哲学家%d,开始吃饭\n",x);
sleep(2);
printf("哲学家%d,吃完了\n",x);
pthread_mutex_unlock(&lock[left]);
printf("哲学家%d,放下左边的%d号筷子\n",x,x);
pthread_mutex_unlock(&lock[right]);
printf("哲学及%d,放下右手的%d号筷子\n",x,right);
sleep(2);
}}else{
for(i = 0;i<=9;i++){
printf("哲学家%d,开始思考\n",x);
sleep(2);
pthread_mutex_lock(&lock[left]);
printf("哲学家%d,拿起左边的%d号筷子\n",x,x);
pthread_mutex_lock(&lock[right]);
printf("哲学家%d,拿起右边的%d号筷子\n",x,right);
printf("哲学家%d,开始吃饭\n",x);
sleep(2);
printf("哲学家%d,吃完了\n",x);
pthread_mutex_unlock(&lock[left]);
printf("哲学家%d,放下左边的%d号筷子\n",x,x);
pthread_mutex_unlock(&lock[right]);
printf("哲学及%d,放下右手的%d号筷子\n",x,right);
sleep(2);
}
}
}
int main(){
lock_init();
pthread_t p0,p1,p2,p3,p4;
int i0 = 0,i1=1,i2=2,i3=3,i4=4;
pthread_create(&p0,0,person,&i0);
pthread_create(&p1,0,person,&i1);
pthread_create(&p2,0,person,&i2);
pthread_create(&p3,0,person,&i3);
pthread_create(&p4,0,person,&i4);

pthread_join(p0,0);
pthread_join(p1,0);
pthread_join(p2,0);
pthread_join(p3,0);
pthread_join(p4,0);

lock_des();
}

测试结果,不会产生死锁:

哲学家不死锁


本文作者: ziyikee
本文链接: https://ziyikee.fun/2021/11/30/OS%E5%AE%9E%E9%AA%8C%E4%BA%8C/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!