LinuxC/C++编程(8)—共享内存通信

原创 2016年05月31日 16:08:24

懒,先贴代码,有空再更原理:

写共享内存:

//============================================================================
// Name        : shmWrite.cpp
// Author      : Lin
// Version     :
// Copyright   : Your copyright notice
// Description : Write Shared Memory
//============================================================================

#include <iostream>
#include <sys/shm.h>
#include <cstdio>
#include <unistd.h>
#include <sys/sem.h>
#include <string.h>
#include <sys/ipc.h>
#include <sys/stat.h>
#define SHM_SIZE 256
using namespace std;

union semun
{
	int val;
	struct semid_ds *buf;
	unsigned short *arry;
};

typedef struct shm_t{               //常见的形式,是封装一个struct指向共享内存,但是这个结构体必须指定固定的大小
	char buf[SHM_SIZE];
}shm_t;

//*****这个子函数用于创建信号量*****
int createSem()
{
	int semId = semget((key_t)1230, 1, 0666|IPC_CREAT);//包含于<sys/sem.h>,创建一个信号量,共用一个key_t key即表示共用一个信号量
	if (semId < 0)
	{
		cerr << "create SystemV error! "<< endl;
		return -1;
	}
	else
		return semId;
}

//*****这个子函数用于初始化信号量*****
int setSem(int semId)
{
	union semun se;
	se.val = 1;//设置信号量的初始值为1
	if (semctl(semId, 0, SETVAL, se) == -1)//初始化这个信号量
	{
		cerr << "init fail!" << endl;
		return -1;
	}
	else
		return 0;
}

//*****这个子函数删除信号量*****
int delSem(int semId)
{
	union semun se;
	if (semctl(semId, 0, IPC_RMID, se) < 0)
	{
		cerr << "delete fail!" << endl;
		return -1;
	}
	else
		return 0;
}

//*****信号量P(等待)V(发布)操作*****
int P_Sem(int semId)
{
	struct sembuf buf;
	buf.sem_num = 0;//操作单个信号量的时候该参数为0
	buf.sem_op = -1; //-1表示P操作,1表示V操作
	buf.sem_flg = SEM_UNDO;
	if (semop(semId, &buf, 1) < 0)
	{
		cerr << "P error!" << endl;
		return -1;
	}
	else
		return 0;
}

int V_Sem(int semId)
{
	struct sembuf buf;
	buf.sem_num = 0;//操作单个信号量的时候该参数为0
	buf.sem_op = 1; //-1表示P操作,1表示V操作
	buf.sem_flg = SEM_UNDO;
	if (semop(semId, &buf, 1) < 0)
	{
		cerr << "V error!" << endl;
		return -1;
	}
	else
		return 0;
}


//*****主函数********
int main()
{
	int semID;
	int sid; //共享内存的ID
	struct shm_t *shmObjPtr;//自定义结构体指向共享内存,即共享内存的地址
	struct shmid_ds shmbuf; //这个内核自带的结构体,可以用于查看共享内存的状态信息
	key_t key;

	key = ftok(".", 0);//用这个函数来创建一个key
	if (key == -1)
	{
		cerr << "ftok error!" << endl;
		return -1;
	}

	sid =  shmget(key,sizeof(shm_t),IPC_CREAT|0666); //创建共享内存的ID
	if (sid == -1)
	{
		cerr << "shmget error!" << endl;
		return -1;
	}

	shmObjPtr = ( shm_t*)shmat(sid,NULL,0); //用这个函数获得共享内存的内存地址
	if (shmObjPtr == (shm_t*)-1)
	{
		cerr << "shmat error!" << endl;
		return -1;
	}

	semID = createSem(); //创建信号量
	if (semID == -1)
		return -1;

	if (P_Sem(semID) == -1) //等待信号量初始化则可进入临界区,允许向共享内存写数据
		return -1;

	cout << "now the process is writing the shared memory!" << endl;
	char *a = "heiheihei";
	strcpy(shmObjPtr->buf, a); //向共享内存中写数据

	shmctl(sid, IPC_STAT, &shmbuf); //查看共享内存状态
	cout << "Get the address of shared memory! The size is " << shmbuf.shm_segsz << " Bytes" << endl;

	cout << "write complete, leave the work now!" << endl;

	if (V_Sem(semID) == -1) //退出临界区
		return -1;

	if (shmdt(shmObjPtr) == -1) //进程拆卸该共享内存段
	{
		cerr << "shm delete fail!" << endl;
		return -1;
	}
	return 0;
}




