Frage

Was ist ein "Handle", wenn die Ressourcen in Windows zu diskutieren? Wie funktionieren sie?

War es hilfreich?

Lösung

Es ist ein abstraktes Referenzwert auf eine Ressource, die oft Speicher oder eine geöffnete Datei oder ein Rohr.

Richtig , in Windows (und in der Regel in computing) ein Handgriff ist eine Abstraktion, die eine reale Speicheradresse von dem API Benutzer versteckt, so dass das System in das Programm physische Speicher transparent reorganisieren. einen Handgriff in einen Zeiger Auflösungs verriegelt den Speicher und den Griff Loslassen invalidiert den Zeiger. In diesem Fall betrachten Sie es als einen Index in eine Tabelle von Zeigern ... Sie den Index für die System-API-Aufrufe verwenden, und das System kann den Zeiger in der Tabelle nach Belieben ändern.

Alternativ kann ein echter Zeiger kann als Griff gegeben werden, wenn die API Schriftsteller beabsichtigt, dass der Benutzer der API von den Besonderheiten der isoliert werden, was die Adresse zurück Punkte; in diesem Fall muss es, dass in Betracht gezogen werden, was die Griffpunkte jederzeit (ab API-Version zu Version oder sogar von Aufruf der API aufrufen, die den Griff zurückzugibt) ändern kann - der Griff daher als einfach einen undurchsichtigen Wert behandelt werden soll sinnvoll nur auf die API.

soll ich das in jedem modernen Betriebssystem hinzufügen, auch die so genannten „echten Zeiger“ noch undurchsichtige Griffe in den virtuellen Speicherraum des Prozesses sind, die ohne die Wirksamkeit die Zeiger die O / S zu verwalten und neu anordnen Speicher ermöglicht im Prozess.

Andere Tipps

Ein HANDLE ist eine kontextspezifische eindeutige Kennung. Durch kontextspezifisch, meine ich, dass ein Handgriff von einem Kontext erhalten kann nicht unbedingt in jedem anderen aribtrary Kontext verwendet werden, die auch auf HANDLEs funktioniert.

Zum Beispiel gibt GetModuleHandle eine eindeutige Kennung zu einem aktuell geladenen Modul. Der zurückgegebene Handle kann in anderen Funktionen verwendet werden, die Modulgriffe akzeptieren. Es kann nicht auf Funktionen gegeben werden, die anderen Arten von Griffen erfordern. Zum Beispiel könnten Sie nicht einen Griff zurück von GetModuleHandle geben HeapDestroy und erwarten, dass es etwas Vernünftiges tun.

Die HANDLE selbst ist nur ein integraler Typ. In der Regel, aber nicht unbedingt, es ist ein Zeiger auf ein zugrunde liegendes Typ oder Speicherort. Zum Beispiel kann die HANDLE durch GetModuleHandle zurückgegeben ist tatsächlich ein Zeiger auf die Basisadresse des virtuellen Speichers des Moduls. Aber es gibt keine Regel, die besagt, dass Griffe Zeiger sein müssen. Ein Griff könnte auch nur eine einfache ganze Zahl sein (die gegebenenfalls durch eine Win32 API als ein Index in ein Array verwendet werden könnte).

HANDLEs sind absichtlich undurchsichtig Darstellungen, die Verkapselung und Abstraktion von internen Win32 Ressourcen zur Verfügung stellen. Auf diese Weise könnte der Win32-APIs möglicherweise den zugrunde liegenden Typen hinter einem Griff ändern, ohne dass es aufprall Code Benutzer in irgendeiner Weise (zumindest das ist die Idee).

Beachten Sie auch diese drei verschiedene internen Implementierungen eines Win32-API, die ich gerade aus, und geht davon aus, dass Widget ein struct ist.

Widget * GetWidget (std::string name)
{
    Widget *w;

    w = findWidget(name);

    return w;
}
void * GetWidget (std::string name)
{
    Widget *w;

    w = findWidget(name);

    return reinterpret_cast<void *>(w);
}
typedef void * HANDLE;

HANDLE GetWidget (std::string name)
{
    Widget *w;

    w = findWidget(name);

    return reinterpret_cast<HANDLE>(w);
}

Das erste Beispiel macht die internen Details über die API: es ermöglicht dem Benutzer-Code zu wissen, dass GetWidget einen Zeiger auf eine struct Widget zurückgibt. Dies hat ein paar Folgen:

  • der Benutzercode muss Zugriff auf die Header-Datei, die die Widget struct
  • definiert
  • könnte der Benutzercode möglicherweise ändern interne Teile des zurück Widget struct

Diese beiden Folgen unerwünscht sein kann.

Das zweite Beispiel verbirgt sich diese interne Detail aus dem Benutzer-Code, nur um void * zurück. Der Benutzercode benötigt keinen Zugriff auf den Header, der die Widget Struktur definiert.

Das dritte Beispiel ist genau das gleiche wie die zweiten, aber wir die void * stattdessen ein HANDLE einfach anrufen. Vielleicht schreckt dieser Benutzercode von dem Versuch, genau herauszufinden, was die void * Punkte zu.

Warum durch diese Mühe machen? Betrachten Sie dieses vierte Beispiel einer neueren Version des gleichen API:

typedef void * HANDLE;

HANDLE GetWidget (std::string name)
{
    NewImprovedWidget *w;

    w = findImprovedWidget(name);

    return reinterpret_cast<HANDLE>(w);
}

