Linux——进程间通信,信号量的使用+小demo(C语言)

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

 1.sem.h

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/sem.h>

union semun {
  int val;
};

void sem_init();
void sem_p();
void sem_v();
void sem_destory();

2.sem.c

#include "sem.h"
#include <sys/sem.h>
#include <sys/types.h>

static int semid = -1;

void sem_init() {
  semid = semget((key_t)1234, 1, IPC_CREAT | IPC_EXCL | 0600);
  if (semid == -1) {
    semid = semget((key_t)1234, 1, 0600);
    if (semid == -1) {
      printf("semget err\n");
    }
  } else {
    union semun a;
    a.val = 1;
    if (semctl(semid, 0, SETVAL, a) ==
        -1) { //此时我们只需要一个变量,所以下标为0
      printf("semctl err\n");
    }
  }q
}
void sem_p() {
  struct sembuf buf;
  buf.sem_num = 0;
  buf.sem_op = -1;
  buf.sem_flg = SEM_UNDO;
  if (semop(semid, &buf, 1) == -1) {
    printf("p err\n");
  }
}
void sem_v() {
  struct sembuf buf;
  buf.sem_num = 0;
  buf.sem_op = 1;
  buf.sem_flg = SEM_UNDO;
  if (semop(semid, &buf, 1) == -1) {
    printf("v err\n");
  }
}
void sem_destory() {
  if (semctl(semid, 0, IPC_RMID) == -1) {
    printf("semvtl err\n");
  }
}

3.main.c

#include "sem.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
int main() {
  sem_init();
  for (int i = 0; i < 5; i++) {
    sem_p();
    printf("B");
    fflush(stdout);
    int n = rand() % 3;
    sleep(n);
    printf("B");
    fflush(stdout);
    sem_v();
    sleep(n);
  }
  sleep(10);
  sem_destory();
}

4.test.c

#include "sem.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
int main() {
  sem_init();
  for (int i = 0; i < 5; i++) {
    sem_p();
    printf("A");
    fflush(stdout);
    int n = rand() % 3;
    sleep(n);
    printf("A");
    fflush(stdout);
    sem_v();
    sleep(n);
  }
}

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

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

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值