读共享内存:

//============================================================================
// Name        : shmRead.cpp
// Author      : Lin
// Version     :
// Copyright   : Your copyright notice
// Description : Hello World in C++, Ansi-style
//============================================================================

#include <iostream>
#include <sys/shm.h>
#include <cstdio>
#include <unistd.h>
#include <sys/sem.h>
#include <string.h>
#define SHM_SIZE 256
using namespace std;

union semun
{
	int val;
	struct semid_ds *buf;
	unsigned short *arry;
};

typedef struct shm_t{   //同样,将共享内存定义为一个结构体
	char buf[SHM_SIZE];
}shm_t;

/*******这个子函数用于创建信号量*******/
int createSem()
{
	int semId = semget((key_t)1230, 1, 0666|IPC_CREAT);//包含于<sys/sem.h>,创建一个信号量,共用一个key_t key即表示共用一个信号量
	if (semId < 0)
	{
		cerr << "create SystemV error! "<< endl;
		return -1;
	}
	else
		return semId;
}

/*******这个子函数用于初始化信号量*******/
int setSem(int semId)
{
	union semun se;
	se.val = 1;//设置信号量的初始值为1
	if (semctl(semId, 0, SETVAL, se) == -1)//初始化这个信号量
	{
		cerr << "init fail!" << endl;
		return -1;
	}
	else
		return 0;
}

/*******这个子函数删除信号量*******/
int delSem(int semId)
{
	union semun se;
	if (semctl(semId, 0, IPC_RMID, se) < 0)
	{
		cerr << "delete fail!" << endl;
		return -1;
	}
	else
		return 0;
}

/*******信号量P(等待)V(发布)操作*******/
int P_Sem(int semId)
{
	struct sembuf buf;
	buf.sem_num = 0;//操作单个信号量的时候该参数为0
	buf.sem_op = -1; //-1表示P操作,1表示V操作
	buf.sem_flg = SEM_UNDO;
	if (semop(semId, &buf, 1) < 0)
	{
		cerr << "P error!" << endl;
		return -1;
	}
	else
		return 0;
}

int V_Sem(int semId)
{
	struct sembuf buf;
	buf.sem_num = 0;//操作单个信号量的时候该参数为0
	buf.sem_op = 1; //-1表示P操作,1表示V操作
	buf.sem_flg = SEM_UNDO;
	if (semop(semId, &buf, 1) < 0)
	{
		cerr << "V error!" << endl;
		return -1;
	}
	else
		return 0;
}


