Linux 프로세스 간 통신 | 공유 메모리

공유 메모리

1. 공유 메모리 개요

공유 메모리는 프로세스가 부정적인 데이터없이 직접 메모리를 읽고 쓸 수 있기 때문에 프로세스 간 통신의 가장 효율적인 방법 중 하나입니다. 여러 프로세스간에 정보를 교환하기 위해 커널은 액세스해야하는 프로세스에 의해 자체 개인 공간 주소에 매핑 될 수있는 메모리 영역을 따로 설정했습니다. 여러 프로세스가 메모리 세그먼트를 공유하므로 뮤텍스 및 세마포와 같은 일부 동기화 메커니즘에 의존해야합니다.
공유 메모리 원리의 개략도 .jpg

2. 공유 메모리 프로그래밍

2.1 프로그래밍 지침

공유 메모리 구현은 두 단계로 나뉩니다.

  • 공유 메모리 만들기, 즉 메모리에서 공유 메모리 영역을 가져오고 shmget () 함수를 사용합니다.
  • 공유 메모리 매핑, 즉 생성 된 공유 메모리를 특정 프로세스 공간에 매핑하려면
    지금까지 shmat () 함수 를 사용하여이 공유 메모리를 사용합니다. 버퍼링되지 않은 I / O 읽기 및 쓰기 명령을 사용하여 수행 할 수 있습니다. 운영. 메모리 매핑을 취소하는 작업도 있습니다. 함수는 shmdt ()입니다.
2.2 기능 소개

shmget ()은 공유 메모리 함수를 만듭니다.

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

shmat () 매핑 공유 메모리 함수

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

shmdt () 실행 취소 메모리 매핑 함수

/*****shmdt()函数*****/
函数原型:int shmdt(const void *shmaddr)
传 入 值:shmaddr 被映射的共享内存段地址
返 回 值:成功:返回0;
		 失败:返回-1
2.3 기능 예
/*****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);
}

추천

출처blog.csdn.net/Chuangke_Andy/article/details/108306410