信号量与共享内存实现不同进程间通讯

通过信号量与共享内存实现不同进程间通讯

头文件:myshm.h

#ifndef __MYSHM_H__
#define __MYSHM_H__

#define KEYPATH "/etc"
#define SEMPRJ 'a'
#define SHMPRJ 'b'
#define NAMESIZE 1024

struct stu_st    //自定义传输数据类型
{
  char name[NAMESIZE];
  int math;
  int chinese;
};

#endif

 

发送方:sender.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <sys/shm.h>
#include "myshm.h"

static void P(int semid,int num)   //P操作信号量减一
{
  struct sembuf set;

  set.sem_num = num;       //信号量数组中的哪一个
  set.sem_op = -1;        //减一操作
  set.sem_flg = 0;       //无特殊要求

  semop(semid,&set,1);      //设置信号量(信号量ID,设置信息,设置多少个信号量)
}

static void V(int semid,int num)  //V操作信号量加一
{
  struct sembuf set;

  set.sem_num = num;         //信号量数组中的哪一个
  set.sem_op = 1;         //加一操作
  set.sem_flg = 0;       //无特殊要求

  semop(semid,&set,1);   //设置信号量(信号量ID,设置信息,设置多少个信号量)
}

int main()
{
  key_t semkey,shmkey;
  int semid,shmid;
  struct stu_st *std;
  int ret;

  semkey = ftok(KEYPATH,SEMPRJ);   //申请信号量key值
  if(semkey <0)
  {
    perror("ftok semkey()");
    exit(1);
  }

  shmkey = ftok(KEYPATH,SHMPRJ);  //申请共享内存key值
  if(shmkey <0)
  {
    perror("ftok shmkey()");
    exit(1);
  }

  semid = semget(semkey,2,IPC_CREAT|0600);  //创建信号量 (key,多少个信号量,属性)
  if(semid <0)
  {
    perror("semget()");
    exit(1);
  }

  shmid = shmget(shmkey,sizeof(*std),IPC_CREAT|0600); //创建共享内存 (key,共享内存大小,属性)
  if(shmid <0)
  {
    perror("shmget()");
    exit(1);
  }

  ret = semctl(semid,0,SETVAL,1);  //设置信号量(信号量ID,哪个信号量,操作命令,参数)
  if(ret<0)
  {
    perror("semctl");
    exit(1);
  }

  ret = semctl(semid,1,SETVAL,0); //设置信号量(信号量ID,哪个信号量,操作命令,参数)
  if(ret<0)
  {
    perror("semctl");
    exit(1);
  }

  std = shmat(shmid,NULL,0);    //映射共享内存
  if(std == (void *)-1)
  {
    perror("shmat");
    exit(1);
  }

  P(semid,0);    //P操作

  strcpy(std->name,"Alin");  //共享内存设置数据
  std->math = 100;
  std->chinese = 30;

  V(semid,1);  //V操作
  P(semid,0);  //P操作

  shmdt(std);   //取消共享内存映射
  shmctl(shmid,IPC_RMID,NULL); //删除共享内存ID
  semctl(semid,0,IPC_RMID),  //删除信号量ID
  semctl(semid,1,IPC_RMID);

  exit(0);
}

接收方:rcver.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <sys/shm.h>
#include "myshm.h"

static void P(int semid,int num)
{
  struct sembuf set;

  set.sem_num = num;
  set.sem_op = -1;
  set.sem_flg = 0;

  semop(semid,&set,1);
}

static void V(int semid,int num)
{
  struct sembuf set;

  set.sem_num = num;
  set.sem_op = 1;
  set.sem_flg = 0;

  semop(semid,&set,1);
}

int main()
{
  key_t semkey,shmkey;
  int semid,shmid;
  struct stu_st *std;
  int ret;

  semkey = ftok(KEYPATH,SEMPRJ);
  if(semkey <0)
  {
    perror("ftok semkey()");
    exit(1);
  }

  shmkey = ftok(KEYPATH,SHMPRJ);
  if(shmkey <0)
  {
    perror("ftok shmkey()");
    exit(1);
  }

  semid = semget(semkey,2,0);    //运行sender时已创建这里不需要重复创建
  if(semid <0)
  {
    perror("semget()");
    exit(1);
  }

  shmid = shmget(shmkey,sizeof(*std),0);  //运行sender时已创建这里不需要重复创建
  if(shmid <0)
  {
    perror("shmget()");
    exit(1);
  }

  ret = semctl(semid,0,SETVAL,1);
  if(ret<0)
  {
    perror("semctl");
    exit(1);
  }

  ret = semctl(semid,1,SETVAL,0);
  if(ret<0)
  {
    perror("semctl");
    exit(1);
  }

  std = shmat(shmid,NULL,0);
  if(std == (void *)-1)
  {
    perror("shmat");
    exit(1);
  }

  P(semid,1);
  printf("name:%s math:%d chinese:%d\n",std->name,std->math,std->chinese);  //输出共享内存内容
  V(semid,0);

  shmdt(std);
  shmctl(shmid,IPC_RMID,NULL);
  semctl(semid,0,IPC_RMID);

  exit(0);
}

 

编译文件:Makefile

all:rcver sender

rcver:rcver.o
  $(CC) $^ -o $@

sender:sender.o
  $(CC) $^ -o $@

clean:
  $(RM) *.o rcver sender

posted @ 2022-08-05 09:50  *^VV^*  阅读(48)  评论(0编辑  收藏  举报