进程间通讯之共享内存

共享内存是两个或多个进程共享一给定的在内存上的存储区。进程之间共享这个存储区,所以,数据的存取就减少了复制的过程,这就使得共享内存成为一种最快的IPC。另外,这部分共享存储区被作为一个临界资源,则用信号量来实现共享存储区访问的同步。即当一进程正在使用这一存储区,并在他完成这一操作之前,其它进程应不能访问这部分存储区。

共享内存的操作:

     创建获取:

int shmget((ket_t)key, size_t size, int flag);

key:创建标识

size:内存区大小(字节)

flag:创建权限

成功返回存储区ID(shmid),失败返回 -1

     映射到本进程的地址空间上:

void *shmat(int shmid, void *addr, int flag);

shmid:内存区ID

*addr:指定链接地址

flag:权限

成功返回内存区地址,失败返回 -1

     断开链接:

int shmdt(void *ptr);

*ptr:指向内存区首地址的指针

成功返回0,失败返回 -1

     释放:

int shmctl(int shmid, int cmd, struct shmid_ds *buff);

cmd:命令参数(IPC_STAT  IPC_SET  IPC_RMID  SHM_LOCK  SHM_UNLOCK)

shmid_ds:内核为共享存储区分配的一个结构

 

工作原理为:

可以看出进程操作共享存储区是通过指针来实现的。

 

下面就是具体的实现代码:

首先用信号量来对共享内存进行控制:

头文件:sem.h

#ifndef __SEM_H

#define __SEM_H

 

#include<stdio.h>

#include<stdlib.h>

#include<unistd.h>

#include<string.h>

#include<assert.h>

#include <sys/sem.h>

#include <sys/shm.h>

union semun

{

  int val;

};

void sem_get();

void sem_p();

void sem_v();

void sem_del();

#endif

 

信号量控制的实现:

#include "sem.h"

int semid = -1;

void sem_get() //  创建或者获取信号量集。

{

  semid = semget((key_t)1234, 1, 0664);

  if(semid == -1)

  {

  semid = semget((key_t)1234, 1, IPC_CREAT | 0664);

  if(semid == -1)

  {

  perror("");

  exit(0);

  }

  // 初始化新创建的信号量集

  union semun un;

  un.val = 1;

  semctl(semid, 0, SETVAL, un);

  }

}

void sem_p()  //  完成P操作

{

  struct sembuf  buf;

  buf.sem_num = 0;

  buf.sem_op = -1;

  buf.sem_flg = SEM_UNDO;

  semop(semid, &buf, 1);

}

void sem_v() // 完成V操作

{

  struct sembuf buf;

  buf.sem_num = 0;

  buf.sem_op = 1;

  buf.sem_flg = SEM_UNDO;

  if(-1 == semop(semid, &buf, 1))

  {

  perror("");

  }

}

void sem_del() // 释放信号量集

{

  semctl(semid, 0, IPC_RMID);

}

 

A进程实现从内存中读数据

#include "sem.h"

int main()

{

  int shmid = shmget((key_t)1234, 128, IPC_CREAT|0664);

  assert(shmid != -1);

  char *ptr = (char*)shmat(shmid, NULL, 0);

  sem_get();

  while(1)

  {

  sem_p();

  if(strncmp(ptr, "end", 3) == 0)

  {

  break;

  }

  printf("%s \n %d\n", ptr, strlen(ptr) - 1);

  sem_v();

  }

  shmdt(ptr);

  exit(0);

}

 

B进程实现向内存中写数据

#include "sem.h"

int  main()
{

    int shmid = shmget((key_t)1234, 128, IPC_CREAT|0664);

    assert(shmid != -1);

    char *ptr = (char*)shmat(shmid, NULL, 0);

    sem_get();

    while(1)

    {

     sem_p();

     printf("please input: ");

     fgets(ptr, 128, stdin);

     sem_v();

     if(strncmp(ptr, "end", 3) == 0)

    {

       break;

    }

    }

     shmdt(ptr);

     exit(0);
    }

猜你喜欢

转载自blog.csdn.net/magic_world_wow/article/details/79888964
今日推荐