进程间通信-共享内存

发布时间:2024年01月12日

常用函数

#include <sys/shm.h>
// 创建/获取共享内存
int shmget (key_t key, size_t size, int shmflg);
/*
Key : 键值
size: 共享内存大小
shmflg:
	0 - 获取,不存在即失败。 
	IPC_CREAT - 创建,不存在即创建, 
	已存在即获取,除非… 
	IPC_EXCL - 排斥,已存在即失败。
*/


//加载共享内存 
void* shmat (int shmid, const void* shmaddr,int shmflg);
/*
shmid : 知识的共享内存,由shmget()返回得到
shmaddr:NULL
shmflg:
	0 - 以读写方式使用共享内存。 
	SHM_RDONLY - 以只读方式使用共享内存。 
	SHM_RND - 只在shmaddr参数非NULL时起作用。 
	表示对该参数向下取内存页的整数倍,作为映射地址。
成功返回映射地址,失败返回-1
*/


//卸载共享内存 
int shmdt (const void* shmaddr); 
/*
shmaddr : 由shmaddr参数所指向的,共享内存映射区域,由shmat()返回得到
*/

//销毁/控制共享内存 
int shmctl (int shmid, int cmd, struct shmid_ds* buf); 


例子

server

#include <stdio.h>
#include <unistd.h>
#include <stdbool.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <signal.h>

char *ptrr = NULL;
char *ptrw = NULL;
pid_t  cid;  //客户端的进程号
bool first = true;
int shmidr;
int shmidw;
//接收到sig信号,表明对方写了数据到共享内存中,可以读
void sigint_proc(int sig){
	if(ptrr != NULL){
		if(first){
			sscanf(ptrr,"%d",&cid);//第一次读取客户端的进程号
			printf("client pid:%d\n",cid);
			first = false;
		}else{
			printf("recv:%s",ptrr);	
		}
	}
}

void sigquit_proc(int sig){		//退出
	shmdt(ptrr);
	shmdt(ptrw);
	shmctl(shmidr,IPC_RMID,NULL);
	shmctl(shmidw,IPC_RMID,NULL);
	exit(0);
}
int main(){
	printf("进程号:%d\n",getpid());
	if(signal(SIGINT,sigint_proc)==SIG_ERR){
		perror("signal");
		return -1;
	}
	if(signal(SIGQUIT,sigquit_proc)==SIG_ERR){
		perror("signal");
		return -1;
	}
	//键值标识
	key_t id1 = ftok(".",100);
	key_t id2 = ftok(".",101);

	if(id1==-1 || id2==-1){
		perror("ftok");
		return -1;
	}
	//创建共享内存
	shmidw = shmget(id1,4096,IPC_CREAT|0644);	//写,
	shmidr = shmget(id2,4096,IPC_CREAT|0644);	//读,用来读取反馈信息
	if(shmidw == -1 || shmidr == -1){
		perror("shmget");
		return -1;
	}
	//加载共享内存 映射
	ptrw = shmat(shmidw,NULL,0);
	if(ptrw == NULL){
		perror("shmat");
		return -1;
	}
	ptrr = shmat(shmidr,NULL,0);
	if(ptrr == NULL){
		perror("shmat");
		return -1;
	}
	//两个进程A和B互发数据
	
	sprintf(ptrw,"%d",getpid());//把自己的进程号写入到共享内存中
	for(;;){
		if(!first){
			fgets(ptrw,4096,stdin);//读到的内容直接写入到共享内存中
			kill(cid,SIGINT);//给对方发送一个信号,写入了数据到共享内存中
		}
	}

	return 0;	
}

client

#include <stdio.h>
#include <unistd.h>
#include <stdbool.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <signal.h>

char *ptrr = NULL;
char *ptrw = NULL;
pid_t  sid;  //服务器的进程号
int shmidr;
int shmidw;
//接收到sig信号,表明对方写了数据到共享内存中,可以读
void sigint_proc(int sig){
	if(ptrr != NULL){
		printf("recv:%s",ptrr);	
	}
}

void sigquit_proc(int sig){
	shmdt(ptrr);
	shmdt(ptrw);
	exit(0);
}
int main(){
	printf("进程号:%d\n",getpid());
	if(signal(SIGINT,sigint_proc)==SIG_ERR){
		perror("signal");
		return -1;
	}
	if(signal(SIGQUIT,sigquit_proc)==SIG_ERR){
		perror("signal");
		return -1;
	}
	key_t id1 = ftok(".",100);
	key_t id2 = ftok(".",101);

	if(id1==-1 || id2==-1){
		perror("ftok");
		return -1;
	}
	//创建共享内存
	shmidr = shmget(id1,4096,0);
	shmidw = shmget(id2,4096,0);
	if(shmidw == -1 || shmidr == -1){
		perror("shmget");
		return -1;
	}
	//加载共享内存 映射
	ptrw = shmat(shmidw,NULL,0);
	if(ptrw == NULL){
		perror("shmat");
		return -1;
	}
	ptrr = shmat(shmidr,NULL,0);
	if(ptrr == NULL){
		perror("shmat");
		return -1;
	}
	//两个进程A和B互发数据
	
	sscanf(ptrr,"%d",&sid);//读取服务器的进程号
	printf("server pid:%d\n",sid);
	sprintf(ptrw,"%d",getpid());//把自己的进程号写入到共享内存中
	kill(sid,SIGINT);	//发送信号通知服务端
	for(;;){
		fgets(ptrw,4096,stdin);//读到的内容直接写入到共享内存中
		kill(sid,SIGINT);//给对方发送一个信号,写入了数据到共享内存中
	}

	return 0;	
}

文章来源:https://blog.csdn.net/qq_52575999/article/details/135541251
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。