-
Win32Platform/메모리 2009. 2. 10. 21:30MmMapLockedPages() // ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL) or ASSERT(KeGetCurrentIrql() <= APC_LEVEL)
MmUnmapLockedPages() // ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL) or ASSERT(KeGetCurrentIrql() <= APC_LEVEL)
IoAllocateMdl() // ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL)
MmBuildMdlForNonPagedPool() // ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL)
IoFreeMdl() // ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL)
MmGetSystemAddressForMdl() // ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL)
MmMapIoSpace() // ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL)
MmUnmapIoSpace() // ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL)
==
가상 메모리
VirtualAlloc() // 페이지 단위 malloc()?
MEM_COMMIT
PAGE_READWRITE
VirtualFree()
MEM_RELEASE
VirtualLock()
VirtualUnlock(()
Windows Heap
프로세스의 디폴트 힙으로의 접근은 직렬화된다.
추가의 힙을 사용
성능
할당의 효율
디버깅 목적으로 데이터 컴포넌트를 격리
하나의 힙으로 충분한 경우라면 C라이브러리 메모리 관리 함수들(malloc, free, calloc, realloc)을 사용하면 된다.
프로세스 힙을 파괴해서는 안된다.
HeapCreate()
HEAP_NO_SERIALIZE
HEAP_GENERATE_EXCEPTIONS
HeapDestroy()
C++ 객체 인스턴스들의 소멸자가 호출되지 않는다.
HeapLock() // 동기화
HeapUnlock()
HeapAlloc() // malloc() - <stdlib.h>
HEAP_ZERO_MEMORY
HEAP_GENERATE_EXCEPTIONS
HeapRealloc() // realloc()
HEAP_ZERO_MEMORY
HEAP_GENERATE_EXCEPTIONSHeapFree() // free
GetProcessHeap()
GetProcessHeaps()
HeapSize()
HeapCompact()
HeapValidate()
HeapWalk()
GlobalAlloc()
GMEM_MOVEABLE
GMEM_FIXED
GMEM_ZEROINIT
GHND
GPTR
GlobalFree()
LocalAlloc()
GlobalLock()
GlobalUnlock()
#define KEY_SIZE 8
/* Structure definition for a tree node. */
typedef struct _TreeNode {
struct _TreeNode *Left, *Right;
TCHAR Key [KEY_SIZE];
LPTSTR pData;
} TREENODE, *LPTNODE, **LPPTNODE;
#define NODE_SIZE sizeof (TREENODE)
#define NODE_HEAP_ISIZE 0x8000
#define DATA_HEAP_ISIZE 0x8000
#define MAX_DATA_LEN 0x1000
#define TKEY_SIZE KEY_SIZE * sizeof (TCHAR)
LPTNODE FillTree (HANDLE, HANDLE, HANDLE);
BOOL Scan (LPTNODE);
int KeyCompare (LPCTSTR, LPCTSTR); iFile; /* for access in exception handler */
BOOL InsertTree (LPPTNODE, LPTNODE);
int _tmain (int argc, LPTSTR argv [])
{
HANDLE hIn, hNode = NULL, hData = NULL;
LPTNODE pRoot;
BOOL NoPrint;
CHAR ErrorMessage[256];
int iFirstFile = Options (argc, argv, _T ("n"), &NoPrint, NULL);
if (argc <= iFirstFile)
ReportError (_T ("Usage: sortBT [options] files"), 1, FALSE);
/* Process all files on the command line. */
for (iFile = iFirstFile; iFile < argc; iFile++) __try {
/* Open the input file. */
hIn = CreateFile (argv [iFile], GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
if (hIn == INVALID_HANDLE_VALUE)
RaiseException (0, 0, 0, NULL);
/* Allocate the two heaps. */
__try {
hNode = HeapCreate (
HEAP_GENERATE_EXCEPTIONS | HEAP_NO_SERIALIZE, NODE_HEAP_ISIZE, 0);
hData = HeapCreate (
HEAP_GENERATE_EXCEPTIONS | HEAP_NO_SERIALIZE, DATA_HEAP_ISIZE, 0);
/* Process the input file, creating the tree. */
pRoot = FillTree (hIn, hNode, hData);
/* Display the tree in Key order. */
if (!NoPrint) {
_tprintf (_T ("Sorted file: %s\n"), argv [iFile]);
Scan (pRoot);
}
} __finally { /* Heaps and file handle are always closed */
/* Destroy the two heaps and data structures. */
if (hNode != NULL) HeapDestroy (hNode);
if (hData!= NULL) HeapDestroy (hData);
hNode = NULL; hData = NULL;
if (hIn != INVALID_HANDLE_VALUE) CloseHandle (hIn);
}
} /* End of main file processing loop and try block. */
__except (EXCEPTION_EXECUTE_HANDLER) {
_stprintf (ErrorMessage, _T("\n%s %s"), _T("sortBT error on file:"), argv[iFile]);
ReportError (ErrorMessage, 0, TRUE);
}
return 0;
}
LPTNODE FillTree (HANDLE hIn, HANDLE hNode, HANDLE hData)
/* Scan the input file, creating a binary search tree in the
hNode heap with data pointers to the hData heap. */
/* Use the calling program's exception handler. */
{
LPTNODE pRoot = NULL, pNode;
DWORD nRead, i;
BOOL AtCR;
TCHAR DataHold [MAX_DATA_LEN];
LPTSTR pString;
/* Open the input file. */
while (TRUE) {
pNode = HeapAlloc (hNode, HEAP_ZERO_MEMORY, NODE_SIZE);
pNode->pData = NULL;
(pNode->Left) = pNode->Right = NULL;
/* Read the key. Return if done. */
if (!ReadFile (hIn, pNode->Key, TKEY_SIZE,
&nRead, NULL) || nRead != TKEY_SIZE)
/* Assume end of file on error. */
return pRoot; /* Read the data until the end of line. */
AtCR = FALSE; /* Last character was not a CR. */
for (i = 0; i < MAX_DATA_LEN; i++) {
ReadFile (hIn, &DataHold [i], TSIZE, &nRead, NULL);
if (AtCR && DataHold [i] == LF) break;
AtCR = (DataHold [i] == CR);
}
DataHold [i - 1] = '\0';
/* DataHold contains the data without the key.
Combine the Key and the Data. */
pString = HeapAlloc (hData, HEAP_ZERO_MEMORY,
(SIZE_T)(KEY_SIZE + _tcslen (DataHold) + 1) * TSIZE);
memcpy (pString, pNode->Key, TKEY_SIZE);
pString [KEY_SIZE] = '\0';
_tcscat (pString, DataHold);
pNode->pData = pString;
/* Insert the new node into the search tree. */
InsertTree (&pRoot, pNode);
} /* End of while (TRUE) loop */
return NULL; /* Failure */
}
BOOL InsertTree (LPPTNODE ppRoot, LPTNODE pNode)
/* Insert the new node, pNode, into the binary search tree, pRoot. */
{
if (*ppRoot == NULL) {
*ppRoot = pNode;
return TRUE;
}
if (KeyCompare (pNode->Key, (*ppRoot)->Key) < 0)
InsertTree (&((*ppRoot)->Left), pNode);
else
InsertTree (&((*ppRoot)->Right), pNode);
return TRUE;
}
int KeyCompare (LPCTSTR pKey1, LPCTSTR pKey2)
/* Compare two records of generic characters.
The key position and length are global variables. */
{
return _tcsncmp (pKey1, pKey2, KEY_SIZE);
}
static BOOL Scan (LPTNODE pNode)
/* Scan and print the contents of a binary tree. */
{
if (pNode == NULL)
return TRUE;
Scan (pNode->Left);
_tprintf (_T ("%s\n"), pNode->pData);
Scan (pNode->Right);
return TRUE;
}
메모리 맵드 파일(memory-mapped file)
파일 매핑 객체
CreateFileMapping()
OpenFileMapping()
MapViewOfFile()
MapViewOfFileEx()
UnMapViewOfFile()
FlushViewOfFile()
BOOL Asc2Un (LPCTSTR fIn, LPCTSTR fOut, BOOL bFailIfExists)
/* ASCII to Unicode file copy function.
* fIn: Source file pathname.
* fOut: Destination file pathname.
* bFailIfExists: Do not copy if the destination file already exists.
* Behavior is modeled on CopyFile. */
{
BOOL Complete = FALSE;
_try {
HANDLE hIn, hOut;
HANDLE hInMap, hOutMap;
LPSTR pIn, pInFile;
LPWSTR pOut, pOutFile;
DWORD FsLow, fdwOut;
/* Open the input file. */
hIn = CreateFile (fIn, GENERIC_READ, 0, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hIn == INVALID_HANDLE_VALUE)
ReportException (_T ("Failure opening input file."), 1);
/* Create a file mapping object on the input file. Use the file size. */
hInMap = CreateFileMapping (hIn, NULL, PAGE_READONLY, 0, 0, NULL);
if (hInMap == INVALID_HANDLE_VALUE)
ReportException (_T ("Failure Creating input map."), 2);
/* Map the input file */
pInFile = MapViewOfFile (hInMap, FILE_MAP_READ, 0, 0, 0);
if (pInFile == NULL)
ReportException (_T ("Failure Mapping input file."), 3);
/* Get the input file size. As the mapping succeeded, the file size is < 2 GB. */
FsLow = GetFileSize (hIn, NULL);
if (FsLow == 0xFFFFFFFF)
ReportException (_T ("Failure getting file size."), 4);
/* Create/Open the output file. */
fdwOut = bFailIfExists ? CREATE_NEW : CREATE_ALWAYS;
/* The output file MUST have Read/Write access for the mapping to succeed. */
hOut = CreateFile (fOut, GENERIC_READ | GENERIC_WRITE,
0, NULL, fdwOut, FILE_ATTRIBUTE_NORMAL, NULL);
if (hOut == INVALID_HANDLE_VALUE) {
Complete = TRUE; /* Do not delete an existing file. */
ReportException (_T ("Failure Opening output file."), 5);
}
/* Set the output file's size to twice the input size. */
/* This commented code is included for illustration and as an alterantive */
/* to setting the file size in the CreateFileMapping call */
/* if ( SetFilePointer (hOut, 2 * FsLow, NULL, FILE_BEGIN) == 0xFFFFFFFF
|| !SetEndOfFile (hOut))
ReportException (_T ("Failure setting file size."), 6);
*/
/* Map the output file. Using the file length in the next two calls
is optional but must be done if you do not set the file size above.
In fact, using the file size on CreateFileMapping will expand
the file if it is smaller than the mapping. */
hOutMap = CreateFileMapping (hOut, NULL, PAGE_READWRITE, 0, 2 * FsLow, NULL);
if (hOutMap == INVALID_HANDLE_VALUE)
ReportException (_T ("Failure creating output map."), 7);
pOutFile = MapViewOfFile (hOutMap, FILE_MAP_WRITE, 0, 0, (SIZE_T)(2 * FsLow));
if (pOutFile == NULL)
ReportException (_T ("Failure mapping output file."), 8);
/* Now move the input file to the output file, doing all the work in memory. */
pIn = pInFile;
pOut = pOutFile;
while (pIn < pInFile + FsLow) {
*pOut = (WCHAR) *pIn;
pIn++;
pOut++;
}
/* Close all views and handles. */
UnmapViewOfFile (pOutFile);
UnmapViewOfFile (pInFile);
CloseHandle (hOutMap);
CloseHandle (hInMap);
CloseHandle (hIn);
CloseHandle (hOut);
Complete = TRUE;
return TRUE;
}
_except (EXCEPTION_EXECUTE_HANDLER) {
/* Delete the output file if the operation did not complete successfully. */
if (!Complete)
DeleteFile (fOut);
return FALSE;
}
}
/* Definitions of the record structure in the sort file. */
#define DATALEN 56
#define KEY_SIZE 8
typedef struct _RECORD {
TCHAR Key [KEY_SIZE];
TCHAR Data [DATALEN];
} RECORD;
#define RECSIZE sizeof (RECORD)
typedef RECORD * LPRECORD;
int KeyCompare (LPCTSTR, LPCTSTR);
int _tmain (int argc, LPTSTR argv [])
{
/* The file is the first argument. Sorting is done in place. */
/* Sorting is done by file memory mapping. */
HANDLE hFile = INVALID_HANDLE_VALUE, hMap = NULL;
HANDLE hStdOut = GetStdHandle (STD_OUTPUT_HANDLE);
LPVOID pFile = NULL;
DWORD FsLow, Result = 2;
TCHAR TempFile [MAX_PATH];
LPTSTR pTFile;
BOOL NoPrint;
int iFirstFile;
iFirstFile = Options (argc, argv, _T ("n"), &NoPrint, NULL);
if (argc <= iFirstFile)
ReportError (_T ("Usage: sortFL [options] files"), 1, FALSE);
_try { /* try-except */
/* Copy the input file to a temp output file that will be sorted.
Do not alter the input file. */
_stprintf (TempFile, _T ("%s%s"), argv [iFirstFile], _T (".tmp"));
CopyFile (argv [iFirstFile], TempFile, TRUE);
Result = 1; /* tmp file is new and should be deleted. */
/* Open the file (use the temporary copy). */
hFile = CreateFile (TempFile, GENERIC_READ
| GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
if (hFile ==INVALID_HANDLE_VALUE)
ReportException (_T ("File open failed."), 2);
/* Get file size.
If the file is too large, catch that when it is mapped. */
FsLow = GetFileSize (hFile, NULL);
if (FsLow == 0) { /* There is nothing to sort */
CloseHandle (hFile);
return 0; /* You might want to put out an informational message */
}
/* Create a file mapping object.
Use the file size but add space for the null character. */
hMap = CreateFileMapping (hFile, NULL, PAGE_READWRITE, 0, FsLow + TSIZE, NULL);
if (hMap == NULL)
ReportException (_T ("Create File map failed."), 3);
pFile = MapViewOfFile (hMap, FILE_MAP_ALL_ACCESS, 0, 0 /* FsLow + TSIZE */, 0);
if (pFile == NULL)
ReportException (_T ("MapView failed"), 4);
/* Now sort the file.
Perform the sort with the C library - in mapped memory. */
qsort (pFile, FsLow / RECSIZE, RECSIZE, KeyCompare);
/* Print out the entire sorted file. Treat it as one single string. */
pTFile = (LPTSTR) pFile;
pTFile [FsLow/TSIZE] = '\0';
if (!NoPrint)
PrintMsg (hStdOut, pFile);
/* Indicate successful completion. */
Result = 0;
ReportException (EMPTY, 5); /* Force an exception to clean up. */
return 0;
} /* End of inner try-except. */
_except (EXCEPTION_EXECUTE_HANDLER) {
/* Catch any exception here. Indicate any error.
This is the normal termination. Delete the temporary
file and Free all the resources. */
if (pFile != NULL)
UnmapViewOfFile (pFile);
if (hMap != NULL)
CloseHandle (hMap);
if (hFile != INVALID_HANDLE_VALUE)
CloseHandle (hFile);
if (Result != 2)
DeleteFile (TempFile);
return Result;
}
} /* End of _tmain */
int KeyCompare (LPCTSTR pKey1, LPCTSTR pKey2)
/* Compare two records of generic characters.
The key position and length are global variables. */
{
return _tcsncmp (pKey1, pKey2, KEY_SIZE);
}
int KeyCompare (LPCTSTR, LPCTSTR);
DWORD CreateIndexFile (DWORD, LPCTSTR, LPTSTR);
DWORD_PTR KStart, KSize; /* Key start position & size (TCHAR). */
BOOL Revrs;
int _tmain (int argc, LPTSTR argv [])
{
/* The file is the first argument. Sorting is done in place. */
/* Sorting is done by file memory mapping. */
HANDLE hInFile, hInMap; /* Input file handles. */
HANDLE hXFile, hXMap; /* Index file handles. */
HANDLE hStdOut = GetStdHandle (STD_OUTPUT_HANDLE);
BOOL IdxExists, NoPrint;
DWORD FsIn, FsX, RSize, iKey, nWrite, *pSizes;
LPTSTR pInFile = NULL;
LPBYTE pXFile = NULL, pX;
TCHAR _based (pInFile) *pIn;
TCHAR IdxFlNam [MAX_PATH], ChNewLine = '\n';
int FlIdx;
/* Determine the options. */
FlIdx = Options (argc, argv, _T ("rIn"), &Revrs, &IdxExists, &NoPrint, NULL);
if (FlIdx >= argc)
ReportError (_T ("No file name on command line."), 1, FALSE);
/* Step 1: Open and Map the Input File. */
hInFile = CreateFile (argv [FlIdx], GENERIC_READ | GENERIC_WRITE,
0, NULL, OPEN_EXISTING, 0, NULL);
if (hInFile == INVALID_HANDLE_VALUE)
ReportError (_T ("Failed to open input file."), 2, TRUE);
/* Create a file mapping object. Use the file size. */
hInMap = CreateFileMapping (hInFile, NULL, PAGE_READWRITE, 0, 0, NULL);
if (hInMap == NULL)
ReportError (_T ("Failed to create input file mapping."), 3, TRUE);
pInFile = MapViewOfFile (hInMap, FILE_MAP_ALL_ACCESS, 0, 0, 0);
if (pInFile == NULL)
ReportError (_T ("Failed to map input file."), 4, TRUE);
/* Get the file size.
As the mapping succeeded, the file size is less than 2 GB. */
FsIn = GetFileSize (hInFile, NULL);
/* Create the index file name. */
_stprintf (IdxFlNam, _T ("%s%s"), argv [FlIdx], _T (".idx"));
/* Steps 2 and 3, if necessary. */
if (!IdxExists)
RSize = CreateIndexFile (FsIn, IdxFlNam, pInFile);
/* Step 4. Map the index file. */
hXFile = CreateFile (IdxFlNam, GENERIC_READ | GENERIC_WRITE,
0, NULL, OPEN_EXISTING, 0, NULL);
if (hXFile == INVALID_HANDLE_VALUE)
ReportError (_T ("Failed to open existing index file."), 5, TRUE);
/* Create a file mapping object. Use the file size. */
hXMap = CreateFileMapping (hXFile, NULL, PAGE_READWRITE, 0, 0, NULL);
if (hXMap == NULL)
ReportError (_T ("Failed to create index file mapping."), 6, TRUE);
pXFile = MapViewOfFile (hXMap, FILE_MAP_ALL_ACCESS, 0, 0, 0);
if (pXFile == NULL)
ReportError (_T ("Failed to map index file."), 7, TRUE);
FsX = GetFileSize (hXFile, NULL);
/* Get the key size/key start and adjust the file size for the
KeySize/KeyStart fields. Compute the record size from the key size. */
pSizes = (LPDWORD)pXFile; KSize = *pSizes;
KStart = *(pSizes + 1);
FsX -= 2 * sizeof (DWORD);
/* Step 5. Sort the index file using qsort. */
if (!IdxExists)
qsort (pXFile + 2 * sizeof (DWORD), FsX / RSize, RSize, KeyCompare);
/* Step 6. Output the input file in sorted order. */
/* Point to the address of the input file string.
Start in the Input file. */
pX = pXFile + 2 * sizeof (DWORD) + RSize - sizeof (LPTSTR);
if (!NoPrint)
for (iKey = 0; iKey < FsX / RSize; iKey++) {
WriteFile (hStdOut, &ChNewLine, TSIZE, &nWrite, NULL);
/* The cast on pX is important, as it is a pointer to a
byte and we need the four bytes of a based pointer. */
pIn = (TCHAR _based (pInFile)*) *(DWORD_PTR *) pX;
while ((*pIn != CR || *(pIn + 1) != LF) && (SIZE_T) pIn < (SIZE_T)FsIn) {
WriteFile (hStdOut, pIn, TSIZE, &nWrite, NULL);
pIn++;
}
pX += RSize;
}
/* Done. Free all the handles and maps. */
UnmapViewOfFile (pInFile);
CloseHandle (hInMap);
CloseHandle (hInFile);
UnmapViewOfFile (pXFile);
CloseHandle (hXMap);
CloseHandle (hXFile);
return 0;
}
DWORD CreateIndexFile (DWORD FsIn, LPCTSTR IdxFlNam, LPTSTR pInFile)
/* Perform Steps 2-3 as defined in program description. */
/* This step will be skipped if the options specify use of an existing index file. */
{
HANDLE hXFile;
TCHAR _based (pInFile) *pInScan = 0;
DWORD nWrite;
/* Step 2a: Create an index file.
Do not map it yet as its length is not known. */
hXFile = CreateFile (IdxFlNam, GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ, NULL, CREATE_ALWAYS, 0, NULL);
if (hXFile == INVALID_HANDLE_VALUE)
ReportError (_T ("Failure to create index file."), 8, TRUE);
/* Step 2b: Get the first key and determine key size and start. */
KStart = (DWORD_PTR) pInScan;
/* Computed start of key field. */
while (*pInScan != ' ' && *pInScan != '\t') pInScan++;
/* Computed end of key field */
KSize = ((DWORD_PTR) pInScan - KStart) / TSIZE;
/* Computed key field size in characters. */
/* Step 2c. Step 3. Scan the complete file, writing keys
and record pointers to the key file. */
/* The eight bytes contain the Key Size/Key Start.
This is necessary so that we can re-use the index file. */
WriteFile (hXFile, &KSize, sizeof (DWORD), &nWrite, NULL);
WriteFile (hXFile, &KStart, sizeof (DWORD), &nWrite, NULL);
pInScan = /*(TCHAR _based (pInFile)*)*/0;
while ((DWORD_PTR) pInScan < FsIn) {
WriteFile (hXFile, pInScan + KStart, KSize * TSIZE, &nWrite, NULL);
WriteFile (hXFile, &pInScan, sizeof (LPTSTR), &nWrite, NULL);
while ((DWORD) (DWORD_PTR)pInScan < FsIn && ((*pInScan != CR)
|| (*(pInScan + 1) != LF))) {
pInScan++; /* Skip to end of line. */
}
pInScan += 2; /* Skip past CR, LF. */
}
CloseHandle (hXFile);
/* Size of an individual record. */
return KSize * TSIZE + sizeof (LPTSTR);
}
int KeyCompare (LPCTSTR pKey1, LPCTSTR pKey2)
/* Compare two records of generic characters.
The key position and length are global variables. */
{
DWORD i;
TCHAR t1, t2;
int Result = 0;
for (i = 0; i < KSize && Result == 0; i++) {
t1 = *pKey1;
t2 = *pKey2;
if (t1 < t2)
Result = -1;
if (t1 > t2)
Result = +1;
pKey1++;
pKey2++;
}
return Revrs ? -Result : Result;
}
TLS
TlsAlloc()
TlsFree()
TlsSetValue()
TlsGetValue()
참조 사이트: