Vollständige Version anzeigen : [C/C++] Virtual Memory - File Wrapper


Rushh0ur
21.12.2010, 20:42

Nun ja, zur Vorgeschichte, mein Prof hat mich vor ein paar Tagen gefragt ob es möglich wäre den Arbeitsspeicher irgendwie auf die Festplatte auszulagern, er möchte gern 16GB reservieren und benutzen, er habe aber nur 8 drin .....
Da ich darauf keine Antwort hatte hab ich mich ein wenig schlau gemacht und bin der MSDN und allgemein im Internet über ein paar interessante Funktionen gestolpert wodurch nun diese kleine Programm/Schnittstelle entstanden ist.

Die meisten Programmierer kennen die Funktionen malloc, realloc und free um mit dem Arbeitsspeicher zu arbeiten (später wurde new und delete eingeführt). Nun wäre es doch praktisch wenn man eine Datei auf der Festplatte über eine virtuelle Addresse direkt beschrieben könnte ohne irgendwelche Read und Write Funktionen aufzurufen und genau dies ermöglicht der folgende Code.

In der folgenden "Wrapper-Bibliothek" findet ihr die Funktionen f_malloc, f_realloc und f_free die eigentlich genau wie die alten Befehle arbeiten nur mit dem kleinen Unterschied das der zurück gegebene Zeiger und der damit verknüpfte Adressraum sich auf eine Datei beziehen.

Kurz: Ihr schreibt oder lest Daten vom Speicher welche *direkt* (cached) in die Datei geschrieben/ausgelesen werden.

fmalloc;h

/*************************************************************************** */
/* filename: fmalloc;cpp */
/* author: SubZeroX */
/* date: 23;12;2010 13:15 */
/* thx to: Gibbon for a few tips */
/*************************************************************************** */
#ifndef _FMALLOC_H_INCLUDE_
#define _FMALLOC_H_INCLUDE_

#include <windows;h>
#include <vector>
#include <tchar;h>

void *f_malloc (TCHAR *lpFileName, size_t size, DWORD dwCreationDisposition = CREATE_ALWAYS, DWORD flProtect = PAGE_READWRITE);
void *f_realloc (void *memblock, size_t size);
void f_free (void *memblock, bool cleanup = true);
size_t f_getsize (void *memblock);

#endif // _FMALLOC_H_INCLUDE_


fmalloc;cpp

/*************************************************************************** */
/* filename: fmalloc;cpp */
/* author: SubZeroX */
/* date: 23;12;2010 13:15 */
/* thx to: Gibbon for a few tips */
/*************************************************************************** */
#include "fmalloc;h"

#ifndef _WIN64
#define STRINGIFY(x) #x
#define TOSTRING(x) STRINGIFY(x)
#pragma message (__FILE__ "(" TOSTRING(__LINE__) ") : warning: It will be recommended to use this code only as Win64 build;")
#endif

typedef struct
{
TCHAR *sFileName;
VOID *ptr;
DWORD flProtect;
HANDLE hPageFile;
HANDLE hPage;
} FMemEntry;

/// *************************************************************************** **********
/// HeapList data manager
/// *************************************************************************** **********
static std::vector<FMemEntry> fHeapList;

/// *************************************************************************** **********
/// Replace all specific Charater in a String
/// param str: character array
/// param cold: the old character
/// param cnew: the new character
/// *************************************************************************** **********
static void str_replace(TCHAR *str, TCHAR *cold, TCHAR *cnew)
{
while (*str != 0)
{
if (*str == *cold)
*str = *cnew;
str++;
}
}

/// *************************************************************************** **********
/// Find a heap entry with the specific entry
/// param lpFileNamethe: filename of the heap entry
/// return: iterator to the object
/// *************************************************************************** **********
static std::vector<FMemEntry>::const_iterator HeapFindFile(TCHAR *lpFileName)
{
for (std::vector<FMemEntry>::const_iterator it = fHeapList;begin(); it < fHeapList;end(); ++it)
if (!_tcscmp(it->sFileName, lpFileName))
return it;

return fHeapList;end();
}

/// *************************************************************************** **********
/// Find a heap entry with the specific memblock
/// param memblock: memblock of the heap entry
/// return: iterator to the object
/// *************************************************************************** **********
static std::vector<FMemEntry>::const_iterator HeapFindMemory(void *memblock)
{
for (std::vector<FMemEntry>::const_iterator it = fHeapList;begin(); it < fHeapList;end(); ++it)
if (it->ptr == memblock)
return it;

return fHeapList;end();
}

