2017-10-19 3 views
0

나는 이것이 나와 함께 클릭하지 않는 주제에 대한 숙제이므로 더 많은 설명에 초점을 맞추면 크게 감사 할 것입니다.내 공유 메모리의 이름을 파이프에 쓸 수 없다.

공유 메모리의 이름을 지정하면 다른 여러 프로세스에 액세스 할 수 있도록 공유 메모리를 만들려고합니다. 내 다른 프로세스는 파이프를 통해 부모 프로세스에 연결되며, 공유 메모리가 작성된 후 파이프에 공유 메모리의 이름을 쓰려고합니다. 지금까지 제 코드가 있습니다. 나는 print 서술서를 만들 수 없다.

쓰기를 주석 처리하면 프로그램이 한 번 작동합니다. 그러나 프로그램을 다시 실행하려고하면 내 이름 공간의 이름을 변경해야 작동 할 수 있습니다. 나는 그것이 왜 일어나고 있는지 이해하지 못한다. 내가 이해하지 못하는 기능 중 하나의 속성이있을 것이라고 확신합니다. 당신의 write() 호출에

int shm; 
    char *p; 
    shm = shm_open("Name", O_RDWR | O_CREAT, S_IRUSR | S_IWUSR); 
    size_t len = 4 * 255; 

    if (ftruncate(shm, len) == -1) { 
    perror("Truncate"); 
    return 1; 
    } 

    p = mmap(0, 4, PROT_WRITE, MAP_SHARED, shm, 0); 
    if (p == MAP_FAILED){ 
    perror("mmap"); 
    return 1; 
    } 

    write(fd[1], "Name", 30); 

    printf("Initiator: Shared memory for Consonanats is %d.\n", shm); 
+0

열린 자원은 모두 끝나면 닫아야합니다. 공유 메모리를 shm_close해야한다. 그러면 프로그램을 다시 실행할 때마다 네임 스페이스를 변경해야 할 필요가 없어 질 것입니다. – Hypino

+0

공유 메모리 세그먼트의 이름은 슬래시 ('/')로 시작해야합니다. –

+0

@Hypino, "shm_unlink"의 철자가 틀린 것 같습니다. shm_close()는 shm_open()에 대한 표준 카운터가 아닙니다. –

답변

0

인수는 일치하지 않습니다 : 당신은 분명히 배열의 경계를 넘 5 바이트 배열의 30 바이트를 작성하려고

write(fd[1], "Name", 30); 

.

또한 write() 호출의 반환 값을 확인하지 않습니다. 원칙적으로 짧은 쓰기가 발생할 수 있으므로 나머지 바이트를 전송하기 위해 하나 이상의 추가 호출을해야합니다. 아마도 더 많은 가능성이있어, 글을 쓰는 데 실패 할 수도 있습니다.이 경우에는 예고하고 뭔가를하고 싶을 것입니다. 두 조건 중 하나가 write()의 반환 값을 통해 전달됩니다.

는 또한 쓰기 :

내가 다시 프로그램을 실행하려고 할 때, 나는 그것이 작동하려면 내 이름 공간의 이름을 변경해야합니다. 나는 그것이 왜 일어나고 있는지 이해하지 못한다. 을 이해하지 못하는 기능 중 하나의 속성이있을 것입니다.

네, 이해할 수없는 속성이 있습니다. 공유 메모리 세그먼트에는 커널 범위와 지속성이 있습니다. 다른 말로하면, 수명이 자신을 만드는 프로세스의 수명에만 국한되지 않으며, 시스템의 이름이 시스템에 대한 전역이라는 것을 의미합니다. 그렇기 때문에 서로 다른 프로세스가 동일한 이름을 지정하여 동일한 세그먼트에 대한 액세스 권한을 얻을 수 있습니다.

@Hypino가 주석에서 관찰 한 바와 같이, 사용자가 만든 세그먼트를 절대 제거하지 않습니다. 실제로, 당신은 그것을 직접 할 수 없습니다; 대신 을 통해 shm_unlink()을 통해 연결 해제해야합니다. 세그먼트의 이름은 커널에서 분리되지만 직접적으로 파기하지는 않습니다. 다른 프로세스 (또는 동일한 프로세스조차도)가 여전히 그것을 사용할 수 있기 때문에 안전하지 않을 수 있습니다. 링크가 해제 된 후에는 세그먼트가 해체되고 제거 될 예정이지만 프로세스가 매핑되지 않으면 세그먼트가 삭제됩니다. 그 동안 지정된 이름을 가진 다른 세그먼트를 만들 수 있습니다.

따라서 공유 메모리 세그먼트를 안전하고 실용적으로 해제하는 즉시 링크를 해제하는 것이 일반적입니다. 결과적으로, 그것은 (이름으로) 맵핑해야하는 모든 프로세스가 그렇게 한 후에 가능한 한 빨리 의미합니다. 세그먼트 매핑은 프로세스 별 속성이므로 프로세스가 종료 될 때 사라집니다.

실제로 이름을 재사용하면 문제가 발생하는 이유는 분명하지 않습니다.플래그 중에 O_EXCL을 지정하지 않으면 이전 실행에서 남겨진 기존 공유 메모리 세그먼트를 열 수 있어야합니다. 그 특정 문제가 당신이 생략 한 코드에서 뭔가를 중심으로 용의자.

또한 세그먼트 이름과 관련하여 선택 이름 지정의 자유가 절대적이지 않음을 유의하십시오. shm_open()의 리눅스 설명서가 말했듯 : 휴대용 사용을 위해

을, 공유 메모리 객체 형태 /somename의 이름으로 식별되어야한다; 즉 슬래시로 시작하고 그 뒤에 하나 이상의 문자 (슬래시가 없음)가 뒤에 오는 NAME_MAX (즉, 255)까지의 널로 끝나는 문자열입니다.

+0

당신은 저의 교수가 전체 강연에서 한 것보다 3 단락에서 더 많이 가르쳐 줬습니다. 정말 고마워요! 대단히 감사합니다. – user4493284