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 #include2 #include 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章。
sem.h:
1 #include2 #include 3 #include 4 #include 5 #include 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 #include3 #include 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 errn"); 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 errn"); 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 errn"); 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 errn"); 57 } 58 } 59 void sem_destory() 60 { 61 if(semctl(semid,0,IPC_RMID) ==-1) 62 { 63 //删除失败 64 printf("semctl err destoryn"); 65 } 66 }
给A、B程序加p、v操作:
A.c
1 #include2 #include 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 #include2 #include 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



