多進程間使用共享內存進行通信的簡單例程(linux)

以下爲head.h頭文件,包含其中的彩色打印中的對應ASCII碼

#ifndef __HEAD_H_
#define __HEAD_H_

#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <signal.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/wait.h>
#include <sys/sem.h>


#define NONE "\033[m"
#define RED "\033[0;32;31m"
#define LIGHT_RED "\033[1;31m"
#define GREEN "\033[0;32;32m"
#define LIGHT_GREEN "\033[1;32m"
#define BLUE "\033[0;32;34m"
#define LIGHT_BLUE "\033[1;34m"
#define DARY_GRAY "\033[1;30m"
#define CYAN "\033[0;36m"
#define LIGHT_CYAN "\033[1;36m"
#define PURPLE "\033[0;35m"
#define LIGHT_PURPLE "\033[1;35m"
#define BROWN "\033[0;33m"
#define YELLOW "\033[1;33m"
#define LIGHT_GRAY "\033[0;37m"
#define WHITE "\033[1;37m"

#define PrintERROR(str,ret)\
if(-1 == ret)\
{\
	perror(str);\
	exit(-1);\
}
#endif 

以下爲對應的共享內存通訊的簡單代碼shm_sem.c
#include"head.h"

#define SHM_SIZE	1024*4 //4K對齊
#define pathname	"."	//當前目錄
#define proj_id		888

static int create_sem(void);
static int init_sem(int semid);
static int DestroySem(int semid);
static int create_shm(void);
char * at_addr(int shmid);
static int Delete_at_addr(char *shmaddr);
static int DestroyShm(int shmid);
static int child_pv_opration(char *buf,int semid);
static int father_pv_opration(char *buf,int semid);

typedef union semun {
   int              val;    /* Value for SETVAL */
   struct semid_ds *buf;    /* Buffer for IPC_STAT, IPC_SET */
   unsigned short  *array;  /* Array for GETALL, SETALL */
   struct seminfo  *__buf;  /* Buffer for IPC_INFO
                               (Linux-specific) */
}semun_t;
  
/******************************************************************************
  Function: create_sem
  Description: 創建信號量,並獲得ID
  INPUT: 
  OUTPUT: 
  Return: 
  Revision: 
         1. Author: linsen
            Date:  2018/4/03
            Changes: First create 
 ******************************************************************************/
static int create_sem(void)
{
	key_t sem_key;
	//創建2個信號量 int semget(key_t key, int nsems, int semflg);
	sem_key = semget(sem_key,2,IPC_CREAT|0664);
	PrintERROR("semget", sem_key);
	return sem_key;
}
  
/******************************************************************************
  Function: init_sem
  Description: 給兩個信號量設置初始值
  INPUT: 
  OUTPUT: 
  Return: 
  Revision: 
         1. Author: linsen
            Date:  2018/4/03
            Changes: First create 
 ******************************************************************************/
static int init_sem(int semid)
{
//int semctl(int semid, int semnum, int cmd, ...);
	int ret = 0;
	//設置初始值0
	semun_t semval;
	semval.val = 0;
	//給編號爲0的信號量設置初始值
	ret = semctl(semid,0,SETVAL,semval);	
	PrintERROR("semctl", ret);
	//給編號爲1的信號量設置初始值
	semctl(semid,1,SETVAL,semval);	
	PrintERROR("semctl", ret);
}
/******************************************************************************
  Function: DestroySem
  Description: 刪除信號量
  INPUT: 
  OUTPUT: 
  Return: 
  Revision: 
         1. Author: linsen
            Date:  2018/4/03
            Changes: First create 
 ******************************************************************************/
static int DestroySem(int semid)
{
	int ret =0;
	ret =semctl(semid,0,IPC_RMID);
	PrintERROR("semctl", ret);
}
/******************************************************************************
  Function: create_shm
  Description: 創建共享內存
  INPUT: 
  OUTPUT: 
  Return: 
  Revision: 
         1. Author: linsen
            Date:  2018/4/03
            Changes: First create 
 ******************************************************************************/
static int create_shm(void)
{
	//key_t ftok(const char *pathname, int proj_id);
	int shm_id = 0;
	key_t key = ftok(pathname,proj_id);
	PrintERROR("ftok", key);
	//int shmget(key_t key, size_t size, int shmflg);
	shm_id = shmget(key,SHM_SIZE,IPC_CREAT|0666);
	PrintERROR("shmget", shm_id);
	return shm_id;
}

  
/******************************************************************************
  Function: at_addr
  Description: 映射共享內存
  INPUT: 
  OUTPUT: 
  Return: 
  Revision: 
         1. Author: linsen
            Date:  2018/4/03
            Changes: First create 
 ******************************************************************************/
char * at_addr(int shmid)
{
	//void *shmat(int shmid, const void *shmaddr, int shmflg);
	return shmat(shmid,NULL,0);
}
  
