【리눅스】시스템 V 공유 메모리

머리말

콘텐츠

한때 AT&T System V라고도 알려진 System V는 Unix 운영 체제의 여러 버전 중 하나입니다.

System V는 메시지 큐, 공유 공간 및 세마포의 세 가지 고급 프로세스 간 통신 메커니즘을 도입합니다.

공유 메모리는 프로세스 간 통신의 가장 빠른 방법인데, 그 이유는 통신하는 프로세스 pcb의 주소 공간의 공유 영역이 물리적 메모리의 한 조각에 동시에 매핑되고 그 위의 데이터가 직접 가상 주소를 통해 찾아 액세스, 이러한 프로세스 간 데이터 전송不再涉及到内核的系统接口的调用

공유 메모리를 신청하면 프로세스 1과 프로세스 2는 각각 해당 공유 메모리를 자신의 주소 공간에 붙이고 정상적으로 통신할 수 있다.

파이프 기반 프로세스 간 통신의 경우 읽기 및 쓰기와 같은 시스템 인터페이스를 호출해야 합니다. 쓰기 끝은 먼저 커널의 파일 버퍼에 데이터를 쓰고 읽기 끝은 버퍼에서 읽습니다. 이러한 작업은 모두 시스템 인터페이스를 호출합니다.

즉, 프로세스는 더 이상 커널로 들어가는 시스템 호출을 실행하여 서로의 데이터를 전달하지 않습니다.

여기에 이미지 설명 삽입

1. 공유 메모리 데이터 구조

struct shmid_ds {
    
    
	struct ipc_perm shm_perm; /* operation perms */
	int shm_segsz; /* size of segment (bytes) */
	__kernel_time_t shm_atime; /* last attach time */
	__kernel_time_t shm_dtime; /* last detach time */
	__kernel_time_t shm_ctime; /* last change time */
	__kernel_ipc_pid_t shm_cpid; /* pid of creator */
	__kernel_ipc_pid_t shm_lpid; /* pid of last operator */
	unsigned short shm_nattch; /* no. of current attaches */
	unsigned short shm_unused; /* compatibility */
	void *shm_unused2; /* ditto - used by DIPC */
	void *shm_unused3; /* unused */
};

2. 공유 메모리 기능

  • 공유 메모리 생성
int shmget(key_t key, size_t size, int shmflg);

매개변수
키: 공유 메모리 세그먼트 이름
크기: 공유 메모리 크기
shmflg: 9개의 권한 플래그로 구성되며 사용법은 파일을 생성할 때 사용되는 모드 플래그와 동일합니다
. 반환 값: 성공적으로 음이 아닌 정수를 반환합니다. , 즉, 공유 메모리 메모리의 식별 코드, 실패 시
shmflg에서 -1을 반환합니다.
여기에 이미지 설명 삽입

  • 키 생성 키
    가 ftok 함수에 의해 획득되고 공유 메모리의 고유 식별 코드를 반환합니다.shmid
key_t ftok(const char *pathname, int proj_id);
  • 프로세스 주소 공간에 공유 메모리 세그먼트 연결
void *shmat(int shmid, const void *shmaddr, int shmflg);

매개변수
shmid: 공유 메모리 식별자
shmaddr: 연결 주소 지정
shmflg: 두 가지 가능한 값은 일반적으로 0으로 설정되는 SHM_RND 및 SHM_RDONLY입니다
. 반환 값: 힙에서 공간을 여는 malloc과 유사하게 포인터를 성공적으로 반환합니다. -1을 반환

  • 공유 메모리에서 프로세스 주소 공간 바인딩 해제
int shmdt(const void *shmaddr);

매개변수
shmaddr: shmat에 의해 반환된 포인터 반환
값: 성공하면 0, 실패하면 -1
참고: 현재 프로세스에서 공유 메모리 세그먼트를 분리한다고 해서 공유 메모리 세그먼트가 삭제되는 것은 아닙니다.
ipc 리소스는 프로세스가 실행될 때 해제되지 않습니다 . 종료하지만 프로세스를 따릅니다. 커널
은 시스템 인터페이스 free 명령을 사용하여 종료하거나 공유 메모리를 해제합니다.ipcrm shmid

  • 공유 메모리를 제어하는 ​​데 사용
int shmctl(int shmid, int cmd, struct shmid_ds *buf);

매개변수
shmid: shmget에 의해 반환된 공유 메모리 식별 코드
cmd: 수행할 작업(3가지 가능한 값이 있음)
buf: 공유 메모리의 모드 상태 및 액세스 권한을 저장하는 데이터 구조를 가리킴
반환 값: 성공은 0을 반환, 실패는 반환 -1
여기에 이미지 설명 삽입

3. 명령줄 보기 공유 메모리

