VC + + 에서 메모리 맵 파일 로 큰 파일 처리 하기 2 (전송)
VC + + 에서 메모리 맵 파일 로 큰 파일 처리 1 모음 집
저자: 랑 예 출처: 중국 전파 연구소
CreateFileMapping () 함수 가 파일 맵 커 널 대상 을 만 들 고 인자 hFile 을 통 해 프로 세 스 주소 공간 에 매 핑 될 파일 핸들 을 지정 합 니 다. (이 핸들 은 CreateFile () 함수 의 반환 값 으로 가 져 옵 니 다.)메모리 맵 파일 의 물리 적 저장 소 는 실제 디스크 에 저 장 된 파일 이기 때문에 시스템 의 페이지 파일 에서 분 배 된 메모리 가 아 닙 니 다. 따라서 시스템 은 주소 공간 영역 을 자발적으로 보존 하지 않 고 파일 의 저장 공간 을 이 지역 에 자동 으로 표시 하지 않 습 니 다. 시스템 이 페이지 에 어떤 보호 속성 을 취 하 는 지 확인 할 수 있 도록 합 니 다.인자 flProtect 를 통 해 속성 보호 PAGE 를 설정 해 야 합 니 다.READONLY、PAGE_REATWRITE 와 PAGEWRITECOPY 는 각각 파일 매 핑 대상 이 매 핑 된 후 파일 데 이 터 를 읽 고 쓸 수 있 음 을 나타 낸다.PAGE 사용 중READOnly 시 Create File () 이 GENERIC 를 사용 하 는 지 확인 해 야 합 니 다.READ 매개 변수;PAGE_REATWRITE 는 Create File () 에 GENERIC 를 사용 하도록 요구 했다.READ|GENERIC_WRITE 매개 변수;속성 에 대해 PAGEWRITECOPY 는 CreateFile () 이 GENERIC 를 사 용 했 는 지 확인 하기 만 하면 된다.READ 와 GENERICWRITE 중 하나 면 됩 니 다.DWORD 형의 매개 변수 dwMaximum SizeHigh 와 dwMaximum SizeLow 도 상당히 중요 합 니 다. 파일 의 최대 바이트 수 를 지 정 했 습 니 다. 이 두 매개 변 수 는 모두 64 비트 이기 때문에 지원 하 는 최대 파일 길 이 는 16EB 로 빅 데이터 파일 처리 장소의 요 구 를 거의 만족 시 킬 수 있 습 니 다.
LPVOID MapViewOfFile(HANDLE hFileMappingObject,
DWORD dwDesiredAccess,
DWORD dwFileOffsetHigh,
DWORD dwFileOffsetLow,
DWORD dwNumberOfBytesToMap);
MapViewOfFile () 함 수 는 파일 데 이 터 를 프로 세 스 의 주소 공간 에 비 추 는 것 을 책임 집 니 다. 인자 hFileMappingObject 는 Create FileMapping () 이 되 돌아 오 는 파일 이미지 대상 핸들 입 니 다.인자 dwDesiredAccess 는 파일 데이터 에 대한 접근 방식 을 다시 지정 하고 Create FileMapping () 함수 가 설정 한 보호 속성 과 일치 해 야 합 니 다.여기 서 보호 속성 을 반복 적 으로 설정 하 는 것 은 불필요 해 보이 지만 응용 프로그램 이 데이터 의 보호 속성 에 대해 효과 적 인 통 제 를 할 수 있 습 니 다.MapViewOfFile () 함 수 는 전체 또는 일부 맵 파일 을 허용 합 니 다. 맵 을 표시 할 때 데이터 파일 의 오프셋 주소 와 매 핑 할 길 이 를 지정 해 야 합 니 다.이 가운데 파일 의 오프셋 주 소 는 DWORD 형의 매개 변수 인 dwFileOffset High 와 dwFileOffset Low 로 구 성 된 64 비트 값 으로 지정 되 며, 운영 체제 의 할당 입도 의 정수 배 여야 하 며, 윈도 우즈 운영 체제 에 대해 서 는 할당 입도 가 64KB 로 고정 되 어 있다.물론 다음 코드 를 통 해 현재 운영 체제 의 배분 입 도 를 동적 으로 얻 을 수 있 습 니 다.
SYSTEM_INFO sinf;
GetSystemInfo(&sinf);
DWORD dwAllocationGranularity = sinf.dwAllocationGranularity;
매개 변수 dwNumberOfBytesToMap 은 데이터 파일 의 맵 길 이 를 지정 합 니 다. 여기 서 특별히 지적 해 야 할 것 은 Windows 9x 운영 체제 에 대해 MapViewOfFile () 이 전체 파일 맵 대상 을 저장 할 충분 한 영역 을 찾 지 못 하면 빈 값 (NULL) 으로 돌아 갑 니 다.그러나 윈도 2000 에서 MapViewOfFile () 은 필요 한 보 기 를 위해 충분 한 영역 을 찾 으 면 되 며 전체 파일 맵 대상 의 크기 를 고려 하지 않 아 도 된다.
프로 세 스 주소 공간 영역 에 매 핑 된 파일 처 리 를 마 친 후 함수 UnmapViewOfFile () 을 통 해 파일 데이터 이미지 에 대한 방출 을 완료 해 야 합 니 다. 이 함수 프로 토 타 입 은 다음 과 같 습 니 다.
BOOL UnmapViewOfFile(LPCVOID lpBaseAddress);
유일한 인자 인 lpBaseAddress 는 반환 구역 의 기본 주 소 를 지정 하 였 으 며, 이 를 MapViewOfFile () 의 반환 값 으로 설정 해 야 합 니 다.함수 MapViewOfFile () 을 사용 한 후 에는 해당 하 는 UnmapViewOfFile () 호출 이 있어 야 합 니 다. 그렇지 않 으 면 프로 세 스 가 종료 되 기 전에 남 겨 진 영역 을 풀 수 없습니다.이 밖 에 도 앞서 Create File () 과 Create FileMapping () 함수 로 파일 커 널 대상 과 파일 맵 커 널 대상 을 만 든 적 이 있 으 며, 프로 세 스 가 종료 되 기 전에 CloseHandle () 을 통 해 풀 어야 합 니 다. 그렇지 않 으 면 자원 유출 문제 가 발생 할 수 있 습 니 다.
앞에서 필요 한 API 함 수 를 제외 하고 메모리 맵 파일 을 사용 할 때 상황 에 따라 다른 보조 함 수 를 선택해 야 합 니 다.예 를 들 어 메모리 맵 파일 을 사용 할 때 속 도 를 높이 기 위해 시스템 은 파일 의 데이터 페이지 를 고속 캐 시 하고 파일 맵 보 기 를 처리 할 때 파일 의 디스크 이미 지 를 즉시 업데이트 하지 않 습 니 다.이 문 제 를 해결 하기 위해 서 는 FlushviewOfFile () 함 수 를 사용 하 는 것 을 고려 할 수 있 습 니 다. 이 함 수 는 수 정 된 데이터 부분 이나 디스크 이미지 에 모두 다시 쓰 도록 강제 하여 모든 데이터 업데이트 가 디스크 에 제때에 저 장 될 수 있 도록 합 니 다.
CreateFileMapping () 함수 가 파일 맵 커 널 대상 을 만 들 고 인자 hFile 을 통 해 프로 세 스 주소 공간 에 매 핑 될 파일 핸들 을 지정 합 니 다. (이 핸들 은 CreateFile () 함수 의 반환 값 으로 가 져 옵 니 다.)메모리 맵 파일 의 물리 적 저장 소 는 실제 디스크 에 저 장 된 파일 이기 때문에 시스템 의 페이지 파일 에서 분 배 된 메모리 가 아 닙 니 다. 따라서 시스템 은 주소 공간 영역 을 자발적으로 보존 하지 않 고 파일 의 저장 공간 을 이 지역 에 자동 으로 표시 하지 않 습 니 다. 시스템 이 페이지 에 어떤 보호 속성 을 취 하 는 지 확인 할 수 있 도록 합 니 다.인자 flProtect 를 통 해 속성 보호 PAGE 를 설정 해 야 합 니 다.READONLY、PAGE_REATWRITE 와 PAGEWRITECOPY 는 각각 파일 매 핑 대상 이 매 핑 된 후 파일 데 이 터 를 읽 고 쓸 수 있 음 을 나타 낸다.PAGE 사용 중READOnly 시 Create File () 이 GENERIC 를 사용 하 는 지 확인 해 야 합 니 다.READ 매개 변수;PAGE_REATWRITE 는 Create File () 에 GENERIC 를 사용 하도록 요구 했다.READ|GENERIC_WRITE 매개 변수;속성 에 대해 PAGEWRITECOPY 는 CreateFile () 이 GENERIC 를 사 용 했 는 지 확인 하기 만 하면 된다.READ 와 GENERICWRITE 중 하나 면 됩 니 다.DWORD 형의 매개 변수 dwMaximum SizeHigh 와 dwMaximum SizeLow 도 상당히 중요 합 니 다. 파일 의 최대 바이트 수 를 지 정 했 습 니 다. 이 두 매개 변 수 는 모두 64 비트 이기 때문에 지원 하 는 최대 파일 길 이 는 16EB 로 빅 데이터 파일 처리 장소의 요 구 를 거의 만족 시 킬 수 있 습 니 다.
LPVOID MapViewOfFile(HANDLE hFileMappingObject,
DWORD dwDesiredAccess,
DWORD dwFileOffsetHigh,
DWORD dwFileOffsetLow,
DWORD dwNumberOfBytesToMap);
MapViewOfFile () 함 수 는 파일 데 이 터 를 프로 세 스 의 주소 공간 에 비 추 는 것 을 책임 집 니 다. 인자 hFileMappingObject 는 Create FileMapping () 이 되 돌아 오 는 파일 이미지 대상 핸들 입 니 다.인자 dwDesiredAccess 는 파일 데이터 에 대한 접근 방식 을 다시 지정 하고 Create FileMapping () 함수 가 설정 한 보호 속성 과 일치 해 야 합 니 다.여기 서 보호 속성 을 반복 적 으로 설정 하 는 것 은 불필요 해 보이 지만 응용 프로그램 이 데이터 의 보호 속성 에 대해 효과 적 인 통 제 를 할 수 있 습 니 다.MapViewOfFile () 함 수 는 전체 또는 일부 맵 파일 을 허용 합 니 다. 맵 을 표시 할 때 데이터 파일 의 오프셋 주소 와 매 핑 할 길 이 를 지정 해 야 합 니 다.이 가운데 파일 의 오프셋 주 소 는 DWORD 형의 매개 변수 인 dwFileOffset High 와 dwFileOffset Low 로 구 성 된 64 비트 값 으로 지정 되 며, 운영 체제 의 할당 입도 의 정수 배 여야 하 며, 윈도 우즈 운영 체제 에 대해 서 는 할당 입도 가 64KB 로 고정 되 어 있다.물론 다음 코드 를 통 해 현재 운영 체제 의 배분 입 도 를 동적 으로 얻 을 수 있 습 니 다.
SYSTEM_INFO sinf;
GetSystemInfo(&sinf);
DWORD dwAllocationGranularity = sinf.dwAllocationGranularity;
매개 변수 dwNumberOfBytesToMap 은 데이터 파일 의 맵 길 이 를 지정 합 니 다. 여기 서 특별히 지적 해 야 할 것 은 Windows 9x 운영 체제 에 대해 MapViewOfFile () 이 전체 파일 맵 대상 을 저장 할 충분 한 영역 을 찾 지 못 하면 빈 값 (NULL) 으로 돌아 갑 니 다.그러나 윈도 2000 에서 MapViewOfFile () 은 필요 한 보 기 를 위해 충분 한 영역 을 찾 으 면 되 며 전체 파일 맵 대상 의 크기 를 고려 하지 않 아 도 된다.
프로 세 스 주소 공간 영역 에 매 핑 된 파일 처 리 를 마 친 후 함수 UnmapViewOfFile () 을 통 해 파일 데이터 이미지 에 대한 방출 을 완료 해 야 합 니 다. 이 함수 프로 토 타 입 은 다음 과 같 습 니 다.
BOOL UnmapViewOfFile(LPCVOID lpBaseAddress);
유일한 인자 인 lpBaseAddress 는 반환 구역 의 기본 주 소 를 지정 하 였 으 며, 이 를 MapViewOfFile () 의 반환 값 으로 설정 해 야 합 니 다.함수 MapViewOfFile () 을 사용 한 후 에는 해당 하 는 UnmapViewOfFile () 호출 이 있어 야 합 니 다. 그렇지 않 으 면 프로 세 스 가 종료 되 기 전에 남 겨 진 영역 을 풀 수 없습니다.이 밖 에 도 앞서 Create File () 과 Create FileMapping () 함수 로 파일 커 널 대상 과 파일 맵 커 널 대상 을 만 든 적 이 있 으 며, 프로 세 스 가 종료 되 기 전에 CloseHandle () 을 통 해 풀 어야 합 니 다. 그렇지 않 으 면 자원 유출 문제 가 발생 할 수 있 습 니 다.
앞에서 필요 한 API 함 수 를 제외 하고 메모리 맵 파일 을 사용 할 때 상황 에 따라 다른 보조 함 수 를 선택해 야 합 니 다.예 를 들 어 메모리 맵 파일 을 사용 할 때 속 도 를 높이 기 위해 시스템 은 파일 의 데이터 페이지 를 고속 캐 시 하고 파일 맵 보 기 를 처리 할 때 파일 의 디스크 이미 지 를 즉시 업데이트 하지 않 습 니 다.이 문 제 를 해결 하기 위해 서 는 FlushviewOfFile () 함 수 를 사용 하 는 것 을 고려 할 수 있 습 니 다. 이 함 수 는 수 정 된 데이터 부분 이나 디스크 이미지 에 모두 다시 쓰 도록 강제 하여 모든 데이터 업데이트 가 디스크 에 제때에 저 장 될 수 있 도록 합 니 다.
VC + 에서 메모리 맵 파일 로 큰 파일 처리 하기 (3) 모음 집
메모리 맵 파일 로 큰 파일 처리 예제
메모리 맵 파일 의 사용 방법 을 구체 적 인 인 인 스 턴 스 와 결합 하여 설명 합 니 다.이 인 스 턴 스 는 포트 에서 데 이 터 를 받 아 디스크 에 실시 간 으로 저장 합 니 다. 데이터 양 이 많 기 때문에 (수 십 GB) 메모리 맵 파일 을 선택 하여 처리 합 니 다.다음은 작업 스 레 드 MainProc 에 있 는 일부 주요 코드 입 니 다. 이 스 레 드 는 프로그램 이 실 행 될 때 시 작 됩 니 다. 포트 에 데이터 가 도착 하면 이벤트 hEvent [0], WaitForMultiple Objects () 함수 가 이 사건 이 발생 할 때 까지 기 다 렸 다가 받 은 데 이 터 를 디스크 에 저장 합 니 다. 수신 을 중지 하면 이벤트 hEvent [1] 를 보 냅 니 다.이벤트 처리 과정 은 자원 의 방출 과 파일 의 닫 기 등 을 책임 집 니 다.다음은 이 스 레 드 처리 함수 의 구체 적 인 실현 과정 을 보 여 줍 니 다.
……
// , hFile
HANDLE hFile = CreateFile("Recv1.zip",
GENERIC_WRITE | GENERIC_READ,
FILE_SHARE_READ,
NULL,
CREATE_ALWAYS,
FILE_FLAG_SEQUENTIAL_SCAN,
NULL);
// , hFileMapping
HANDLE hFileMapping = CreateFileMapping(hFile,NULL,PAGE_READWRITE,
0, 0x4000000, NULL);
//
CloseHandle(hFile);
// 、
__int64 qwFileSize = 0x4000000;
__int64 qwFileOffset = 0;
__int64 T = 600 * sinf.dwAllocationGranularity;
DWORD dwBytesInBlock = 1000 * sinf.dwAllocationGranularity;
//
PBYTE pbFile = (PBYTE)MapViewOfFile(hFileMapping,
FILE_MAP_ALL_ACCESS,
(DWORD)(qwFileOffset>>32), (DWORD)(qwFileOffset&0xFFFFFFFF), dwBytesInBlock);
while(bLoop)
{
// hEvent[0] hEvent[1]
DWORD ret = WaitForMultipleObjects(2, hEvent, FALSE, INFINITE);
ret -= WAIT_OBJECT_0;
switch (ret)
{
//
case 0:
//
nReadLen=syio_Read(port[1], pbFile + qwFileOffset, QueueLen);
qwFileOffset += nReadLen;
// 60% , ,
if (qwFileOffset > T)
{
T = qwFileOffset + 600 * sinf.dwAllocationGranularity;
UnmapViewOfFile(pbFile);
pbFile = (PBYTE)MapViewOfFile(hFileMapping,
FILE_MAP_ALL_ACCESS,
(DWORD)(qwFileOffset>>32), (DWORD)(qwFileOffset&0xFFFFFFFF), dwBytesInBlock);
}
break;
//
case 1:
bLoop = FALSE;
//
UnmapViewOfFile(pbFile);
//
CloseHandle(hFileMapping);
break;
}
}
…
이벤트 트리거 처 리 를 종료 하 는 과정 에서 UnmapViewOfFile () 과 CloseHandle () 함수 만 간단하게 실행 하면 파일 의 실제 크기 를 정확하게 표시 할 수 없습니다. 즉, 열 린 메모리 맵 파일 이 30GB 이 고 받 은 데 이 터 는 14GB 에 불과 하 다 면 상기 프로그램 이 실 행 된 후에 도 저 장 된 파일 의 길 이 는 30GB 입 니 다.즉, 처리 가 끝 난 후에 다시 메모리 맵 파일 형식 으로 파일 을 실제 크기 로 복원 해 야 합 니 다. 다음은 이 요 구 를 실현 하 는 주요 코드 입 니 다.
//
hFile2 = CreateFile("Recv.zip",
GENERIC_WRITE | GENERIC_READ,
FILE_SHARE_READ,
NULL,
CREATE_ALWAYS,
FILE_FLAG_SEQUENTIAL_SCAN,
NULL);
//
hFileMapping2 = CreateFileMapping(hFile2,
NULL,
PAGE_READWRITE,
0,
(DWORD)(qwFileOffset&0xFFFFFFFF),
NULL);
//
CloseHandle(hFile2);
//
pbFile2 = (PBYTE)MapViewOfFile(hFileMapping2,
FILE_MAP_ALL_ACCESS,
0, 0, qwFileOffset);
//
memcpy(pbFile2, pbFile, qwFileOffset);
file://
UnmapViewOfFile(pbFile);
UnmapViewOfFile(pbFile2);
//
CloseHandle(hFileMapping);
CloseHandle(hFileMapping2);
//
DeleteFile("Recv1.zip");
결론.
실제 테스트 를 통 해 메모리 맵 파일 은 빅 데이터 파일 을 처리 할 때 좋 은 성능 을 보 였 으 며, 일반적으로 CFile 류 와 ReadFile (), Write File () 등 함 수 를 사용 하 는 파일 처리 방식 보다 뚜렷 한 장점 을 가지 고 있다.본 논문 에서 말 한 코드 는 Windows 98 에서 Microsoft Visual C + 6.0 으로 컴 파일 되 었 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSONJSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다. 그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다. 저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.