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


版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

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

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

Linux的进程编程-之二-进程间通信(共享内存)

1.1         共享内存 共享内存是最有用,也是最快的IPC方式。有三种实现共享内存的方法:系统调用mmap( )、POSIX共享内存、系统V共享内存。 三者都是先将文件映射到物理内存页面...

共享内存+信号量通信

Linux进程间通信(IPC)编程实践(十一)System V信号量---实现一个先进先出的共享内存shmfifo

使用消息队列即可实现消息的先进先出(FIFO), 但是使用共享内存实现消息的先进先出则更加快速;    我们首先完成C语言版本的shmfifo(基于过程调用), 然后在此基础上实现C++版本的S...

Linux进程间通信(IPC)编程实践(六)共享内存的使用-mmap

共享内存区是最快的IPC形式。一旦这样的内存映射到共享它的进程的地址空间,这些进程间数据传递不再涉及到内核,换句话说是进程不再通过执行进入内核的系统调用来传递彼此的数据(如图)。 共享内存和其他进...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

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