/// *************************************************************************** **********
/// allocates virtuall memory with associated file
/// param lpFileName: name of the associated file
/// param size: the amount of bytes to associate from begining of the file
/// param dwCreationDisposition: CREATE_ALWAYS or OPEN_ALWAYS
/// param flProtect: see param flProtect of CreateFileMapping function
/// return: virtuall memory pointer
/// *************************************************************************** **********
void *f_malloc(TCHAR *lpFileName, size_t size, DWORD dwCreationDisposition, DWORD flProtect)
{
if (!lpFileName) return NULL;

FMemEntry fHeapListEntry;
bool bError;

// copy file name to HeapListEntry
fHeapListEntry;sFileName = _tcsdup(lpFileName);

{ // check if file name already exist
std::vector<FMemEntry>::const_iterator index = HeapFindFile(lpFileName);
if (index < fHeapList;end())
{
free(fHeapListEntry;sFileName);
return index->ptr;
}
}

// create or open a file
fHeapListEntry;hPageFile = CreateFile(lpFileName, GENERIC_READ | GENERIC_WRITE, 0, NULL, dwCreationDisposition,
FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_OVERLAPPED | FILE_FLAG_RANDOM_ACCESS, NULL);
if (fHeapListEntry;hPageFile)
{
// create a map of the file
TCHAR *lpName = _tcsdup(lpFileName);
#ifdef UNICODE
str_replace(lpName, L"\\", L"_");
#else
str_replace(lpName, "\\", "_");
#endif
#ifdef _WIN64
fHeapListEntry;hPage = CreateFileMapping(fHeapListEntry;hPageFile, NULL, flProtect,
(size >> 32), size & 0xFFFFFFFF, lpName);
#else
fHeapListEntry;hPage = CreateFileMapping(fHeapListEntry;hPageFile, NULL, flProtect,
0, size & 0xFFFFFFFF, lpName);
#endif

if (fHeapListEntry;hPage)
{
// obtain a pointer of the mapped file
fHeapListEntry;ptr = MapViewOfFile(fHeapListEntry;hPage, FILE_MAP_ALL_ACCESS, 0, 0, NULL);

if (fHeapListEntry;ptr)
{
// add entry to HeapList
fHeapListEntry;flProtect = flProtect;
fHeapList;push_back(fHeapListEntry);

bError = false;
}
else
bError = true;
}
else
bError = true;

free(lpName);
}
else
bError = true;

// check error state
if (bError)
{
CloseHandle(fHeapListEntry;hPage);
CloseHandle(fHeapListEntry;hPageFile);
free(fHeapListEntry;sFileName);
return NULL;
}

// return the memory pointer to the file
return fHeapListEntry;ptr;
}

/// *************************************************************************** **********
/// free the virtual memory with associated file
/// param memblock: memblock of the associated file
/// param cleanup: if true the specific file will be delete
/// *************************************************************************** **********
void f_free(void *memblock, bool cleanup)
{
if (!memblock) return;

std::vector<FMemEntry>::const_iterator index = HeapFindMemory(memblock);
if (index < fHeapList;end())
{
TCHAR* lpFileName = index->sFileName;
UnmapViewOfFile (index->ptr);
CloseHandle (index->hPage);
CloseHandle (index->hPageFile);
fHeapList;erase (index);
if (cleanup) DeleteFile(lpFileName);
free(lpFileName);
}
}

/// *************************************************************************** **********
/// reallocate virtual memory with associated file and resize
/// param memblock: memblock of the associated file
/// param size: new size
/// *************************************************************************** **********
void *f_realloc(void *memblock, size_t size)
{
if (!memblock) return NULL;

std::vector<FMemEntry>::const_iterator index = HeapFindMemory(memblock);
if (index < fHeapList;end())
{
TCHAR *lpFileName = _tcsdup(index->sFileName);
DWORD flProtect = index->flProtect;
f_free(memblock, false);

void *ptr = f_malloc(lpFileName, size, OPEN_ALWAYS, flProtect);
free(lpFileName);

return ptr;
}

return NULL;
}

/// *************************************************************************** **********
/// get size of virtual memory region
/// param memblock: memblock of the associated file
/// return: size of block
/// *************************************************************************** **********
size_t f_getsize(void *memblock)
{
if (!memblock) return 0;

std::vector<FMemEntry>::const_iterator index = HeapFindMemory(memblock);
if (index < fHeapList;end())
{
#ifdef _WIN64
DWORD dwHighSize;
DWORD dwLowSize = GetFileSize(index->hPageFile, &dwHighSize);
return dwLowSize | ((size_t)dwHighSize << 32);
#else
return GetFileSize(index->hPageFile, NULL);
#endif
}
else
return 0;
}


Beispiel:

// Datei auf der Festplatte öffnen/erstellen
char* str = (char*)f_malloc(L"D:\\test;txt", 256, OPEN_ALWAYS);

printf("Alter Text:\n");
printf("%s", str);
printf("Geben Sie einen neuen Text ein:\n");
scanf("%s", test);

// Datei schliessen ohne zu löschen (false)
f_free((void*)str, false);


