栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 系统运维 > 运维 > Linux

10、信号量(两进程)

Linux 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

10、信号量(两进程)

临界资源

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
  2 #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章。


p、v操作具体函数封装:

sem.h:

  1  #include
  2  #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 #include
  3 #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 #include
  2 #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 #include
  2 #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
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/460457.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号