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

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

写共享内存:

//============================================================================
// 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


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章