Linux interprocess communication|shared memory

Shared memory

1. Overview of Shared Memory

Shared memory is one of the most efficient ways of inter-process communication, because the process can directly read and write memory without any negative data. In order to exchange information between multiple processes, the kernel has set aside a memory area that can be mapped to its own private space address by the process that needs to be accessed. Since multiple processes share a segment of memory, they also need to rely on some synchronization mechanism, such as mutexes and semaphores.
Schematic diagram of shared memory principle.jpg

2. Shared memory programming

2.1 Programming instructions

The implementation of shared memory is divided into two steps:

  • Create shared memory, that is, obtain a shared memory area from the memory, use the shmget() function
  • Mapping shared memory, that is, to map the created shared memory to a specific process space, use the shmat() function
    so far to use this shared memory, you can use unbuffered I/O read and write commands to do it operating. There is also an operation to undo the memory mapping, the function is shmdt()
2.2 Function introduction

shmget() creates a shared memory function

/*****shmget()函数*****/
函数原型:int shmget(key_t key, int size, int shmflg)
传 入 值:key 共享内存的键值,多个进程可通过它访问同一个共享内存。IPC_PRIVATE用于创建私有共享内存
		 size 共享内存区大小
		 semflg 同 open() 函数的权限位
返 回 值:成功:返回共享内存标识符;
		 失败:返回-1

shmat() mapping shared memory function

/*****shmat()函数*****/
函数原型:int shmat(int shmid, const void *shmaddr, int shmflg)
传 入 值:shmid 要映射的共享内存区标识符
		 shmaddr 将共享内存映射到指定地址(若为0表示系统自动分配地址并把该段共享内存映射到调用进程的地址空间)
		 semflg 默认为0表示共享内存可读写;SHM_RDONLY表示共享内存只读
返 回 值:成功:被映射的段地址;
		 失败:返回-1

shmdt() undo memory mapping function

/*****shmdt()函数*****/
函数原型:int shmdt(const void *shmaddr)
传 入 值:shmaddr 被映射的共享内存段地址
返 回 值:成功:返回0;
		 失败:返回-1
2.3 Function examples
/*****shmem.c*****/
//省略头文件
#define BUFFER_SIZE 2048

int main(){
    
    
	pid_t pid;
	int shmid,
	char *shm_addr;
	char flag[] = "WROTE";
	char *buff;

	if((shmid = shmget(IPC_PRIVATE,BUFFER_SIZE,0666)) < 0){
    
    	//创建共享内存
		perror("shmget");
		exit(1);
	}
	else
		printf("Creat shared-memory: %d\n",shmid);

	system("ipcs -m");	//使用了system()函数调用shell命令“ipcs”,ipcs命令用于报告进程间通讯机制状态
	pid = fork();
	if(pid == -1){
    
    
		perror("fork");
		exit(1);
	}
	else if(pid == 0){
    
    	//子进程
		if((shm_addr = shmat(shmid,0,0)) == (void*)-1){
    
    		//映射共享内存
			perror("Child:shmat");
			exit(1);
		}
		else{
    
    
			printf("Child: Attach shared-memory: %p\n",shm_addr);
		}
		system("ipcs -m");
		
		while(strncmp(shm_addr, flag, strlen(flag))){
    
    
			printf("Child: Wait for enable data...\n");
			sleep(5);
		}

		strcpy(buff, shm_addr + strlen(flag));
		printf("Child: Shared-memory: %s\n",buff);

		if((shmdt(shm_addr)) < 0){
    
    		//解除共享内存映射
			perror("shmdt");
			exit(1);
		}
		else{
    
    
			printf("Child: Deattach shared-memory\n");
		}
		system("ipcs -m");
		
		if((shmctl(shmid, IPC_RMID, NULL)) == -1){
    
    		//删除共享内存
			perror("Child: shmctl(IPC_RMID)\n");
			exit(1);
		}
		else{
    
    
			printf("Delete shared-memory\n");
		}
		system("ipcs -m");
	}
	else{
    
      //父进程
		if((shm_addr = shmat(shmid,0,0)) == (void*)-1){
    
    
			perror("Parent:shmat");
			exit(1);
		}
		else{
    
    
			printf("Parent: Attach shared-memory: %p\n",shm_addr);
		}
		
		sleep(1);
		printf("\nInput some string:\n");
		fgets(buff,BUFFER_SIZE,stdin);
		strncpy(shm_addr + strlen(flag), buff, strlen(buff));
		strncpy(shm_addr, flag, strlen(flag));
		
		if((shmdt(shm_addr)) < 0){
    
    
			perror("Parent shmdt");
			exit(1);
		}
		else{
    
    
			printf("Parent: Deattach shared-memory\n");
		}
		system("ipcs -m");
		
		waitpid(pid, NULL, 0);
		printf("Finished\n");
	}
	exit(0);
}

Guess you like

Origin blog.csdn.net/Chuangke_Andy/article/details/108306410