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


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