临界资源
1、临界资源:同一时刻只允许一个进程来访问的资源。
2、临界区:访问临界资源的代码段
信号量
信号量:为了控制对临界资源的访问。ex:0、1信号量,计数信号量、、、
pv操作
p操作:资源减一,代表获取资源。
v操作:资源加一,代表释放资源。加一和减一都是原子操作。
实例:假设有一个打印机,用A、B程序分别打印A和B,打印第一次时表示正在打印,第二次表示打印结束。
与信号量相关的几个方法:
1、sem_init() 初始化函数
2、sem_p() p操作,使用资源,信号量-1
3、sem_v() v操作,释放资源,信号量值+1
4、sem_destory 销毁信号量
未使用信号量之前:
A.c B.c同理
1 #include<stdio.h>
2 #include<stdlib.h>
3 int main()
4 {
5 for(int i=0;i<5;i++)
6 {
7 printf("A");
8 fflush(stdout);
9 int n= rand()%3;
10 sleep(n);
11 printf("A");
12 fflush(stdout);
13
14 n=rand()%3;
15 sleep(n);
16 }
17 }
stu@stu-virtual-machine:~/Test/信号量举例$ ABBAABBABAABBABABBAA
[1]- 已完成 ./A
[2]+ 已完成 ./B
可以看到未使用信号量之前,A和B的打印时没有顺序的,不能像正常的打印机一样,A使用完之后B使用。正常的应该AABB、、、总之是成对出现的。
信号量函数的原始接口:
linux程序设计14章。
p、v操作具体函数封装:
sem.h:
1 #include<stdio.h>
2 #include<sys/sem.h>
3 #include<string.h>
4 #include<stdlib.h>
5 #include<unistd.h>
6
7 union semun
8 {
9 int val;
10 };
11 void sem_init();
12 void sem_p();
13 void sem_v();
14 void sem_destory();
sem.c:
1 #include"sem.h"
2 #include<stdio.h>
3 #include<sys/sem.h>
4
5 static int semid = -1;
6 union semum
7 {
8 int val;
9 };
10
11 void sem_init()
12 {
13 semid = semget((key_t)1234,1,IPC_CREAT|IPC_EXCL|0600);
14 if(semid==-1)
15 {
16 semid = semget((key_t)1234,1,0600);
17 if(semid==-1)
18 {
19 printf("semget err\n");
20 return;
21 }
22 }
23 else
24 {
25 //全新创建信号量成功,需要初始化
26 union semum a;
27 a.val =1 ;
28 if(semctl(semid,0,SETVAL,a)==-1)
29 {
30 printf("semctl err\n");
31
32 }
33 }
34 }
35 void sem_p()
36 {
37 struct sembuf buf;
38 buf.sem_num = 0;//只有一个信号量
39 buf.sem_op=-1;//p操作为-1
40 buf.sem_flg=SEM_UNDO;
41
42 if(semop(semid,&buf,1)==-1)
43 {
44 printf("sem_op p err\n");
45 }
46 }
47 void sem_v()
48 {
49 struct sembuf buf;
50 buf.sem_num = 0;//只有一个信号量
51 buf.sem_op=1;//v操作为1
52 buf.sem_flg=SEM_UNDO;
53
54 if(semop(semid,&buf,1)==-1)
55 {
56 printf("sem_op v err\n");
57 }
58 }
59 void sem_destory()
60 {
61 if(semctl(semid,0,IPC_RMID) ==-1)
62 {
63 //删除失败
64 printf("semctl err destory\n");
65 }
66 }
给A、B程序加p、v操作:
A.c
1 #include<stdio.h>
2 #include<stdlib.h>
3 #include"sem.h"
4 int main()
5 {
6 sem_init();
7 for(int i=0;i<5;i++)
8 {
9 sem_p();
10
11 printf("A");
12 fflush(stdout);
13 int n= rand()%3;
14 sleep(n);
15 printf("A");
16 fflush(stdout);
17
18 sem_v();
19 n=rand()%3;
20 sleep(n);
21 }
22 sleep(10);//认为A程序结束10s后B会结束
23 sem_destory();
24 }
B.c
1 #include<stdio.h>
2 #include<stdlib.h>
3 #include"sem.h"
4 int main()
5 {
6 sem_init();
7 for(int i=0;i<5;i++)
8 {
9 sem_p();
10
11 printf("B");
12 fflush(stdout);
13 int n= rand()%3;
14 sleep(n);
15 printf("B");
16 fflush(stdout);
17 sem_v();
18
19 n=rand()%3;
20 sleep(n);
21 }
22 }
加p、v操作之后的运行结果:
stu@stu-virtual-machine:~/Test/信号量举例$ ./A& ./B&
[1] 3369
[2] 3370
stu@stu-virtual-machine:~/Test/信号量举例$ AABBAAAABBAABBAABBBB
[1]- 已完成 ./A
[2]+ 已完成 ./B
}
**加p、v操作之后的运行结果:**
```bash
stu@stu-virtual-machine:~/Test/信号量举例$ ./A& ./B&
[1] 3369
[2] 3370
stu@stu-virtual-machine:~/Test/信号量举例$ AABBAAAABBAABBAABBBB
[1]- 已完成 ./A
[2]+ 已完成 ./B