Linux——进程间通信,信号量的使用

一.什么是信号量呢?用途又是什么呢?

        信号量就是解决进程之间竞争资源的情况,比如:我们在宿舍用的公共洗衣机,我们只有当它空闲的时候,我们才可以去使用它,当别人看到洗衣机在使用的时候,就不能再去使用了。这个例子中,洗衣机就是资源,每个想洗衣服的人都想去占用资源。但是我们得等当前的前一个人洗完才可以使用,这就是等待。

        首先我们来看Linux下的几个信号量相关的函数:

1.int semget(key_t key, int nsems, int semflg);

这个函数可以用来初始化信号量或者获得当前的信号量,当无法初始化的时候,返回的值为-1。使用时是这样。第一个参数是设置key_t的值,第二个是信号量的个数。第三个是通过bash来获取信号量的信息。


   
   
  1. semid = semget(( key_t) 1234, 1, IPC_CREAT | IPC_EXCL | 0600); //用来初始化信号量,如果信号量的key_t值已存在的话就返回-1
  2. semid = semget(( key_t) 1234, 1, 0600); //获取已经存在信号量的key_t值,如果已存在返回当前key_t。如果没有,返回-1

2.semctl(int semid, int semnum, int cmd, ...);

返回的是当前信号量的key值(usigned int)类型的,通常用获取或者删除某个信号量,使用方法如下


   
   
  1. semctl(semid, 0, SETVAL, a) //这个是初始化当前semid信号量第0+1个元素的值,a为下方结构体
  2. union semun {
  3. int val; /* Value for SETVAL */
  4. struct semid_ds *buf; /* Buffer for IPC_STAT, IPC_SET */
  5. unsigned short *array; /* Array for GETALL, SETALL */
  6. struct seminfo *__buf; /* Buffer for IPC_INFO
  7. (Linux-specific) */
  8. }; //需要程序员去定义
  9. semctl(semid, 0, IPC_RMID); //这个是删除当前semid对应的信号量

  3. semop(semid, &buf, 1) ;(这些函数都可以通过bash命令man来找到原型)

用来获取或者释放当前资源,其中buf是定义好的结构体,结构体成员sem_op为1的时候就是释放资源,为-1则是占用资源


   
   
  1. struct sembuf buf;
  2. buf.sem_num = 0;
  3. buf.sem_op = 1;
  4. buf.sem_flg = SEM_UNDO;
  5. semop(semid, &buf, 1); //第一个参数是当前信号量的id,第二个参数就是提到的结构体,第三个参数是如果程序异常退出的话,我们可以释放它所占用的资源

4.Ok,逻辑成立,理论实践。

        介绍一下文件的结构把,先来编辑

只看.从.c和.h文件,文字描述一下把。sem.h文件中声明了四个方法,比如信号量的初始化,资源的释放和占用,信号量的销毁、

sem.c文件就是队sem.h头文件的实现。

main.c和test.c就是两个进程,我们两个进程都占用屏幕来输出,但是我们再同一时间,只想让一个进程来使用我们的屏幕,这就得用来我们的信号量。下面我们来看一看各个文件的具体实现把。

 1.sem.h

   
   
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <unistd.h>
  4. #include <string.h>
  5. #include <sys/sem.h>
  6. union semun {
  7. int val;
  8. };
  9. void sem_init();
  10. void sem_p();
  11. void sem_v();
  12. void sem_destory();
2.sem.c

   
   
  1. #include "sem.h"
  2. #include <sys/sem.h>
  3. #include <sys/types.h>
  4. static int semid = -1;
  5. void sem_init() {
  6. semid = semget(( key_t) 1234, 1, IPC_CREAT | IPC_EXCL | 0600);
  7. if (semid == -1) {
  8. semid = semget(( key_t) 1234, 1, 0600);
  9. if (semid == -1) {
  10. printf( "semget err\n");
  11. }
  12. } else {
  13. union semun a;
  14. a.val = 1;
  15. if ( semctl(semid, 0, SETVAL, a) ==
  16. -1) { //此时我们只需要一个变量,所以下标为0
  17. printf( "semctl err\n");
  18. }
  19. }q
  20. }
  21. void sem_p() {
  22. struct sembuf buf;
  23. buf.sem_num = 0;
  24. buf.sem_op = -1;
  25. buf.sem_flg = SEM_UNDO;
  26. if ( semop(semid, &buf, 1) == -1) {
  27. printf( "p err\n");
  28. }
  29. }
  30. void sem_v() {
  31. struct sembuf buf;
  32. buf.sem_num = 0;
  33. buf.sem_op = 1;
  34. buf.sem_flg = SEM_UNDO;
  35. if ( semop(semid, &buf, 1) == -1) {
  36. printf( "v err\n");
  37. }
  38. }
  39. void sem_destory() {
  40. if ( semctl(semid, 0, IPC_RMID) == -1) {
  41. printf( "semvtl err\n");
  42. }
  43. }
3.main.c

   
   
  1. #include "sem.h"
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <string.h>
  5. #include <unistd.h>
  6. int main() {
  7. sem_init();
  8. for ( int i = 0; i < 5; i++) {
  9. sem_p();
  10. printf( "B");
  11. fflush(stdout);
  12. int n = rand() % 3;
  13. sleep(n);
  14. printf( "B");
  15. fflush(stdout);
  16. sem_v();
  17. sleep(n);
  18. }
  19. sleep( 10);
  20. sem_destory();
  21. }
4.test.c

   
   
  1. #include "sem.h"
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <string.h>
  5. #include <unistd.h>
  6. int main() {
  7. sem_init();
  8. for ( int i = 0; i < 5; i++) {
  9. sem_p();
  10. printf( "A");
  11. fflush(stdout);
  12. int n = rand() % 3;
  13. sleep(n);
  14. printf( "A");
  15. fflush(stdout);
  16. sem_v();
  17. sleep(n);
  18. }
  19. }

5.进程间通信几个文件进行运行的话和普通文件的编译也不一样,所以CV之前的代码只是半九十,我们来看一下编译吧

这是编译时候的代码 ,运行结果如下,最后一行的最左侧有个B,别忘记了。困惑了我半天。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值