//Edit:
Hab mal noch die Funktion f_getsize hinzugefügt, mit der man die Größe des Speicherblock auslesen kann.

Die drei Funktionen sollten eigentlich selbsterklährend sein, wenn nicht im Sourcecode sind noch ein paar Kommentare, ansonste hier einfach nochmal nachfragen.
Das man dadruch einfach mit Dateien arbeiten kann sollte auch klar sein oder auch damit benutzerdefniert den "Arbeitsspeicher" erweitern kann. (letzteres siehe Post 2 lieber VirtualAlloc benutzen)

Das ganze sollte am besten in 64Bit Anwendungen benutz werden, da da der Virtuele Addresraum größer ist (für kleine Dateien auch unter 32Bit nutzbahr).

Kritik und Verbesserungsvorschläge erwünscht.
Solltet ihr den Code in eurem Projekt verwenden dann nennt doch Bitte die Autoren in den Credits.

Mfg Rushh0ur

Hardware Preisvergleich | Amazon Blitzangebote!

Videos zum Thema
Video Loading...
N0S
21.12.2010, 21:32

Hast du VirtualAlloc ausprobiert? Diese Funktion kann auf einem 64Bit System theoretisch 2^64 Byte reservieren. Du kannst auf einem 32-Bit System sowieso nicht mehr als 2^32 ansprechen...

Paging/swapping ein Feature des Betriebssystems, also sollte man das Feature auch nutzen...


Rushh0ur
21.12.2010, 23:19

Jup kenne die Funktion. Das mit dem mehr "Arbeitsspeicher" wird etwas missverstanden. Da hast du natürlich recht, da sollte man VirtualAlloc benutzen.

Mir geht es eher darum um schnelle bzw einfacher auf Dateien zuzugreifen.

Mfg Rushh0ur


Gibbon
22.12.2010, 14:55

Hat es einen Grund, dass du über den std::vector per operator[] loopst, statt mit Iteratoren, die performanter sind? Würde dann beispielsweise so aussehen:

for (std::vector<FMemEntry>::const_iterator it = fHeapList;begin(); it != fHeapList;end(); ++it)
// hier erfolgt dann der Zugriff z. B. auf sFilename per (*it);sFilename oder einfacher it->sFilename


Alternativ kannst du natürlich noch statt std::vector<FMemEntry> ein typedef verwenden und dann darüber auf den const_iterator zugreifen:

typedef std::vector<FMemEntry> vec_t;

for (vec_t::const_iterator ....;)


Rushh0ur
23.12.2010, 13:31

Hat es einen Grund, dass du über den std::vector per operator[] loopst, statt mit Iteratoren, die performanter sind?

Nein einen besonderen Grunds gibts eigentlich nicht, vermutlich weil ich mich mit der Syntax der Iteratoren nicht befreunden kann und die von den Standartsarrays bevorzuge.

Aber es wird mal Zeit das neue auch zu akzeptieren und zu verwenden. Danke Dir, hab nun den Code dementsprechend geändert und nen kleinen "Bug" entfernt (== bei ner if-Abfrage).

Mfg Rushh0ur


failsafe
23.12.2010, 14:15

So richtig verstehe ich den Sinn auch nicht ganz. Das Betriebssystem hat ja, wie bereits ausgeführt, genau diese Funktionalität.

Wenn Du komfortable mit Dateien wie mit Arbeitsspeicher arbeiten willst, stellen Betriebssystem dir soetwas wie mmap() zur Verfügung: Du bekommst einen Pointer im Speicher, der Speicherbereich wird synchron zu einer gegebenen Datei gehalten. Das ganze ist so ausgefuchst, dass sich mehrere Prozesse dadurch einen Speicherbereich teilen können, wenn sie die gleiche Datei angeben.

Das ganze gibt es auch unter Windows, hatte ich auch einmal verwendet, aber wieder vergessen. Musst mal schauen, die Unix Funktion ist wiegesagt mmap()


Rushh0ur
23.12.2010, 14:48

Nun ja das Betriebsystem stellt diese Funktionalität zwar zur verfügung jedoch finde ich die Handhabung etwas komplitziert und der Code soll diese vereinfachen.

Kann zu Unix-Programierung nichts sagen da ich damit nicht arbeite, aber es scheint, dass es da auch nicht grad "einfach" ist und man sich durch diversen Befehlen durchkämpfen muss.

Mfg Rushh0ur


failsafe
23.12.2010, 15:27

Wenn etwas vom Betriebssystem vorgegeben ist, sollte man sich schon mal "durchkämpfen", da die Performance oft gar nicht anders zu erreichen ist. Gut, ich hab unter Windows schon manch schlechte Erfahrung gemacht (strtod etwa, in manchen Fällen ist die BSD Version tausend mal schneller als die von Windows).

