10、信号量(两进程)

本文介绍了临界资源的概念,即同一时刻只能被一个进程访问的资源,并探讨了如何通过信号量进行管理。详细阐述了信号量的p、v操作,以及在实际例子中如何使用它们来解决打印机的并发问题。通过在A、B程序中添加p、v操作,实现了打印任务的有序执行,避免了未使用信号量时的混乱状态。
摘要由CSDN通过智能技术生成

临界资源

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
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值