ipcs -m

여기에 이미지 설명 삽입
shmid : 공유 메모리 번호
소유자 : 작성자
perms : 권한
바이트 수 : 크기
nattch : 연결된 프로세스 수
status : 공유 메모리 세그먼트가 삭제되었지만 여전히 사용자가 사용 중임을 나타내는 "dest"가 표시됩니다. 필드가 SHM_DEST로 설정되면 메모리 "dest" 세그먼트의 모드가 표시됩니다.

4. 실험: 서버와 클라이언트 통신

실험적 현상
여기에 이미지 설명 삽입

  • 공통.h
#include <stdio.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <unistd.h>
#define PATH_NAME  "/root/class101/linux/lesson20/sharememory" 
#define PROJ_ID 18733213
#define SIZE 4097
  • 서버.c
#include "common.h"
int main() {
    
    
  key_t key = ftok(PATH_NAME, PROJ_ID);
  if(key == -1) {
    
    
    perror("ftok");
    return 1;
  }

  printf("key: %x\n", key);

  int shmid = shmget(key, SIZE, IPC_CREAT|IPC_EXCL|0644);

  if(shmid == -1) {
    
    
    perror("shmget");
    return 2;
  }

  printf("shmid: %d\n", shmid);
  sleep(5);


  char* start = (char*)shmat(shmid, NULL, 0);
  if(start == (void*)-1) {
    
    
    perror("shmat");
    return 3;
  }
  printf("shmat success...\n");
  sleep(5);
  while(1) {
    
    
    printf("%s\n", start);
    sleep(1);
  }


  shmdt(start);
  sleep(5);
  shmctl(shmid, IPC_RMID, NULL);
  return 0;
}
  • 클라이언트.c
#include "common.h"
int main(){
    
    
  
  key_t key = ftok(PATH_NAME, PROJ_ID);
  if(key == -1) {
    
    
    perror("ftok");
    return 1;
  }

  int shmid = shmget(key, SIZE, IPC_CREAT);
  if(shmid == -1) {
    
    
    perror("shmget");
    return 2;
  }

  sleep(5);
  char* start = (char*)shmat(shmid, NULL, 0);
  if(start == (void*)-1) {
    
    
    perror("shmat");
    return 3;
  }
  sleep(5);


  char ch = 'A';
  while(ch<='Z') {
    
    
    start[ch-'A'] = ch;
    ch++;
    sleep(1);
  }

  shmdt(start);
  printf("%x\n", key);
  return 0;
} 
  • 메이크파일
CC=gcc
all: server client
server: server.c
	$(CC) -o $@ $^
client: client.c
	$(CC) -o $@ $^
.PHONY: clean
clean: 
	rm -f server client

서버가 무한 루프로 인쇄하기 때문에 결국 수동으로 공유 메모리를 해제해야 합니다.
여기에 이미지 설명 삽입

ipcrm -m 327680

5. 참고/반복

1. 공유 메모리 기능

공유 메모리 공유 메모리 生命周期随OS
작동 공유 메모리는 모든 프로세스 간 통신에 사용됩니다. 공유 메모리 생성에 권장되는 크기는 4KB의 정수배입니다. 그렇지 않으면 시스템이 4KB에 따라 정렬됩니다.不提供任何同步与互斥双方彼此独立
速度最快的

2. 키 대 쉬미드

key: 사용자 계층에서 생성한 고유한 키 값 핵심 기능은 고유성을 구별하는 것으로 IPC 자원을 운용하는 데 사용할 수 없음
shmid: 시스템이 우리에게 반환하는 IPC 자원 식별자로 운용에 사용 IPC 리소스.

  • 여러 프로세스가 동일한 공유 메모리 조각을 보게 하려면 어떻게 해야 합니까?
    Key에 의한 고유한 구별
  • A와 B가 동일한 키를 사용하도록 하는 방법
    key_t ftok(const char* pathname, int proj_id)

3. 시스템 인터페이스

시스템에서 ipc를 보는 명령은ipcs

所有ipc资源都是随内核예, 프로세스가 종료될 때 인터페이스가 릴리스/OS 재시작을 위해 호출되지 않는 한 프로세스가 종료될 때 자동으로 릴리스되지 않습니다.

명령 릴리스 ipc

ipcrm -m shmid

넷째, 루틴

// 키 생성

key_t ftok(pathname, proj_id);

// 공유 메모리 생성

int shmid = shmget(key, SIZE, IPC_CREAT  | IPC_EXCL | 0644);

// 공유 메모리 후크 프로세스

char* start = shmat(shmid, NULL, 0);

// 연결 해제

shmdt(start);

// 해제됨

shmctl(shmid, IPC_RMID, NULL);

추천

출처blog.csdn.net/m0_52640673/article/details/123280222