So kompliziert ist es doch aber gar nicht, hier ist ein Beispiel aus dem MSDN:
Creating Named Shared Memory (Windows) (;msdn;microsoft~com/en-us/library/aa366551(v=vs;85);aspx)
Statt INVALID_HANDLE_VALUE kannst Du auch ein File-Handle angeben, auf dem Du arbeiten willst. Wie Du am Ende siehst, bekommst Du ein Pointer pBuf, den Du wie einen normalen Pointer verwenden kannst. Dies Beispiel zielt eher auf IPC ab, wenn man ein bisschen schaut, finden sich sicherlich noch mehr Beispiele für eine andere Verwendung.
Aber das ist doch im Prinzip genau das, was Du willst? Nur direkt vom Betriebssystem und tausendfach erprobt und bewährt :P


Rushh0ur
26.12.2010, 21:18

So kompliziert ist es doch aber gar nicht, hier ist ein Beispiel aus dem MSDN:
Creating Named Shared Memory (Windows) (;msdn;microsoft~com/en-us/library/aa366551(v=vs;85);aspx)
Statt INVALID_HANDLE_VALUE kannst Du auch ein File-Handle angeben, auf dem Du arbeiten willst. Wie Du am Ende siehst, bekommst Du ein Pointer pBuf, den Du wie einen normalen Pointer verwenden kannst. Dies Beispiel zielt eher auf IPC ab, wenn man ein bisschen schaut, finden sich sicherlich noch mehr Beispiele für eine andere Verwendung.
Aber das ist doch im Prinzip genau das, was Du willst? Nur direkt vom Betriebssystem und tausendfach erprobt und bewährt :P


Em mein Code implementiert den Code den du verlinkt hast und kümmert sich für die Verwaltung....

Du kannst das ganze mit ner String-Klasse vergleichen, die String Klasse kümmer sich um die verwaltung eines char/wchar_t-Arrays und mein Code kümmert sich um die Erstellung und die Friegabe der Handles die man dafür benötigt und bietet damit eine einfachere Handhabung. Aber wenn du das nicht brauchst dann kannst du es doch selbert so wie du es brauchst zussamenschrieben.
Ich, finde es zumindest praktisch und eventuelle ein paar andere Leute auch.

Ich hoffe der Zweck ist jetzt etwas näher gekommen.

Mfg Rushh0ur


failsafe
27.12.2010, 10:56

Em mein Code implementiert den Code den du verlinkt hast und kümmert sich für die Verwaltung....

Du kannst das ganze mit ner String-Klasse vergleichen, die String Klasse kümmer sich um die verwaltung eines char/wchar_t-Arrays und mein Code kümmert sich um die Erstellung und die Friegabe der Handles die man dafür benötigt und bietet damit eine einfachere Handhabung. Aber wenn du das nicht brauchst dann kannst du es doch selbert so wie du es brauchst zussamenschrieben.
Ich, finde es zumindest praktisch und eventuelle ein paar andere Leute auch.

Ich hoffe der Zweck ist jetzt etwas näher gekommen.

Mfg Rushh0ur

Haha, OK, hätte ich mal genauer nachschauen sollen. So ist mir jetzt wenigstens klar, was Du gemacht hast ;)


Ähnliche Themen zu [C/C++] Virtual Memory - File Wrapper
  • [CSS] Wrapper tut nicht das was er soll
    Hey Leute, ich habe ein Projekt für die Uni am laufen bzw. eine Website, die benotet wird. Das ganze soll in php ablaufen und ich bin momentan im klinsch mit dem Stylen der Seite mit CSS. Ich gebe euch mal den code der index;php <html> <?php ## Website programmiert in php ## Version 1 [...]

  • [Java] Wrapper Klasse
    Guten Abend Ich versuche gerade eine wrapper klasse zum Laufen zu bringen. Ich habe bereits alle anderen Klassen mit set und get methoden ausgestattet was auch super geklappt hat. Auch das erzeugen von Objekten war kein Problem. Nur die Wrapper Klasse macht mir zu schaffen. überall Fehler. pac [...]

  • [C/C++] cURL C++ Wrapper
    Heyho Hab für mein Projekt 'nen kleinen cURL Wrapper geschrieben. Ist nur ne vorläufige Version und falls ich das Teil noch überarbeite werde ich den Code im Thread mit Datum aktualisieren. Beispiel: #include <iostream> #include "curl;h" using namespace std; int main( void ) curl;h: #if [...]

  • gdb memory dump file
    Hi ich hab mal ne frage, und zwar beweg ich mich gerade auf einem Mac. Jetzt hab ich hier zwei Memory dump's nun möcht ich festellen welche Speicherzellen sich zwischen den beiden verändert hat. Natürlich geht das mit einem Simplen HexEditor, aber das ist recht umständlich gibt es da eine e [...]



raid-rush.ws | Imprint & Contact pr