//*****主函数********
int main()
{
	int semID;
	int sid; //共享内存的ID
	struct shm_t *shmObjPtr;//自定义结构体指向共享内存,即共享内存的地址
	struct shmid_ds shmbuf; //这个内核自带的结构体,可以用于查看共享内存的状态信息
	key_t key;

	key = ftok(".", 0);//用这个函数来创建一个key
	if (key == -1)
	{
		cerr << "ftok error!" << endl;
		return -1;
	}

	sid =  shmget(key,sizeof(shm_t),IPC_CREAT|0666); //创建共享内存的ID
	if (sid == -1)
	{
		cerr << "shmget error!" << endl;
		return -1;
	}

	shmObjPtr = ( shm_t*)shmat(sid,NULL,0); //用这个函数获得共享内存的内存地址
	if (shmObjPtr == (shm_t*)-1)
	{
		cerr << "shmat error!" << endl;
		return -1;
	}

	semID = createSem(); //创建信号量,定义使用共享内存的同步机制
	if (semID == -1)
		return -1;
	if (setSem(semID) == -1) //一个信号量只能被初始化/删除一次
		return -1;

	if (P_Sem(semID) == -1) //进入临界区,允许向共享内存写数据
		return -1;

	cout << "Now the process is reading the shared memory!" << endl;
	cout << "The read process has read the msg: "<< shmObjPtr -> buf << endl; //读共享内存

	shmctl(sid, IPC_STAT, &shmbuf); //查看共享内存状态
	cout << "Get the address of shared memory! The size is " << shmbuf.shm_segsz << " Bytes" << endl;

	cout << "read complete, leave the work now!" << endl;

	if (V_Sem(semID) == -1) //退出临界区
		return -1;

	if (delSem(semID) == -1) //一个信号量只能被初始化/删除一次
		return -1;

	if (shmdt(shmObjPtr) == -1) //拆卸进程中的共享内存段
	{
		cerr << "shm desprate fail!" << endl;
		return -1;
	}

	if (shmctl(sid, IPC_RMID, 0) == -1) //删除共享内存段,而且必须删除。否则会占用系统资源
	{
		cerr << "shm delete fail!" << endl;
	}
	return 0;
}

测试过程和结果:

lin@lin-Z97-HD3:~/workspace$ ./shmWrite/Debug/shmWrite &
[1] 3464
lin@lin-Z97-HD3:~/workspace$ It's the write process here!
Get the address of shared memory! The size is 256 Bytes
./shmRead/Debug/shmRead 
Get the address of shared memory! The size is 256 Bytes
now the process is writing the shared memory!
write complete, leave the work now!
Now the process is reading the shared memory!
The read process has read the msg: heiheihei
read complete, leave the work now!
[1]+  已完成               ./shmWrite/Debug/shmWrite


LinuxC/C++编程(6)—重定向、管道重定向

LinuxC中的重定向功能,必须依靠等位文件描述符函数dup,该函数的介绍如下: dup和dup2用来复制文件描述符。 函数介绍: #include int dup(int oldfd); int ...

LinuxC/C++编程(7)—守护进程

守护进程(Daemon)是运行在后台的一种特殊进程。它独立于控制终端并且周期性地执行某种任 务或等待处理某些发生的事件。         守护进程是一种很有用的进程。Linux的大多数服务器就是用守护...

LinuxC/C++编程(3)—异步清理子进程(避免成为僵尸进程)

先了解Linux中进程的一些机制: 孤儿进程和僵尸进程: 1 如果父进程先退出,子进程尚未退出,那么子进程会成为孤儿,这时候会被init进程领养,等到子进程生命周期结束后,init会作为父进程释放掉...

进程间通信(8) - 共享内存(posix)

1.前言 本篇文章的所有例子,基于RHEL6.5平台(linux kernal: 2.6.32-431.el6.i686)。 2.共享内存介绍 前面所讲述的Linux下面的各种进程间通信方式,例如:p...
  • shltsh
  • shltsh
  • 2015年06月19日 23:59
  • 1569

进程间通信—共享内存、信号量

/************************************************************************* > File Name: test.c ...

进行通信,共享内存方式

  • 2014年06月03日 18:22
  • 88KB
  • 下载

Linux下C编程:共享内存通信实例

共享内存是LUNIX 系统中最底层的通信机制,也是最快速的通信机制。共享内存通过两个或多个进程共享同一块内存区域来实现进程间的通信。通常是由一个进程创建一块共享 内存区域,然后多个进程可以对其进行访...

进程间通信共享内存映射

  • 2017年03月07日 22:17
  • 79KB
  • 下载

共享内存+信号量通信

  • 2013年10月16日 15:07
  • 3KB
  • 下载
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:LinuxC/C++编程(8)—共享内存通信
举报原因:
原因补充:

(最多只允许输入30个字)