Beachten Sie, dass die Funktion der Schnittstelle zu dem dritten Beispiel oben identisch ist. Dies bedeutet, dass Code Benutzer weiterhin kann diese neue Version der API verwenden, ohne Änderungen, auch wenn die „hinter den Kulissen“ Implementierung geändert hat stattdessen die NewImprovedWidget Struktur zu verwenden.

Die Griffe in diesen Beispielen sind wirklich nur ein neuer, vermutlich freundlicher, Name für void *, das ist genau das, was ein HANDLE in dem Win32-API ist (schauen Sie bei MSDN ). Es stellt eine undurchsichtige Wand zwischen dem Benutzercode und der internen Darstellungen der Win32-Bibliothek, die Portabilität zwischen Windows-Versionen des Codes erhöht, die das Win32-API verwendet.

Ein Griff in der Win32-Programmierung ist ein Token, der eine Ressource darstellt, die von dem Windows-Kernel verwaltet wird. Ein Handgriff kann an ein Fenster sein, eine Datei, etc.

Die Griffe sind einfach eine Möglichkeit, eine partikuläre Ressource zu identifizieren, die Sie mit der Verwendung der Win32-APIs arbeiten möchten.

So zum Beispiel, wenn Sie ein Fenster erstellen, und zeigen Sie es auf dem Bildschirm Sie Folgendes tun können:

// Create the window
HWND hwnd = CreateWindow(...); 
if (!hwnd)
   return; // hwnd not created

// Show the window.
ShowWindow(hwnd, SW_SHOW);

Im obigen Beispiel bedeutet HWND „ein Handle zu einem Fenster“.

Wenn Sie eine objektorientierte Sprache verwendet werden Sie von einem Griff als eine Instanz einer Klasse ohne Methoden denken kann, der Zustand ist, ist nur modifizierbar durch andere Funktionen. In diesem Fall wird die Showwindow Funktion ändert den Zustand des Fenstergriffs.

Siehe Griffe und Datentypen für weitere Informationen .

Ein Handle ist ein eindeutiger Bezeichner für ein Objekt verwaltet die von Windows. Es ist wie ein Zeiger , sondern keinen Zeiger in dem Sinne, dass es nicht eine Adresse ist, die durch Benutzercode dereferenziert werden könnte Zugriff auf bestimmte Daten zu gewinnen. Stattdessen wird ein Griff ist auf eine Reihe von Funktionen übergeben werden, die Aktionen auf dem Objekt ausführen kann der Griff identifiziert.

Ein Griff ist wie ein Primärschlüsselwert eines Datensatzes in einer Datenbank.

Bearbeiten 1: gut, warum die downvote, ein Primärschlüssel eindeutig einen Datensatz der Datenbank, und ein Griff in dem Windows-System eindeutig identifizieren ein Fenster, eine geöffnete Datei, usw. identifiziert, Das ist, was ich sage

.

So auf der untersten Ebene ein Griff jeglicher Art ist ein Zeiger auf einen Zeiger oder

#define HANDLE void **

Nun, warum Sie wollen würde, es zu benutzen

Ermöglicht eine Einrichtung nehmen:

class Object{
   int Value;
}

class LargeObj{

   char * val;
   LargeObj()
   {
      val = malloc(2048 * 1000);
   }

}

void foo(Object bar){
    LargeObj lo = new LargeObj();
    bar.Value++;
}

void main()
{
   Object obj = new Object();
   obj.val = 1;
   foo(obj);
   printf("%d", obj.val);
}

Also, da obj Wert übergeben wurde (eine Kopie erstellen und geben, dass auf die Funktion) auf foo, die printf wird den ursprünglichen Wert von 1 drucken.

Wenn wir jetzt aktualisieren foo:

void foo(Object * bar)
{
    LargeObj lo = new LargeObj();
    bar->val++;
}

Es gibt eine Chance, dass der printf den aktualisierten Wert von 2. druckt Aber es gibt auch die Möglichkeit, dass foo irgendeine Form von Speicherbeschädigung oder Ausnahme verursachen werden.

Der Grund hierfür ist, während Sie jetzt einen Zeiger passieren obj an die Funktion sind Sie auch 2 Megabyte Speicher Zuweisung, könnte dies das Betriebssystem veranlassen, den Speicher um die Aktualisierung der Position von obj zu bewegen. Da Sie die Zeiger nach Wert übergeben haben, wenn obj bewegt wird dann das Betriebssystem der Zeiger aktualisiert, aber nicht die Kopie in der Funktion und möglicherweise Probleme verursachen.

Eine letzte Update auf foo aus:

void foo(Object **bar){
    LargeObj lo = LargeObj();
    Object * b = &bar;
    b->val++;
}

Damit wird der aktualisierte Wert immer drucken.

Sehen Sie, wenn der Compiler Speicher für Zeiger ordnet er sie als unbeweglich markiert, so dass jede Wieder Schlurfen von Speicher durch das große Objekt verursacht wird, um den Wert der Funktion übergeben zugeordnet wird an die richtige Adresse richten Sie den endgültigen Standort, um herauszufinden, im Speicher zu aktualisieren.

Jeder bestimmte Typ von Handles (hWnd, FILE, usw.) ist domänenspezifische und verweist auf eine bestimmte Art von Struktur gegen Speicherbeschädigung zu schützen.

Denken Sie an das Fenster in Windows als eine Struktur, die es beschreibt. Diese Struktur ist ein interner Bestandteil von Windows und Sie brauchen nicht die Details, es zu wissen. Stattdessen stellt Windows ein typedef für Zeiger für diese Struktur auf struct. Das ist der „Griff“, mit denen Sie halten auf dem Fenster.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top