공유 메모리 작업

4933 단어
서로 다른 프로세스 간의 메모리는 서로 독립된 것이기 때문에 상대방 내의 데이터를 직접 조작할 수 없다. 공유 메모리는 운영체제가 제공하는 메모리 매핑 메커니즘에 의해 서로 다른 프로세스의 주소 공간을 같은 가상 메모리 구역에 매핑하고 서로 다른 프로세스를 공용 메모리 블록으로 조작할 수 있다.공유 메모리는 내부 핵과 프로그램 사이에서 데이터를 복제할 필요가 없기 때문에 효율이 가장 높은 프로세스 간 통신 메커니즘이다.
공유 메모리는 시스템에서 제공하는 mmap 함수를 사용합니다. 이 함수는 가상 메모리의 한 구역에 파일을 비추고 프로그램은 바늘로 이 구역을 인용합니다. 이 메모리 구역에 대한 동작은 파일로 되돌아갑니다. 함수의 원형은 다음과 같습니다.
void *mmap(void *addr, size_t len, int prot, int flags, int fd, off_t offset);
  • 매개 변수 fd는 프로세스 공간에 비치는 파일 설명자로서 open()에서 되돌아옵니다. 또한 fd는 -1로 지정할 수 있습니다. 이때flags 매개 변수 중의 MAP 를 지정해야 합니다.ANON, 익명 맵을 표시합니다. (구체적인 파일 이름은 언급하지 않고 파일의 생성과 열기를 피하며 친연 관계를 가진 프로세스 간 통신에만 사용할 수 있습니다.)
  • len은 호출 프로세스 주소 공간에 비치는 바이트입니다. 비치는 파일의 시작 부분인offset 바이트부터 계산합니다.
  • prot 매개 변수는 공유 메모리에 대한 접근 권한을 지정합니다.PROTREAD(읽기 가능), PROTWRITE(쓰기 가능), PROTEXEC(실행 가능), PROTNONE(액세스 불가).
  • flags는 다음과 같은 일반 값으로 지정됩니다. MAPSHARED, MAP_PRIVATE, MAP_FIXED.여기서 MAPSHARED,MAP_PRIVATE 중 하나를 선택해야 하는 반면 MAPFIXED는 권장되지 않습니다.MAP 로 지정하면SHARED는 매핑된 메모리에 대한 수정 사항이 파일에도 영향을 미칩니다.MAP라면PRIVATE는 매핑된 메모리에 대한 수정 사항이 프로세스에만 표시되고 파일에 영향을 주지 않습니다.
  • offset 매개 변수는 일반적으로 0으로 설정하여 파일 헤더부터 비추는 것을 나타낸다.
  • 매개 변수addr 지정 파일은 프로세스 공간의 시작 주소에 비추어야 합니다. 보통 빈 바늘이 지정되어 있으며, 이 때 시작 주소를 선택하는 작업은 커널에 남겨집니다.함수의 반환 값은 마지막 파일이 프로세스 공간에 비치는 주소이고 프로세스는 시작 주소가 이 값의 유효한 주소로 직접 조작할 수 있습니다.

  • 겸사겸사 shmopen 및 shmunlink 의 두 가지 함수:
    shm_open () 함수 기능: 공유 메모리 헤더 파일을 열거나 만듭니다: #include 함수 원형: int shmopen(const char *name,int oflag,mode_t mode); 반환값: 0 반환 성공, 오류 반환-1 매개 변수:name 공유 메모리 영역의 이름 oflag 로고 비트 mode 권한 비트 매개 변수 설명:oflag 매개 변수는 O 를 포함해야 합니다RDONLY 및 ORDWR 플래그 및 다음과 같은 플래그를 지정할 수 있습니다. OCREAT,O_EXCL 또는 OTRUNC.mode 매개 변수는 권한 위치를 지정하고 O 을 지정합니다CREAT 플래그를 전제로 사용합니다.shm_open의 반환값은 정수 설명자로서 mmap의 다섯 번째 인자로 사용됩니다.shm_unlink () 함수 기능: 공유 메모리 헤더 파일 삭제: #include 함수 원형: int shmunlink(const char *name); 매개 변수:name 공유 메모리 영역의 이름 반환값:0 반환 성공, 오류 반환-1shmunlink 함수는 공유 메모리 대상의 이름을 삭제하고, 하나의 이름을 삭제하면 후속 오픈, mq 만 방지합니다open 또는 sem오픈 호출이 성공했습니다.
    이 문서의 설명을 참고하여 mmap과 같은 함수를 더욱 이해할 수 있습니다.http://www.cnblogs.com/polestar/archive/2012/04/23/2466022.html
    골랑이 cgo를 호출하는 방법을 이용하여 c의 mmap을 실현할 수 있다.실험은 읽기와 쓰기 두 프로그램으로 나뉘는데, 이로써 읽기 프로세스가 공유 메모리에 쓴 정보를 읽을 수 있음을 관찰할 수 있다.
    shm_writer.go 코드 예:
    package main
    
    /*
    #cgo linux LDFLAGS: -lrt
    
    #include <fcntl.h>
    #include <unistd.h>
    #include <sys/mman.h>
    
    #define FILE_MODE (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)
    
    int my_shm_new(char *name) {
        shm_unlink(name);
        return shm_open(name, O_RDWR|O_CREAT|O_EXCL, FILE_MODE);
    }
    */
    import "C"
    import (
        "fmt"
        "unsafe"
    )
    
    const SHM_NAME = "my_shm"
    const SHM_SIZE = 4 * 1000 * 1000 * 1000
    
    type MyData struct {
        Col1 int
        Col2 int
        Col3 int
    }
    
    func main() {
        fd, err := C.my_shm_new(C.CString(SHM_NAME))
        if err != nil {
            fmt.Println(err)
            return
        }
    
        C.ftruncate(fd, SHM_SIZE)
    
        ptr, err := C.mmap(nil, SHM_SIZE, C.PROT_READ|C.PROT_WRITE, C.MAP_SHARED, fd, 0)
        if err != nil {
            fmt.Println(err)
            return
        }
        C.close(fd)
    
        data := (*MyData)(unsafe.Pointer(ptr))
    
        data.Col1 = 100
        data.Col2 = 876
        data.Col3 = 8021
    }
    shm_reader.go 코드 예:
    package main
    
    /*
    #cgo linux LDFLAGS: -lrt
    
    #include <fcntl.h>
    #include <unistd.h>
    #include <sys/mman.h>
    
    #define FILE_MODE (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)
    
    int my_shm_open(char *name) {
        return shm_open(name, O_RDWR, FILE_MODE);
    }
    */
    import "C"
    import (
        "fmt"
        "unsafe"
    )
    
    const SHM_NAME = "my_shm"
    const SHM_SIZE = 4 * 1000 * 1000 * 1000
    
    type MyData struct {
        Col1 int
        Col2 int
        Col3 int
    }
    
    func main() {
        fd, err := C.my_shm_open(C.CString(SHM_NAME))
        if err != nil {
            fmt.Println(err)
            return
        }
    
        ptr, err := C.mmap(nil, SHM_SIZE, C.PROT_READ|C.PROT_WRITE, C.MAP_SHARED, fd, 0)
        if err != nil {
            fmt.Println(err)
            return
        }
        C.close(fd)
    
        data := (*MyData)(unsafe.Pointer(ptr))
    
        fmt.Println(data)
    }

    위의 프로그램은 mmap이 실제 4G 메모리를 차지하지 않고 가상 메모리를 사용했다는 것을 증명하기 위해 4G의 가상 메모리를 비추었다.shm_writer가 공유 메모리를 만든 후 메모리 영역에 구조체를 썼습니다.shmreader는 구조체를 읽습니다.
    위 코드에서shm 와 같은 cgo의 기교를 사용했다open과 mmap 함수는 오류가 발생할 때errno를 되돌려줍니다. go에서 다중 되돌려주기 문법을 사용하면 cgo는 오류 코드를 오류 정보로 변환하여 편리한 기능을 제공합니다.

    좋은 웹페이지 즐겨찾기