파일 길이보다 큰 주소를 읽거나 쓸 때 파일 지원 메모리 매핑의 동작은 무엇입니까?

파일 길이보다 큰 주소를 읽거나 쓸 때 파일 지원 메모리 매핑의 동작은 무엇입니까?

길이가 매우 긴 파일의 메모리 맵을 여는 것이 정의되지 않은 동작인지 확인하려고 합니다. 내 사용 사례는 시스템 write호출을 통해 파일을 추가할 때 mremap. mmap예를 들어 너무 크거나 페이지 경계에 정렬되지 않은 경우)"인 경우 EINVAL을 반환합니다. 그러나 이것은 분명히 매우 불분명합니다. 특히 메모리 맵 크기가 파일 크기를 초과하는 경우 동작을 명확하게 설명하지 않습니다. 백업 파일보다 훨씬 큰 메모리 맵을 열고 여기에 값을 쓴 다음 즉시 그 값을 다시 읽는 프로그램을 작성할 때 호출이 mmap오류를 반환하지 않고 값이 실제로 올바르게 기록되는 것을 발견했습니다. 메모리 입력/읽기. 그러나 파일은 변경되지 않았습니다. 최적화 없이 컴파일하고 문제가 있는 값을 손상된 것으로 표시하는 것 외에는 아무것도 수행하지 않는 작은 인라인 어셈블리를 사용하여 이 로드 및 저장소가 최적화되지 않도록 했습니다. 매뉴얼 페이지에는 SIGBUS이 경우에 이를 내보내야 한다고 명시되어 있지만, 내가 아는 한 그렇지 않습니다.

이는 mmap이러한 방식을 사용하면 메모리 맵을 다시 생성하지 않고 파일 변경 사항을 추적하는 사용 사례에서 작동할 수 있음을 의미하지만 이것이 의도적인지 우발적인지 여부에 대한 의문을 제기합니다. 나는 Linux 커널의 보장되지 않은 동작에 의존하고 싶지 않습니다. 특히 정보가 디스크와 제대로 동기화되지 않아 나중에 심각한 오류가 발생할 수 있는 경우에는 더욱 그렇습니다. 이 동작이 어딘가에 정의되거나 보장되어 있습니까?

답변1

답은 (숨겨져있다)mmap(2) 페이지의 NOTES 부분:

   A file is mapped in multiples of the page size.  For a  file  that
   is not a multiple of the page size, the remaining memory is zeroed
   when mapped, and writes to that region are not written out to  the
   file.

그러나 텍스트가 좀 더 명확해질 수 있으며 페이지의 논의가 SIGBUS전혀 명확하지 않습니다. 나는 가지고있다변경됨위의 텍스트는 다음과 같아야 합니다.

   A  file  is mapped in multiples of the page size.  For a file that
   is not a multiple of the page size, the  remaining  bytes  in  the
   partial page at the end of the mapping are zeroed when mapped, and
   modifications to that region are not written out to the file.

설명을 다음과 같이 변경했습니다 SIGBUS.

   SIGBUS Attempted  access  to a page of the buffer that lies beyond
          the end of the mapped file.   For  an  explanation  of  the
          treatment  of the bytes in the page that corresponds to the
          end of a mapped file that is not a  multiple  of  the  page
          size, see NOTES.

답변2

동작이 지정되었지만 지정되지 않았습니다.리눅스 mmap맨페이지, 상당히POSIX에서는:

시스템은 항상 개체 끝에 있는 부분 페이지를 0으로 채워야 합니다. 또한 시스템은 개체의 마지막 페이지 끝 이후에 수정 사항을 기록하지 않습니다. 시작 주소 범위 내의 참조아빠그리고 계속해서런던전체 페이지에 대한 객체 끝 이후의 바이트는 SIGBUS 신호가 전송되도록 합니다.

파일 mmapMAP_SHARED매핑이 파일 크기보다 크고 파일 끝을 넘어 메모리에 쓰려고 하면SIGBUS매핑 자체가 범위를 포함하는 경우에도 이 /proc/.../maps나타날 수 있습니다 ( 확인). 위의 텍스트에서,아빠는 반환된 주소 mmap이므로 사양에 따르면 매핑된 메모리 영역 내에 있지만 매핑된 개체의 끝을 완전히 벗어난 페이지의 주소에 액세스하면 SIGBUS부분적으로 내부에 있는 페이지에서 읽기 및 쓰기 작업이 수행됩니다. 일반적으로 메모리 관리 장치에서 제공하는 보호에 해당하는 매핑된 개체입니다.

그 외에도 사용 사례에 필요한 동작은 정의되지 않았습니다.

호출 후 매핑된 파일의 크기가 변경되는 경우매핑() 매핑된 파일에 대한 다른 작업의 결과로 파일의 추가 또는 삭제된 부분에 해당하는 매핑된 영역 부분에 대한 참조의 효과는 지정되지 않습니다.

Linux의 페이지 캐싱과 관련된 몇 가지 미묘한 부분이 있습니다(참조:매뉴얼 페이지의 오류 섹션), 이로 인해 위의 내용 외에도 놀라운 동작이 발생할 수 있습니다. 파일 끝을 넘어 맵의 마지막 페이지 내에 기록된 데이터는 파일에 기록되지 않지만 후속 매핑까지 유지될 수 있습니다.

mmapEINVAL제공된 값이 일반적으로 유효하지 않고 매핑되는 파일과 특정 관계가 없는 경우 파일을 매핑할 때 다음을 반환합니다.정렬 요구 사항이 충족되지 않거나 오프셋 및 길이가 커널이 관리할 수 있는 최대 파일 크기와 호환되지 않는 경우.

관련 정보