10、信号量(两进程)

10、信号量(两进程),第1张

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

欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/zaji/5435967.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2022-12-11
下一篇2022-12-11

发表评论

登录后才能评论

评论列表(0条)

    保存