/******************************************************************************
  Function: Delete_at_addr
  Description: 解除共享內存的映射
  INPUT: 
  OUTPUT: 
  Return: 
  Revision: 
         1. Author: linsen
            Date:  2018/4/03
            Changes: First create 
 ******************************************************************************/
static int Delete_at_addr(char *shmaddr)
{
	//int shmdt(const void *shmaddr);
	return shmdt(shmaddr);
}
  
/******************************************************************************
  Function: DestroyShm
  Description: 刪除共享內存 
  INPUT: 
  OUTPUT: 
  Return: 
  Revision: 
         1. Author: linsen
            Date:  2018/4/03
            Changes: First create 
 ******************************************************************************/
static int DestroyShm(int shmid)
{
	//int shmctl(int shmid, int cmd, struct shmid_ds *buf);
	shmctl(shmid,IPC_RMID,NULL);
}
//struct sembuf{
//	unsigned short sem_num;  /* semaphore number */
//	short          sem_op;   /* semaphore operation */
//	short          sem_flg;  /* operation flags */
//};
/******************************************************************************
  Function: child_pv_opration
  Description: 
  INPUT: 
  OUTPUT: 
  Return: 
  Revision: 
         1. Author: linsen
            Date:  2018/4/03
            Changes: First create 
 ******************************************************************************/
static int child_pv_opration(char *buf,int semid)
{
	struct sembuf sempv; 
	int ret = 0;
	while(1)
	{
		printf(GREEN"child>>>>>>"NONE);
		fflush(stdout);
		//寫操作
		fgets(buf,SHM_SIZE,stdin);
		//進行V操作
		sempv.sem_num = 0;
		sempv.sem_op  = +1;
		sempv.sem_flg = 0;
		//int semop(int semid, struct sembuf *sops, unsigned nsops);
		ret = semop(semid,&sempv,1);
		PrintERROR("semop", ret);

		//對第二個信號量進行P操作
		sempv.sem_num = 1;
		sempv.sem_op = -1;
		sempv.sem_flg = 0;
		ret =semop(semid,&sempv,1);
		PrintERROR("semop", ret);
		//讀
		printf(YELLOW"from father:%s\n",buf);
	}
}
  
/******************************************************************************
  Function: father_pv_opration
  Description: 
  INPUT: 
  OUTPUT: 
  Return: 
  Revision: 
         1. Author: linsen
            Date:  2018/4/03
            Changes: First create 
 ******************************************************************************/
static int father_pv_opration(char *buf,int semid)
{
	struct sembuf sempv; 
	int ret = 0;
	while(1)
	{
		//對第二個信號量進行P操作
		sempv.sem_num = 0;
		sempv.sem_op = -1;
		sempv.sem_flg = 0;
		ret =semop(semid,&sempv,1);
		PrintERROR("semop", ret);
		//讀
		printf(YELLOW"from child:%s\n",buf);
		
	
		printf(GREEN"father>>>>>>"NONE);
		fflush(stdout);
		//寫操作
		fgets(buf,SHM_SIZE,stdin);
		//進行V操作
		sempv.sem_num = 1;
		sempv.sem_op  = +1;
		sempv.sem_flg = 0;
		//int semop(int semid, struct sembuf *sops, unsigned nsops);
		ret = semop(semid,&sempv,1);
		PrintERROR("semop", ret);		
	}
}
/******************************************************************************
  Function: main
  Description: 主函數入口,實現兩個進程間的共享內存通訊
  INPUT: 
  OUTPUT: 
  Return: 
  Revision: 
         1. Author: linsen
            Date:  2018/4/03
            Changes: First create 
 ******************************************************************************/
int main(int argc, const char * argv [ ])
{
	//創建共享內存
	int shmid = create_shm();	
	//創建信號量
	int semid = create_sem();
	//給信號量設置初始值
	init_sem(semid);
	
	//創建兩個進程,子進程進行共享內存的寫操作,父進程進行讀操作並銷燬
	pid_t pid;
	pid = fork();
	PrintERROR("fork", pid);
	if(0 == pid)//child
	{
		char *buf =at_addr(shmid);
		if(buf == (void *)-1)
		{
			perror("shmat");
			exit(-1);
		}
		child_pv_opration(buf,semid);
		
		Delete_at_addr(buf);
	}
	else if(pid >0)//father
	{
		char *buf =at_addr(shmid);
		if(buf == (void *)-1)
		{
			perror("shmat");
			exit(-1);
		}
		father_pv_opration(buf,semid);
		//解除共享內存的映射
		Delete_at_addr(buf);
		waitpid(pid,NULL,0);
		//刪除共享內存
		DestroyShm(shmid);
		//刪除信號量
		DestroySem(semid);
	}
	return 0;
}
編譯環境爲linux的使用gcc編譯.

gcc shm_sem.c -o shm_sem生成可執行文件shm_sem.



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