Erhalten Sie Zugang zu diesem und mehr als 300000 Büchern ab EUR 5,99 monatlich.
Der Standard-Leitfaden – komplett aktualisiert auf Windows 10 und Windows Server 2016 Tauchen Sie in die Architektur und die inneren Mechanismen von Windows ein und lernen Sie die Kernkomponenten kennen, die hinter den Kulissen arbeiten. Dieser klassische Leitfaden wurde von einem Expertenteam für die inneren Mechanismen von Windows verfasst und vollständig auf Windows 10 und Windows Server 2016 aktualisiert. Dieses Buch gibt Entwicklern und IT-Profis entscheidende Insiderinformationen über die Funktionsweise von Windows. Durch praktische Experimente können Sie das interne Verhalten selbst erfahren und nützliche Kenntnisse zur Verbesserung des Designs Ihrer Anwendungen, zur Steigerung der Leistung, für Debugging und Support gewinnen. In diesem Buch lernen Sie: - Wie die Systemarchitektur von Windows aufgebaut ist und wie ihre wichtigsten Elemente aussehen, insbesondere Prozesse und Threads - Wie Prozesse Ressourcen und Threads verwalten - Wie Windows virtuellen und physischen Arbeitsspeicher verwaltet - Wie es in den Tiefen des E/A-Systems von Windows aussieht, wie Gerätetreiber funktionieren und wie sie mit dem Rest des Systems zusammenwirken - Wie das Sicherheitsmodell von Windows Zugriff, Überwachung und Autorisierung handhabt und welche neuen Mechanismen es in Windows 10 und Windows Server 2016 gibt
Sie lesen das E-Book in den Legimi-Apps auf:
Seitenzahl: 1373
Das E-Book (TTS) können Sie hören im Abo „Legimi Premium” in Legimi-Apps auf:
Zu diesem Buch – sowie zu vielen weiteren dpunkt.büchern – können Sie auch das entsprechende E-Book im PDF-Format herunterladen. Werden Sie dazu einfach Mitglied bei dpunkt.plus+:
www.dpunkt.plus
Für meine Familie: meine Frau Idit und unsere Kinder Danielle, Amit und Yoav. Danke für eure Geduld und eure Ermutigung während dieser anspruchsvollen Arbeit.
– Pavel Yosifovich
Für meine Eltern, die mich angeleitet und angeregt haben, meine Träume zu verfolgen, und für meine Familie, die während all dieser zahllosen Abende hinter mir gestanden hat.
– Alex Ionescu
Für unsere Eltern, die uns angeleitet und angeregt haben, unsere Träume zu verfolgen.
– Mark E. Russinovich und David A. Solomon
Band 1: Systemarchitektur, Prozesse, Threads, Speicherverwaltung, Sicherheit und mehr
Übersetzung der 7. englischsprachigen Auflage
Pavel Yosifovich
Alex Ionescu
Mark E. Russinovich
David A. Solomon
Pavel Yosifovich
Alex Ionescu
Mark E. Russinovich
David A. Solomon
Lektorat: Sandra Bollenbacher
Übersetzung: G&U Language & Publishing Services GmbH, www.gundu.com
Copy-Editing: Petra Heubach-Erdmann
Satz: G&U Language & Publishing Services GmbH, www.gundu.com
Umschlaggestaltung: Helmut Kraus, exclam.de
Druckerei: C.H.Beck
ISBN:
Print978-3-86490-538-4
PDF978-3-96088-338-8
ePub978-3-96088-339-5
mobi978-3-96088-340-1
Translation Copyright für die deutschsprachige Ausgabe © 2018 dpunkt.verlag GmbH Wieblinger Weg 17
69123 Heidelberg
Authorized translation from the English language edition, entitled WINDOWS INTERNALS, PART 1: SYSTEM ARCHITECTURE, PROCESSES, THREADS, MEMORY MANAGEMENT, AND MORE, 7th Edition by PAVEL YOSIFOVICH, ALEX IONESCU, MARK RUSSINOVICH, DAVID SOLOMON, published by Pearson Education, Inc, publishing as Microsoft Press, Copyright © 2017 by Pavel Yosifovich, Alex Ionescu, Mark E. Russinovich and David A. Solomon
All rights reserved. No part of this book may be reproduced or transmitted in any form or by any means, electronic or mechanical, including photocopying, recording or by any information storage retrieval system, without permission from Pearson Education, Inc.
German language edition published by dpunkt.verlag GmbH, Copyright © 2018
ISBN of the English language edition: 978-0-7356-8418-8
Die vorliegende Publikation ist urheberrechtlich geschützt. Alle Rechte vorbehalten. Die Verwendung der Texte und Abbildungen, auch auszugsweise, ist ohne die schriftliche Zustimmung des Verlags urheberrechtswidrig und daher strafbar. Dies gilt insbesondere für die Vervielfältigung, Übersetzung oder die Verwendung in elektronischen Systemen.
Es wird darauf hingewiesen, dass die im Buch verwendeten Soft- und Hardware-Bezeichnungen sowie Markennamen und Produktbezeichnungen der jeweiligen Firmen im Allgemeinen warenzeichen-, marken- oder patentrechtlichem Schutz unterliegen.
Alle Angaben und Programme in diesem Buch wurden mit größter Sorgfalt kontrolliert. Weder Autor noch Verlag können jedoch für Schäden haftbar gemacht werden, die in Zusammenhang mit der Verwendung dieses Buchs stehen.
5 4 3 2 1 0
Einleitung
Kapitel 1
Begriffe und Werkzeuge
Versionen des Betriebssystems Windows
Windows 10 und zukünftige Windows-Versionen
Windows 10 und OneCore
Grundprinzipien und -begriffe
Die Windows-API
Dienste, Funktionen und Routinen
Prozesse
Threads
Jobs
Virtueller Arbeitsspeicher
Kernel- und Benutzermodus
Hypervisor
Firmware
Terminaldienste und mehrere Sitzungen
Objekte und Handles
Sicherheit
Die Registrierung
Unicode
Die internen Mechanismen von Windows untersuchen
Leistungsüberwachung und Ressourcenmonitor
Kernel-Debugging
Windows Software Development Kit
Windows Driver Kit
Sysinternals-Werkzeuge
Zusammenfassung
Kapitel 2
Systemarchitektur
Anforderungen und Designziele
Das Modell des Betriebssystems
Die Architektur im Überblick
Portierbarkeit
Symmetrisches Multiprocessing
Skalierbarkeit
Unterschiede zwischen den Client- und Serverversionen
Testbuild
Die virtualisierungsgestützte Sicherheitsarchitektur im Überblick
Hauptsystemkomponenten
Umgebungsteilsysteme und Teilsystem-DLLs
Weitere Teilsysteme
Exekutive
Der Kernel
Die Hardwareabstraktionsschicht
Gerätetreiber
Systemprozesse
Zusammenfassung
Kapitel 3
Prozesse und Jobs
Prozesse erstellen
Argumente der CreateProcess*-Funktionen
Moderne Windows-Prozesse erstellen
Andere Arten von Prozessen erstellen
Interne Mechanismen von Prozessen
Geschützte Prozesse
Protected Process Light (PPL)
Unterstützung für Drittanbieter-PPLs
Minimale und Pico-Prozesse
Minimale Prozesse
Pico-Prozesse
Trustlets (sichere Prozesse)
Der Aufbau von Trustlets
Richtlinien-Metadaten für Trustlets
Attribute von Trustlets
Integrierte System-Trustlets
Trustlet-Identität
IUM-Dienste
Für Trustlets zugängliche Systemaufrufe
Der Ablauf von CreateProcess
Phase 1: Parameter und Flags konvertieren und validieren
Phase 2: Das auszuführende Abbild öffnen
Phase 3: Das Windows-Exekutivprozessobjekt erstellen
Phase 4: Den ursprünglichen Thread mit seinem Stack und Kontext erstellen
Phase 5: Spezifische Prozessinitialisierung für das Windows-Teilsystem durchführen
Phase 6: Ausführung des ursprünglichen Threads starten
Phase 7: Prozessinitialisierung im Kontext des neuen Prozesses durchführen
Einen Prozess beenden
Der Abbildlader
Frühe Prozessinitialisierung
DLL-Namensauflösung und -Umleitung
Die Datenbank der geladenen Module
Importanalyse
Prozessinitialisierung nach dem Import
SwitchBack
API-Sets
Jobs
Grenzwerte für Jobs
Umgang mit Jobs
Verschachtelte Jobs
Windows-Container (Serversilos)
Zusammenfassung
Kapitel 4
Threads
Threads erstellen
Interne Strukturen von Threads
Datenstrukturen
Geburt eines Threads
Die Threadaktivität untersuchen
Einschränkungen für Threads in geschützten Prozessen
Threadplanung
Überblick über die Threadplanung in Windows
Prioritätsstufen
Threadstatus
Die Dispatcherdatenbank
Das Quantum
Prioritätserhöhung
Kontextwechsel
Mögliche Fälle bei der Threadplanung
Leerlaufthreads
Anhalten von Threads
Einfrieren und Tiefgefrieren
Threadauswahl
Mehrprozessorsysteme
Threadauswahl auf Mehrprozessorsystemen
Prozessorauswahl
Heterogene Threadplanung (big.LITTLE)
Gruppengestützte Threadplanung
Dynamische gleichmäßige Planung (DFSS)
Grenzwerte für die CPU-Rate
Dynamisches Hinzufügen und Ersetzen von Prozessoren
Arbeitsfactories (Threadpools)
Erstellen von Arbeitsfactories
Zusammenfassung
Kapitel 5
Speicherverwaltung
Einführung in den Speicher-Manager
Komponenten des Speicher-Managers
Große und kleine Seiten
Die Speichernutzung untersuchen
Interne Synchronisierung
Vom Speicher-Manager bereitgestellte Dienste
Seitenstatus und Speicherzuweisungen
Gesamter zugesicherter Speicher und Zusicherungsgrenzwert
Seiten im Arbeitsspeicher festhalten
Granularität der Zuweisung
Gemeinsam genutzter Arbeitsspeicher und zugeordnete Dateien
Speicherschutz
Datenausführungsverhinderung
Kopieren beim Schreiben
AWE (Address Windowing Extensions)
Kernelmodusheaps (Systemspeicherpools)
Poolgrößen
Die Poolnutzung überwachen
Look-Aside-Listen
Der Heap-Manager
Prozessheaps
Arten von Heaps
NT-Heaps
Heapsynchronisierung
Der Low-Fragmentation-Heap
Segmentheaps
Sicherheitseinrichtungen von Heaps
Debugging einrichten für Heaps
Der Seitenheap
Der fehlertolerante Heap
Layouts für virtuelle Adressräume
x86-Adressraumlayouts
Das Layout des x86-Systemadressraums
x86-Sitzungsraum
System-Seitentabelleneinträge
ARM-Adressraumlayout
64-Bit-Adressraumlayout
Einschränkungen bei der virtuellen Adressierung auf x64-Systemen
Dynamische Verwaltung des virtuellen Systemadressraums
Kontingente für den virtuellen Systemadressraum
Layout des Benutzeradressraums
Adressübersetzung
Übersetzung virtueller Adressen auf x86-Systemen
Der Look-Aside-Übersetzungspuffer für die Übersetzung
Übersetzung virtueller Adressen auf x64-Systemen
Übersetzung virtueller Adressen auf ARM-Systemen
Seitenfehler
Ungültige PTEs
Prototyp-PTEs
Einlagerungs-E/A
Seitenfehlerkollisionen
Seitencluster
Auslagerungsdateien
Gesamter zugesicherter Speicher und systemweiter Zusicherungsgrenzwert
Der Zusammenhang zwischen dem gesamten zugesicherten Speicher und der Größe der Auslagerungsdatei
Stacks
Benutzerstacks
Kernelstacks
Der DPC-Stack
VADs
Prozess-VADs
Umlauf-VADs
NUMA
Abschnittsobjekte
Arbeitssätze
Auslagerung bei Bedarf
Der logische Prefetcher und ReadyBoot
Platzierungsrichtlinien
Verwaltung von Arbeitssätzen
Der Balance-Set-Manager und der Swapper
Systemarbeitssätze
Speicherbenachrichtigungsereignisse
Die PFN-Datenbank
Seitenlistendynamik
Seitenpriorität
Die Schreibthreads für geänderte und für zugeordnete Seiten
PFN-Datenstrukturen
Reservierungen in der Auslagerungsdatei
Grenzwerte für den physischen Speicher
Speichergrenzwerte für Windows-Clienteditionen
Speicherkomprimierung
Ablauf der Komprimierung
Komprimierungsarchitektur
Speicherpartitionen
Speicherzusammenführung
Die Suchphase
Die Klassifizierungsphase
Die Zusammenführungsphase
Vom privaten zum gemeinsamen PTE
Freigabe von zusammengeführten Seiten
Speicherenklaven
Programmierschnittstellen
Initialisierung von Speicherenklaven
Aufbau von Enklaven
Daten in eine Enklave laden
Eine Enklave initialisieren
Vorausschauende Speicherverwaltung (SuperFetch)
Komponenten
Ablaufverfolgung und Protokollierung
Szenarien
Seitenpriorität und Rebalancing
Leistungsstabilisierung
ReadyBoost
ReadyDrive
Prozessreflexion
Zusammenfassung
Kapitel 6
Das E/A-System
Komponenten des E/A-Systems
Der E/A-Manager
Typische E/A-Verarbeitung
IRQ-Ebenen und verzögerte Prozeduraufrufe
IRQ-Ebenen
Verzögerte Prozeduraufrufe
Gerätetreiber
Arten von Gerätetreibern
Aufbau eines Treibers
Treiber- und Geräteobjekte
Geräte öffnen
E/A-Verarbeitung
Verschiedene Arten der E/A
E/A-Anforderungspakete
E/A-Anforderungen an einen einschichtigen Hardwaretreiber
E/A-Anforderungen an geschichtete Treiber
Threadagnostische E/A
Abbrechen der E/A
E/A-Vervollständigungsports
E/A-Priorisierung
Containerbenachrichtigungen
Treiberüberprüfung
E/A-Überprüfungsoptionen
Speicherüberprüfungsoptionen
Der PnP-Manager
Der Grad der Unterstützung für Plug & Play
Geräteauflistung
Gerätestacks
Treiberunterstützung für Plug & Play
Installation von Plug-&-Play-Treibern
Laden und Installieren von Treibern
Treiber laden
Treiberinstallation
Windows Driver Foundation
Kernel-Mode Driver Framework
Das E/A-Modell von KMDF
User-Mode Driver Framework
Energieverwaltung
Verbundener und moderner Standbymodus
Funktionsweise der Energieverwaltung
Energieverwaltung durch die Treiber
Steuerung der Geräteenergiezustände durch den Treiber und die Anwendung
Das Framework für die Energieverwaltung
Energieverfügbarkeitsanforderungen
Zusammenfassung
Kapitel 7
Sicherheit
Sicherheitseinstufungen
Trusted Computer System Evaluation Criteria
Common Criteria
Systemkomponenten für die Sicherheit
Virtualisierungsgestützte Sicherheit
Credential Guard
Device Guard
Objekte schützen
Zugriffsprüfungen
Sicherheitskennungen
Virtuelle Dienstkonten
Sicherheitsdeskriptoren und Zugriffssteuerung
Dynamische Zugriffssteuerung
Die AuthZ-API
Bedingte Zugriffssteuerungseinträge
Privilegien und Kontorechte
Kontorechte
Privilegien
Superprivilegien
Zugriffstokens von Prozessen und Threads
Sicherheitsüberwachung
Überwachung des Objektzugriffs
Globale Überwachungsrichtlinie
Erweiterte Überwachungsrichtlinienkonfiguration
Anwendungscontainer
UWP-Apps im Überblick
Anwendungscontainer
Anmeldung
Initialisierung durch Winlogon
Die einzelnen Schritte der Benutzeranmeldung
Sichere Authentifizierung
Das Windows-Biometrieframework
Windows Hello
Benutzerkontensteuerung und Virtualisierung
Virtualisierung des Dateisystems und der Registrierung
Rechteerhöhung
Schutz gegen Exploits
Abwehrmaßnahmen auf Prozessebene
Control Flow Integrity
Zusicherungen
Anwendungsidentifizierung
AppLocker
Richtlinien für Softwareeinschränkung
Kernelpatchschutz
PatchGuard
HyperGuard
Zusammenfassung
Index
Dieses Buch ist für Computerexperten (Entwickler, Sicherheitsforscher und Systemadministratoren) gedacht, die die Funktionsweise der Kernkomponenten von Microsoft Windows 10 und Windows Server 2016 kennenlernen möchten. Mit diesen Kenntnissen können Entwickler beim Schreiben von Anwendungen für die Windows-Plattform die Gründe für bestimmte Designentscheidungen besser verstehen. Sie helfen ihnen auch beim Debugging komplizierter Probleme. Auch Systemadministratoren profitieren von diesen Informationen, da das Wissen, wie das System in seinem Inneren »tickt«, sein Verhalten verständlicher macht und die Störungssuche erleichtert. Sicherheitsforscher erfahren hier, welche Fehlverhalten Softwareanwendungen und das Betriebssystem an den Tag legen können, wie sie missbraucht werden können und welche Schutzmaßnahmen und Sicherheitsfunktionen moderne Windows-Versionen dagegen bieten. Nach der Lektüre dieses Buches haben Sie ein besseres Verständnis darüber, wie Windows funktioniert und welche Gründe hinter seinem Verhalten stehen.
Dies ist die siebente Ausgabe eines Buches, das ursprünglich Inside Windows NT hieß (Microsoft Press, 1992) und noch vor der Erstveröffentlichung von Windows NT 3.1 von Helen Custer geschrieben wurde. Es war das erste Buch, das es je über Windows NT gab, und es bot wichtige Einsichten in die Architektur und das Design des Systems. Inside Windows NT, Second Edition (Microsoft Press, 1998) wurde von David Solomon geschrieben. Es deckte auch Windows NT 4.0 ab und ging weit tiefer in die technischen Details.
Inside Windows 2000, Third Edition (Microsoft Press, 2000) wurde von David Solomon und Mark Russinovich geschrieben. Hier kamen viele neue Themen wie Starten und Herunterfahren, interne Mechanismen von Diensten und der Registrierung, Dateisystemtreiber und Netzwerkanbindung hinzu. Auch die Änderungen am Kernel in Windows 2000 wurden erläutert, darunter das Windows Driver Model (WDM), Plug & Play, Energieverwaltung, Windows-Verwaltungsinstrumentation (Windows Management Instrumentation, WMI), Verschlüsselung, Jobobjekte und Terminaldienste. Windows Internals, Fourth Edition (Microsoft Press, 2004) war die neue Ausgabe für Windows XP und Windows Server 2003 mit zusätzlichen Inhalten, um IT-Fachleuten zu helfen, ihre Kenntnisse über die internen Mechanismen von Windows praktisch anzuwenden, z. B. durch die Werkzeuge von Sysinternals und die Analyse von Absturzabbildern.
Mit Windows Internals, Fifth Edition (Microsoft Press, 2009) wurde das Buch auf Windows Vista und Windows Server 2008 aktualisiert. Da Mark Russinovich eine Vollzeitstelle bei Microsoft annahm (wo er jetzt als CTO für Azure arbeitet), kam der neue Co-Autor Alex Ionescu hinzu. Zu den neuen Inhalten gehörten der Abbildlader, Einrichtungen für das Debugging im Benutzermodus, ALPC (Advanced Local Procedure Call) und Hyper-V. Die nächste Ausgabe, Windows Internals, Sixth Edition (Microsoft Press, 2012) war komplett aktualisiert, um viele Änderungen am Kernel in Windows 7 und Windows Server 2008 R2 abzudecken. Außerdem kamen viele neue praktische Experimente hinzu, um die Änderungen an den Werkzeugen deutlich zu machen.
Seit der letzten Aktualisierung dieses Buches hat Windows mehrere neue Releases durchlaufen und ist jetzt bei Windows 10 und Windows Server 2016 angekommen. Dabei ist Windows 10 jetzt praktisch der neue Name für Windows. Seit der Produktionsfreigabe hat es wiederum mehrere Releases gegeben. Bezeichnet werden sie jeweils mit einer vierstelligen Zahl, die sich aus dem Jahr und dem Monat der Veröffentlichung zusammensetzt, also z. B. Windows 10 Version 1703 für die Version vom März 2017. Zum Zeitpunkt der Abfassung dieses Buches hat Windows also seit Windows 7 mindestens sechs Versionen durchlaufen.
Beginnend mit Windows 8 hat Microsoft mit einer Zusammenführung seiner Betriebssysteme begonnen, was für die Entwicklung und für das Windows-Konstruktionsteam von Vorteil ist. Windows 8 und Windows Phone 8 verwendeten bereits einen gemeinsamen Kernel, und mit Windows 8.1 und Windows Phone 8.1 kam auch eine Vereinheitlichung bei modernen Apps hinzu. Mit Windows 10 war die Zusammenführung abgeschlossen: Dieses Betriebssystem läuft auf Desktops, Laptops, Servern, der Xbox One, Smartphones (Windows Mobile 10), der Holo-Lens und verschiedenen IoT-Geräten (Internet of Things).
Angesichts dieser großen Vereinheitlichung war die Zeit reif für eine neue Ausgabe dieses Buches, um die Änderungen von fast einem halben Jahrzehnt aufzuarbeiten, die zu einer stabileren Kernelarchitektur geführt haben. Daher deckt dieses Buch verschiedene Aspekte des Betriebssystems von Windows 8 bis Windows 10 Version 1703 ab. Des Weiteren heißen wir Pavel Yosifovich als neuen Co-Autor willkommen.
Auch ohne Zugriff auf den Windows-Quellcode können Sie mithilfe des Kerneldebuggers, der Sysinternals-Tools und der eigens für dieses Buch entwickelten Werkzeuge viel über die internen Mechanismen von Windows herausfinden. Immer wenn ein Aspekt des internen Verhaltens von Windows mit einem der Tools sichtbar gemacht oder veranschaulicht werden kann, erfahren Sie in den mit »Experiment« betitelten Abschnitten, wie Sie dieses Tool selbst ausprobieren können. Diese Abschnitte sind über das ganze Buch verteilt, und wir raten Ihnen dazu, diese Experimente bei der Lektüre auszuführen. Es ist viel eindrucksvoller, die sichtbaren Auswirkungen der internen Mechanismen von Windows zu beobachten, als nur darüber zu lesen.
Windows ist ein umfangreiches und vielschichtiges Betriebssystem. In diesem Buch können wir nicht sämtliche internen Mechanismen von Windows abdecken, sondern konzentrieren uns auf die grundlegenden Systemkomponenten. Beispielsweise werden COM+, die verteilte objektorientierte Programmierinfrastruktur von Windows, und Microsoft .NET Framework, die Grundlage für Anwendungen mit verwaltetem Code, in diesem Buch nicht behandelt. Da es ein Buch über die »Interna« von Windows ist und kein Leitfaden für die Benutzung, die Programmierung oder die Systemadministration, erfahren Sie hier auch nicht, wie Sie Windows verwenden, programmieren oder konfigurieren.
Dieses Buch beschreibt nicht dokumentierte Aspekte der internen Architektur und Funktionsweise von Windows (wie interne Kernelstrukturen und -funktionen), die sich zwischen den einzelnen Releases ändern können.
Das soll nicht heißen, dass sie sich zwangsläufig ändern, sondern nur, dass Sie sich nicht auf ihre Unveränderbarkeit verlassen können. Software, die sich auf solche nicht dokumentierten Schnittstellen oder auf Insiderkenntnisse über das Betriebssystem verlässt, kann in zukünftigen Releases von Windows unter Umständen nicht mehr funktionieren. Software, die im Kernelmodus läuft (z. B. Gerätetreiber) und diese nicht dokumentierten Schnittstellen nutzt, kann bei der Ausführung in einer neueren Windows-Version sogar einen Systemabsturz und damit möglicherweise einen Datenverlust für den Benutzer hervorrufen.
Kurz: Bei der Entwicklung von Software für Endbenutzersysteme und allgemein für jegliche Zwecke außer Forschung und Dokumentation sollten Sie niemals auf die in diesem Buch erwähnten internen Windows-Einrichtungen, Registrierungsschlüssel, Verhaltensweisen, APIs oder sonstigen nicht dokumentierten Elemente zurückgreifen. Suchen Sie immer erst auf MSDN (Microsoft Software Developer Network) nach einer offiziellen Dokumentation.
In diesem Buch wird vorausgesetzt, dass die Leser mit Windows auf dem Niveau von »Power-Usern« vertraut sind und Grundkenntnisse über Betriebssystem- und Hardwareelemente wie CPU-Register, Arbeitsspeicher, Prozesse und Threads mitbringen. In einigen Abschnitten sind auch Grundkenntnisse über Funktionen, Zeiger und ähnliche Konstrukte der Programmiersprache C von Nutzen.
Ebenso wie die sechste Ausgabe ist auch diese in zwei Bände aufgeteilt, von denen Sie den ersten in Händen halten.
Kapitel 1
, »Begriffe und Werkzeuge«, gibt eine allgemeine Einführung in die Grundbegriffe von Windows und in die wichtigsten Werkzeuge, die wir in diesem Buch einsetzen werden. Es ist sehr wichtig, dieses Kapitel als erstes zu lesen, da es die Hintergrundinformationen für das Verständnis des Restes gibt.
Kapitel 2
, »Systemarchitektur«, zeigt die Architektur und die Hauptkomponenten auf, aus denen Windows besteht, und erläutert sie. Mehrere dieser Komponenten werden in den folgenden Kapiteln noch ausführlicher beschrieben.
Kapitel 3
, »Prozesse und Jobs«, erklärt, wie Prozesse in Windows implementiert sind, und zeigt die verschiedenen Vorgehensweisen zu ihrer Bearbeitung auf. Des Weiteren werden Jobs beschrieben, die eine Möglichkeit bieten, um eine Gruppe von Prozessen zu steuern und die Containerunterstützung von Windows zu aktivieren.
Kapitel 4
, »Threads«, beschreibt ausführlich, wie Threads verwaltet, geplant und auf sonstige Weise in Windows bearbeitet werden.
Kapitel 5
, »Speicherverwaltung«, zeigt, wie der Speicher-Manager physischen und virtuellen Arbeitsspeicher verwendet, und erklärt die verschiedenen Möglichkeiten, mit denen Prozesse und Treiber den Arbeitsspeicher bearbeiten und nutzen können.
Kapitel 6
, »Das E/A-System«, beschreibt, wie das E/A-System von Windows funktioniert und wie es mit den Gerätetreibern zusammenwirkt, um die Mechanismen für E/A-Peripheriegeräte bereitzustellen.
Kapitel 7
, »Sicherheit«, beschreibt ausführlich die verschiedenen Sicherheitsmechanismen von Windows einschließlich systemeigener Schutzmaßnahmen gegen Exploits.
In diesem Buch gelten die folgenden Schreibweisen:
Fettschrift
wird für Text verwendet, den Sie in einer Schnittstelle eingeben müssen.
Kursivschrift
kennzeichnet neue Begriffe sowie die Bezeichnungen von GUI-Elementen, Dateinamen und Webadressen.
Codeelemente stehen in
nichtproportionaler Schrift
.
Bei Tastaturkürzeln steht ein Pluszeichen zwischen den Bezeichnungen der einzelnen Tasten. Beispielsweise bedeutet + + , dass Sie gleichzeitig die Tasten , und drücken müssen.
Damit Sie aus diesem Buch noch größeren Nutzen ziehen können, haben wir Begleitmaterial zusammengestellt, das Sie von der folgenden Seite herunterladen können:
https://dpunkt.de/windowsinternals1
Den Quellcode der Tools, die wir eigens für dieses Buch geschrieben haben, finden Sie auf https://github.com/zodiacon/windowsinternals.
Als Erstes möchten wir Pavel Yosifovich dafür danken, dass er sich uns für dieses Projekt angeschlossen hat. Seine Beteiligung war für die Veröffentlichung entscheidend. Die vielen Nächte, die er damit zugebracht hat, Einzelheiten von Windows zu studieren und über Änderungen während der Zeit von sechs Releases zu schreiben, haben dieses Buch erst möglich gemacht.
Ohne die Rückmeldungen und die Unterstützung von wichtigen Mitgliedern des Windows-Entwicklungsteams und anderer Fachleute von Microsoft wäre dieses Buch auch technisch nicht so tief schürfend und nicht so präzise geworden, wie es ist. Daher möchten wir den folgenden Personen danken, die es auf technische Korrektheit durchgesehen, Informationen gegeben oder die Autoren auf andere Weise unterstützt haben: Akila Srinivasan, Alessandro Pilotti, Andrea Allievi, Andy Luhrs, Arun Kishan, Ben Hillis, Bill Messmer, Chris Kleynhans, Deepu Thomas, Eugene Bak, Jason Shirk, Jeremiah Cox, Joe Bialek, John Lambert, John Lento, Jon Berry, Kai Hsu, Ken Johnson, Landy Wang, Logan Gabriel, Luke Kim, Matt Miller, Matthew Woolman, Mehmet Iyigun, Michelle Bergeron, Minsang Kim, Mohamed Mansour, Nate Warfield, Neeraj Singh, Nick Judge, Pavel Lebedynskiy, Rich Turner, Saruhan Karademir, Simon Pope, Stephen Finnigan und Stephen Hufnagel.
Wir möchten auch Ilfak Guilfanov von Hex-Rays (http://www.hex-rays.com) für die IDA Pro Advanced- und Hey-Rays-Lizenzen danken, die er Alex Ionescu vor mehr als einem Jahrzehnt zur Verfügung gestellt hat, um das Reverse-Engineering des Windows-Kernels zu beschleunigen, und für die fortlaufende Unterstützung und Entwicklung der Decompilerfeatures, die es überhaupt erst möglich gemacht haben, ein solches Buch ohne Zugriff auf den Quellcode zu schreiben.
Zu guter Letzt möchten die Autoren den großartigen Mitarbeitern bei Microsoft Press denken, die dieses Buch verwirklicht haben. Devon Musgrave hat zum letzten Mal als unser Akquiseleiter gearbeitet, während Kate Shoup den Titel als Projektleiterin beaufsichtigt hat. Auch Shawn Morningstar, Kelly Talbot und Corina Lebegioara haben zu der Qualität dieses Buches beigetragen.
Wir haben uns gewissenhaft darum bemüht, dieses Buch und das Begleitmaterial so korrekt wie möglich zu gestalten. Jegliche Fehler in der englischen Originalausgabe, die seit der Veröffentlichung des Buches gemeldet wurden, sind auf der Website von Microsoft Press unter folgender Adresse aufgeführt:
https://aka.ms/winint7ed/errata
Mit Anmerkungen, Fragen oder Verbesserungsvorschlägen zu diesem Buch können Sie sich aber auch an den deutschen dpunkt.verlag wenden:
Bitte beachten Sie, dass über unsere E-Mail-Adressen kein Support für Software und Hardware angeboten wird.
Für Supportinformationen bezüglich der Soft- und Hardwareprodukte besuchen Sie die Microsoft-Website http://support.microsoft.com.
Bei Microsoft Press steht Ihre Zufriedenheit an oberster Stelle. Daher ist Ihr Feedback für uns sehr wichtig. Lassen Sie uns auf dieser englischsprachigen Website wissen, wie Sie dieses Buch finden:
https://aka.ms/tellpress
Wir wissen, dass Sie viel zu tun haben. Darum finden Sie auf der Webseite nur wenige Fragen. Ihre Antworten gehen direkt an das Team von Microsoft Press. (Es werden keine persönlichen Informationen abgefragt.) Im Voraus vielen Dank für Ihre Unterstützung.
Über Ihr Feedback per E-Mail freut sich außerdem der dpunkt.verlag über:
Falls Sie News, Updates usw. zu Microsoft Press-Büchern erhalten möchten, können Sie uns auf Twitter folgen:
http://twitter.com/MicrosoftPress (Englisch)
https://twitter.com/dpunkt_verlag (Deutsch)
In diesem Kapitel führen wir Kernbegriffe des Betriebssystems Microsoft Windows ein, die wir in dem gesamten Buch verwenden werden, z. B. Windows-API, Prozesse, Threads, virtueller Speicher, Kernel- und Benutzermodus, Objekte, Handles, Sicherheit und Registrierung. Außerdem stellen wir die Werkzeuge vor, mit denen Sie die inneren Mechanismen von Windows erkunden können, darunter den Kernel-Debugger, die Leistungsüberwachung und die wichtigsten Werkzeuge aus Windows Sysinternals (http://www.microsoft.com/technet/sysinternals). Des Weiteren erklären wir, wie Sie das Windows Driver Kit (WDK) und das Windows Software Developer Kit (SDK) verwenden können, um mehr über Windows-Interna zu erfahren.
In dem Rest dieses Buches wird vorausgesetzt, dass Sie die in diesem Kapitel eingeführten Begriffe kennen.
In diesem Buch geht es um die neueste Version der Client- und Serverbetriebssysteme von Microsoft, nämlich Windows 10 (eine 32-Bit-Version für x86 und ARM sowie eine 64-Bit-Version für x64) und Windows Server 2016 (wovon es nur eine 64-Bit-Version gibt). Sofern nicht ausdrücklich anders angegeben, bezieht sich der Text auf alle diese Versionen. Als Hintergrundinformation finden Sie in Tabelle 1–1 die Produktnamen, internen Versionsnummern und Veröffentlichungsdaten der bisherigen Windows-Versionen.
Produktname
Interne Versionsnummer
Veröffentlichungsdatum
Windows NT 3.1
3.1
Juli 1993
Windows NT 3.5
3.5
September 1994
Windows NT 3.51
3.51
Mai 1995
Windows NT 4.0
4.0
Juli 1996
Windows 2000
5.0
Dezember 1999
Windows XP
5.1
August 2001
Windows Server 2003
5.2
März 2003
Windows Server 2003 R2
5.2
Dezember 2005
Windows Vista
6.0
Januar 2007
Windows Server 2008
6.0 (Service Pack 1)
März 2008
Windows 7
6.1
Oktober 2009
Windows Server 2008 R2
6.1
Oktober 2009
Windows 8
6.2
Oktober 2012
Windows Server 2012
6.2
Oktober 2012
Windows 8.1
6.3
Oktober 2013
Windows Server 2012 R2
6.3
Oktober 2013
Windows 10
10.0 (Build 10240)
Juli 2015
Windows 10 Version 1511
10.0 (Build 10586)
November 2015
Windows 10 Version 1607 (Anniversary Update)
10.0 (Build 14393)
Juli 2016
Windows Server 2016
10.0 (Build 14393)
Oktober 2016
Tabelle 1–1Windows-Betriebssysteme
Beginnend mit Windows 7 scheint bei der Vergabe der Versionsnummern von einem wohldefinierten Muster abgewichen worden zu sein. Die Versionsnummer dieses Betriebssystems lautete nicht 7, sondern 6.1. Als mit Windows Vista die Versionsnummer auf 6.0 erhöht wurde, konnten manche Anwendungen das richtige Betriebssystem nicht erkennen. Das lag daran, dass die Entwickler aufgrund der Beliebtheit von Windows XP nur auf eine Überprüfung auf Hauptversionsnummern größer oder gleich 5 und Nebenversionsnummern größer oder gleich 1 durchführten. Diese Bedingung aber war bei Windows Vista nicht gegeben. Microsoft hatte die Lektion daraus gelernt und im Folgenden die Hauptversion bei 6 belassen und die Nebenversionsnummer auf mindestens 2 (größer 1) festgelegt, um solche Inkompatibilitäten zu minimieren. Mit Windows 10 wurde die Versionsnummer jedoch auf 10.0 heraufgesetzt.
Beginnend mit Windows 8 gibt die FunktionGetVersionExder Windows-API als Betriebssystemnummer unabhängig vom tatsächlich vorhandenen Betriebssystem standardmäßig 6.2 (Windows 8) zurück. (Diese Funktion ist außerdem als unerwünscht eingestuft.) Das dient zur Minimierung von Kompatibilitätsproblemen, zeigt aber auch, dass die Überprüfung der Betriebssystemversion in den meisten Fällen nicht die beste Vorgehensweise ist, weil manche Komponenten unabhängig von einem bestimmten offiziellen Windows-Release installiert werden können. Wenn Sie dennoch die tatsächliche Betriebssystemversion benötigen, können Sie sie indirekt bestimmen, indem Sie die FunktionVerifyVersionInfooder die neuen Hilfs-APIs für die Versionsbestimmung wieIsWindows80rGreater,IsWindows8Point 10rGreater,IsWindows100rGreater,IsWindowsServeru. Ä. verwenden. Außerdem lässt sich die Betriebssystemkompatibilität im Manifest der ausführbaren Datei angeben, was die Ergebnisse dieser Funktion ändert. (Einzelheiten entnehmen Sie bitte Kapitel 8, »Systemmechanismen«, in Band 2.)
Informationen über die Windows-Version können Sie mit dem Befehlszeilenwerkzeug ver oder grafisch durch Ausführen von winver einsehen. Der folgende Screenshot zeigt das Ergebnis von winver in Windows 10 Enterprise Version 1511:
Das Dialogfeld zeigt auch die Buildnummer (hier 10586.218), die für Windows-Insider hilfreich sein mag (also für diejenigen, die sich registriert haben, um Vorabversionen von Windows zu erhalten). Sie ist auch praktisch für die Verwaltung von Sicherheitsaktualisierungen, da sie zeigt, welche Patches installiert sind.
Mit dem Erscheinen von Windows 10 hat Microsoft angekündigt, Windows jetzt in schnellerer Folge zu aktualisieren als zuvor. Es wird kein offizielles Windows 11 geben. Stattdessen wird Windows Update (oder ein anderes Bereitstellungsmodell) das vorhandene Windows 10 auf eine neue Version aktualisieren. Zurzeit hat es schon zwei solcher Aktualisierungen gegeben, nämlich im November 2015 (Version 1511, wobei sich die Nummer auf Jahr und Monat der Bereitstellung bezieht) und im Juli 2016 (Version 1607, die auch unter der Bezeichnung Anniversary Update vermarktet wurde).
Intern wird Windows nach wie vor phasenweise weiterentwickelt. Beispielsweise trug das ursprüngliche Release von Windows 10 den Codenamen Threshold 1 und die Aktualisierung von November 2015 die Bezeichnung Threshold 2. Die nächsten drei Phasen sind Redstone 1 (Version 1607), auf die Redstone 2 und Redstone 3 folgen werden.
Mit den Jahren wurden verschiedene Geschmacksrichtungen von Windows entwickelt. Neben dem Standard-Windows für PCs gibt es auch das Betriebssystem für die Spielkonsole Xbox 360, bei dem es sich um eine Fork von Windows 2000 handelt. Die Variante Windows Phone 7 basierte auf Windows CE (dem Echtzeit-Betriebssystem von Microsoft). Die Pflege und Erweiterung all dieses Codes ist naturgemäß nicht einfach. Daher hat man bei Microsoft entschieden, die Kernels und die Binärdateien für die grundlegende Plattform in einer einzigen zusammenfassen. Das begann bei Windows 8 und Windows Phone 8, die bereits über einen gemeinsamen Kernel verfügten (wobei Window 8.1. und Windows Phone 8.1 auch eine gemeinsame Windows-Laufzeit-API hatten). Mit Windows 10 ist diese Zusammenlegung abgeschlossen. Die gemeinsame Plattform heißt OneCore und läuft auf PCs, Smartphones, der Spielkonsole Xbox One, der HoloLens und auf IoT-Geräten (für das »Internet der Dinge«) wie dem Raspberry Pi 2.
Diese Geräte unterscheiden sich in ihrer physischen Gestalt sehr stark voneinander, weshalb einige Merkmale nicht überall zur Verfügung stehen. So ist es beispielsweise nicht sinnvoll, für HoloLens-Geräte eine Unterstützung für Maus und Tastatur anzubieten, weshalb diese Teile in der Windows 10-Version dafür nicht vorhanden sind. Aber der Kernel, die Treiber und die Binärdateien der grundlegenden Plattform sind im Prinzip identisch (mit registrierungs- oder richtliniengestützten Einstellungen, wo dies für die Leistung oder aus anderen Gründen sinnvoll ist). Ein Beispiel für solche Richtlinien finden Sie im Abschnitt »API-Sets« in Kapitel 3, »Prozesse und Jobs«.
In diesem Buch geht es um die inneren Mechanismen des OneCore-Kernels unabhängig von dem Gerät, auf dem er läuft. Die Experimente in diesem Buch sind jedoch für Desktop-Computer mit Maus und Tastatur ausgelegt, allerdings hauptsächlich aus praktischen Gründen, da es nicht einfach (und manchmal sogar unmöglich) ist, die gleichen Versuche auf Geräten wie Smartphones oder Xbox One durchzuführen.
In den folgenden Abschnitten geben wir eine Einführung in die Grundprinzipien und -begriffe von Windows, deren Kenntnis für das Verständnis dieses Buches unverzichtbar ist. Viele der hier genannten Elemente wie Prozesse, Threads und virtueller Speicher werden in den nachfolgenden Kapiteln noch ausführlicher dargestellt.
Die Windows-API ist die Systemprogrammierschnittstelle der Windows-Betriebssystemfamilie für den Benutzermodus. Vor der Einführung der 64-Bit-Versionen von Windows wurde die 32-Bit-APi als Win32API bezeichnet, um sie von der ursprünglichen 16-Bit-API zu unterscheiden. Die Bezeichnung Windows-API in diesem Buch bezieht sich sowohl auf die 32- als auch die 64-Bit-Programmierschnittstelle von Windows.
Manchmal verwenden wir auch den Begriff Win32API statt Windows-API. Aber auch dann ist sowohl die 32- als auch die 64-Bit-Variante gemeint.
Die Windows-API wird in der Dokumentation des Windows-SDK beschrieben (siehe den Abschnitt »Windows Software Development Kit« weiter hinten in diesem Kapitel), die kostenlos auf https://developer.microsoft.com/en-us/windows/desktop/develop zur Verfügung steht und in allen Abonnements von MSDN, dem Microsoft-Unterstützungsprogramm für Entwickler, eingeschlossen ist. Eine hervorragende Beschreibung der Programmierung für die grundlegende Windows-API finden Sie in dem Buch Windows via C/C++, Fifth Edition von Jeffrey Richter und Christophe Nasarre (Microsoft Press, 2007).
Die Windows-API bestand ursprünglich nur aus C-artigen Funktionen. Heutzutage können Entwickler auf Tausende solcher Funktionen zurückgreifen. Bei der Erfindung von Windows bot sich die Sprache C an, da sie den kleinsten gemeinsamen Nenner darstellte (weil sie auch von anderen Sprachen aus zugänglich war) und maschinennah genug, um Betriebssystemdienste bereitzustellen. Der Nachteil bestand in einer ungeheuren Menge von Funktionen ohne konsistente Benennung und logische Gruppierung (etwa durch einen Mechanismus wie die Namespaces von C++). Aufgrund dieser Schwierigkeiten wurden schließlich neuere APIs verwendet, die einen anderen API-Mechanismus einsetzten, nämlich das Component Object Model (COM).
COM wurde ursprünglich entwickelt, um Microsoft Office-Anwendungen die Kommunikation und den Datenaustausch zwischen Dokumenten zu ermöglichen (z. B. die Einbettung eines Excel-Diagramms in ein Word-Dokument oder eine PowerPoint-Präsentation). Diese Fähigkeit wird als OLE (Object Linking and Embedding) bezeichnet und wurde ursprünglich mit dem alten Windows-Messagingmechanismus DDE (Dynamic Data Exchange) implementiert. Aufgrund der Einschränkungen, die DDE zu eigen waren, wurde allerdings eine neue Kommunikationsmöglichkeit entwickelt, und das war COM. Als COM um 1993 veröffentlicht wurde, hieß es sogar ursprünglich OLE 2.
COM basiert auf zwei Grundprinzipien: Erstens kommunizieren Clients mit Objekten (manchmal COM-Serverobjekte genannt) über Schnittstellen. Dies sind wohldefinierte Kontrakte mit einem Satz logisch verwandter Methoden, die durch einen Zuteilungsmechanismus für virtuelle Tabellen gruppiert werden. Dies ist eine übliche Vorgehensweise von C++-Compilern zur Implementierung einer Zuteilung für virtuelle Funktionen. Sie resultiert in Binärkompatibilität und verhindert Probleme durch Namensverstümmelung im Compiler. Dadurch wird es möglich, die Methoden von vielen Sprachen (und Compilern) aufzurufen, z. B. C, C++, Visual Basic, .NET-Sprachen, Delphi usw. Das zweite Prinzip lautet, dass die Implementierung von Komponenten dynamisch geladen und nicht statisch mit dem Client verlinkt wird.
Der Begriff COM-Server bezieht sich gewöhnlich auf eine DLL (Dynamic Link Library) oder eine ausführbare Datei (EXE), in der die COM-Klassen implementiert sind. COM weist noch weitere wichtige Merkmale zu Sicherheit, prozessübergreifendem Marshalling, Threading usw. auf. Eine umfassende Darstellung von COM können wir in diesem Buch nicht leisten. Eine hervorragende Abhandlung über COM finden Sie in dem Buch Essential COM von Don Box (Addison-Wesley, 1998).
Über COM zugängliche APIs sind beispielsweise DirectShow, Windows Media Foundation, DirectX, DirectComposition, WIC (Windows Imaging Component) und BITS (Background Intelligent Transfer Service).
Mit Windows 8 wurden eine neue API und eine neue Laufzeitumgebung eingeführt, die Windows Runtime (manchmal auch als WinRT abgekürzt; nicht zu verwechseln mit dem inzwischen eingestellten Betriebssystem Windows RT für ARM-Prozessoren). Die Windows-Laufzeitumgebung besteht aus Plattformdiensten für die Entwickler von sogenannten Windows-Apps (die früher auch als Metro Apps, Modern Apps, Immersive Apps und Windows Store Apps bezeichnet wurden). Windows-Apps können auf unterschiedlichen physischen Geräten ausgeführt werden, von kleinen IoT-Geräten über Telefone und Tablets bis zu Laptop- und Desktop-Computern und sogar auf Geräten wie die Xbox One und die Microsoft HoloLens.
Aus der Sicht der API setzt WinRT auf COM auf und erweitert die grundlegende COM-Infrastruktur. Beispielsweise sind in WinRT vollständige Typmetadaten verfügbar (die im .NET-Metadatenformat in WINMDF-Dateien gespeichert werden), was die COM-Typbibliotheken erweitert. Mit Namespace-Hierarchien, konsistenter Benennung und Programmiermustern ist WinRT auch viel zusammenhängender gestaltet als klassische Windows-API-Funktionen.
Anders als normale Windows-Anwendungen (die jetzt als Windows-Desktop-Anwendungen oder klassische Windows-Anwendungen bezeichnet werden) unterliegen Windows-Apps neuen Regeln. Diese Regeln werden in Kapitel 9, »Verwaltungsmechanismen«, von Band 2 beschrieben.
Die Beziehungen zwischen den verschiedenen APIs und Anwendungen sind nicht offensichtlich. Desktop-Anwendungen können einen Teil der WinRT-APIs verwenden, Windows-Apps dagegen eine der Win32- und COM-APIs. Um jeweils genau zu erfahren, welche APIs für welche Anwendungsplattformen zur Verfügung stehen, schlagen Sie bitte in der MSDN-Dokumentation nach. Beachten Sie jedoch, dass die WinRT-API auf der grundlegenden binären Ebene immer noch auf den älteren Binärdateien und APIs von Windows basiert, auch wenn bestimmte APIs nicht unterstützt werden und ihre Verfügbarkeit nicht dokumentiert ist. Es gibt keine neue »native« API für das System. Das ist vergleichbar mit .NET, das nach wie vor auf die traditionelle Windows-API zurückgreift.
Anwendungen, die in C++, C#, anderen .NET-Sprachen oder JavaScript geschrieben sind, können WinRT-APIs dank der für diese Plattformen entwickelten Sprachprojektionen leicht nutzen. Für C++ hat Microsoft eine nicht standardmäßige Erweiterung namens C++/CX erstellt, die die Verwendung von WinRT-Typen vereinfacht. Die normale COM-Interop-Schicht für .NET (zusammen mit einigen unterstützenden Laufzeiterweiterungen) erlaubt allen .NET-Sprachen die natürliche und einfache Nutzung von WinRT-APIs wie in reinem .NET. Für JavaScript-Entwickler gibt es die Erweiterung WinJS für den Zugriff auf WinRT. Für die Gestaltung der Benutzeroberfläche müssen JavaScript-Entwickler allerdings nach wie vor HTML einsetzen.
HTML kann zwar in Windows-Apps eingesetzt werden, allerdings handelt es sich dabei immer noch um eine lokale Client-App und nicht um eine von einem Web-server abgerufene Webanwendung.
.NET Framework gehört zu Windows. Tabelle 1–2 gibt an, welche Version davon jeweils in den einzelnen Windows-Versionen installiert ist. Es ist jedoch immer möglich, auch eine neuere Version zu installieren.
Windows-Version
.NET Framework-Version
Windows 8
4.5
Windows 8.1
4.5.1
Windows 10
4.6
Windows 10 Version 1511
4.6.1
Windows 10 Version 1607
4.6.2
Tabelle 1–2.NET Framework-Standardinstallation in Windows
.NET Framework besteht aus den beiden folgenden Hauptkomponenten:
CLR (Common Language Runtime)
Dies ist die Laufzeit-Engine für .NET. Sie umfasst einen JIT-Compiler (Just In Time), der CIL-Anweisungen (Common Intermediate Language) in die Maschinensprache der CPU übersetzt, einen Garbage Collector, Typverifizierung, Codezugriffssicherheit usw. Sie ist als In-Process-COM-Server (DLL) implementiert und nutzt verschiedene Einrichtungen, die von der Windows-API bereitgestellt werden.
.NET Framework-Klassenbibliothek (FCL)
Dies ist eine umfangreiche Sammlung von Typen für die Funktionalität, die Client- und Serveranwendungen gewöhnlich benötigen, z. B. Benutzerschnittstellendienste, Netzwerkzugriff, Datenbankzugriff usw.
Durch diese und weitere Merkmale, darunter neue High-Level-Programmiersprachen (C#, Visual Basic, F#) und Unterstützungswerkzeuge, steigert .NET Framework die Produktivität von Entwicklern und erhöht Sicherheit und Zuverlässigkeit der Anwendungen. Abb. 1–1 zeigt die Beziehung zwischen .NET Framework und dem Betriebssystem.
Abbildung 1–1Die Beziehung zwischen .NET und Windows
Mehrere Begriffe in der Windows-Dokumentation für Benutzer und für Programmierer haben je nach Kontext eine unterschiedliche Bedeutung. Beispielsweise kann es sich bei einem Dienst um eine aufrufbare Routine im Betriebssystem, um einen Gerätetreiber oder um einen Serverprozess handeln. Die folgende Aufstellung gibt an, was in diesem Buch mit den genannten Begriffen gemeint ist:
Windows-API-Funktionen
Dies sind dokumentierte, aufrufbare Subroutinen in der Windows-API, beispielsweise
CreateProcess
,
CreateFile
und
GetMessage
.
Native Systemdienste (Systemaufrufe)
Dies sind nicht dokumentierte, zugrunde liegende Dienste im Betriebssystem, die vom Benutzermodus aus aufgerufen werden können. Beispielsweise ist
NtCreateUserProcess
der interne Systemdienst, den die Windows-Funktion
CreateProcess
aufruft, um einen neuen Prozess zu erstellen.
Kernelunterstützungsfunktionen (Routinen)
Dies sind Subroutinen in Windows, die ausschließlich im Kernelmodus aufgerufen werden können (der weiter hinten in diesem Kapitel erklärt wird). Beispielsweise ist
ExAllocatePoolWithTag
die Routine, die Gerätetreiber aufrufen, um Speicher von den Windows-Systemheaps (den sogenannten
Pools
) zuzuweisen.
Windows-Dienste
Dies sind Prozesse, die vom Dienststeuerungs-Manager von Windows gestartet werden. Beispielsweise wird der Taskplaner-Dienst in einem Benutzermodusprozess ausgeführt, der den Befehl
schtasks
unterstützt (der den UNIX-Befehlen
at
und
cron
ähnelt). (In der Registrierung werden Windows-Gerätetreiber zwar als »Dienste« bezeichnet, nicht aber in diesem Buch.)
DLLs (Dynamic Link Libraries)
Eine DLL ist eine Binärdatei, zu der aufrufbare Subroutinen verknüpft worden sind und die von Anwendungen, die diese Subroutinen nutzen, dynamisch geladen werden kann, beispielsweise
Msvcrt.dll
(die C-Laufzeitbibliothek) und
Kernel32.dll
(eine der Teilsystem-Bibliotheken der Windows-API). Komponenten des Windows-Benutzermodus und Anwendungen nutzen DLLs ausgiebig. Der Vorteil von DLLs gegenüber statischen Bibliotheken besteht darin, dass Anwendungen sie gemeinsam nutzen, wobei Windows dafür sorgt, dass es im Arbeitsspeicher nur ein einziges Exemplar des DLL-Codes gibt, auf die alle Anwendungen zugreifen. Bibliotheks-Assemblies von .NET werden als DLLs kompiliert, aber ohne nicht verwaltete, exportierte Subroutinen. Stattdessen parst die CLR die kompilierten Metadaten, um auf die entsprechenden Typen und Elemente zuzugreifen.
Programme und Prozesse scheinen zwar oberflächlich gesehen ähnlich zu sein, unterscheiden sich aber grundlegend voneinander. Ein Programm ist eine statische Folge von Anweisungen, wohingegen es sich bei einem Prozess um einen Container für einen Satz von Ressourcen handelt, die bei der Ausführung einer Instanz des Programms genutzt werden. Grob gesehen, besteht ein Windows-Prozess aus folgenden Elementen:
Privater virtueller Adressraum
Dies ist ein Satz von virtuellen Speicheradressen, die der Prozess nutzen kann.
Ausführbares Programm
Das Programm definiert den ursprünglichen Code und die Daten und wird auf den virtuellen Adressraum des Prozesses abgebildet.
Ein Satz offener Handles
Diese Handles werden verschiedenen Systemressourcen zugeordnet, z. B. Semaphoren, Synchronisierungsobjekten und Dateien, und sind von allen Threads im Prozess aus zugänglich.
Sicherheitskontext
Hierbei handelt es sich um ein
Zugriffstoken
, das den Benutzer, die Sicherheitsgruppen, die Rechte, Attribute, Claims und Fähigkeiten, den Virtualisierungsstatus der Benutzerkontensteuerung, die Sitzung und den Zustand des eingeschränkten Benutzerzugriffs angibt, die mit dem Prozess verbunden sind. Des Weiteren legt der Kontext den Bezeichner des Anwendungscontainers fest und enthält Angaben über die zugehörige Sandbox.
Prozesskennung
Dieser eindeutige Bezeichner ist Teil eines weiteren Bezeichners, nämlich der
Clientkennung
.
Mindestens ein Ausführungsthread
Ein »leerer« Prozess ist zwar möglich, aber (meistens) nicht sinnvoll.
Es gibt eine Reihe von Werkzeugen, um Prozesse und Prozessinformationen einzusehen und zu bearbeiten. Die folgenden Experimente zeigen die verschiedenen Ansichten von Prozessinformationen, die Sie mit einigen dieser Tools gewinnen können. Manche dieser Werkzeuge sind in Windows selbst, im Debugging Tool for Windows oder im Windows SDK enthalten, während es sich bei anderen um eigenständige Programme von Sysinternals handelt. Viele dieser Werkzeuge zeigen die gleichen Kerninformationen über Prozesse und Threads an, manchmal jedoch unter unterschiedlichen Bezeichnungen.
Das wahrscheinlich am häufigsten verwendete Werkzeug zur Untersuchung von Prozessaktivitäten ist der Task-Manager. (Der Name ist allerdings etwas eigenartig, da es im Windows-Kernel keine »Tasks« gibt.) Das folgende Experiment führt einige der Grundfunktionen dieses Programms vor.
Experiment: Prozessinformationen im Task-Manager einsehen
Der im Lieferumfang von Windows enthaltene Task-Manager gibt eine Übersicht über die Prozesse im System. Sie können ihn auf vier verschiedene Weisen starten:
Drücken Sie .Rechtsklicken Sie auf die Taskleiste und wählen Sie Task-Manager starten.Drücken Sie und klicken Sie auf die Schaltfläche Task-Manager starten.Starten Sie die ausführbare Datei Taskmgr.exe.Wenn Sie den Task-Manager zum ersten Mal starten, befindet er sich im Übersichtsmodus, in dem nur die Prozesse angezeigt werden, für die es ein sichtbares Fenster gibt:
In diesem Fenster können Sie allerdings nicht viel sehen. Klicken Sie daher auf die Erweiterungsschaltfläche Details, um in die Vollansicht zu wechseln. Dabei liegt standardmäßig die Registerkarte Prozesse oben:
Die Registerkarte Prozesse zeigt eine Liste der Prozesse mit vier Spalten: CPU, Arbeitsspeicher, Datenträger und Netzwerk. Wenn Sie auf die Kopfzeile rechtsklicken, können Sie noch weitere Spalten einblenden lassen. Zur Verfügung stehen Prozessname (Abbild), Prozess-ID, Typ, Status, Herausgeber und Befehlszeile. Einige Prozesse können erweitert werden, sodass Sie erkennen können, welche sichtbaren Fenster von ihnen erstellt werden.
Um noch mehr Einzelheiten zu den Prozessen einzusehen, klicken Sie auf die Registerkarte Details. Sie können auch auf einen Prozess rechtsklicken und Zu Details wechseln auswählen. Dadurch gelangen Sie auf die Registerkarte Details, wobei der betreffende Prozess schon ausgewählt ist.
Die Registerkarte Prozesse im Task-Manager von Windows 7 entspricht ungefähr der Registerkarte Details im Task-Manager von Windows 8 und höher. Im Task-Manager von Windows 7 zeigt die Registerkarte Anwendungen nur Prozesse mit sichtbaren Fenstern, und nicht sämtliche Prozesse. Diese Angaben sind jetzt auf der Registerkarte Prozesse des neuen Task-Managers von Windows 8 und höher enthalten.
Die Registerkarte Details zeigt ebenfalls Prozesse, aber auf kompaktere Art und Weise. Sie gibt die von den Prozessen erstellten Fenster nicht an, enthält aber eine breitere Auswahl von Informationsspalten.
Prozesse werden anhand ihres Namens bezeichnet und mit einem Symbol dargestellt, das angibt, wovon sie eine Instanz darstellen. Anders als viele andere Objekte in Windows können Prozesse keine globalen Namen bekommen. Um weitere Einzelheiten einzublenden, rechtsklicken Sie auf die Kopfzeile und wählen Spalten auswählen. Dadurch wird eine Liste von Spalten angezeigt:
Unter anderem gibt es folgende wichtige Spalten:
Threads Die Spalte Threads zeigt die Anzahl der Threads in jedem Prozess. Normalerweise sollte sie mindestens eins betragen, da es keine unmittelbare Möglichkeit gibt, um einen Prozess ohne Thread zu erstellen (und ein solcher Prozess auch nicht sehr sinnvoll wäre). Werden für einen Prozess null Threads angezeigt, so bedeutet das gewöhnlich, dass der Prozess aus irgendeinem Grund nicht gelöscht werden kann, wahrscheinlich, weil der Treibercode fehlerhaft ist.Handles Die Spalte Handles zeigt die Anzahl der Handles von Kernelobjekten, die die Threads in dem Prozess geöffnet haben. (Dieser Vorgang wird weiter hinten in diesem Kapitel sowie ausführlich in Kapitel 8 von Band 2 beschrieben.)Status Die Spalte Status ist etwas knifflig. Bei Prozessen ohne Benutzerschnittstelle sollte hier normalerweise Wird ausgeführt angezeigt werden, wobei es jedoch sein kann, dass alle Threads auf irgendetwas warten, etwa auf ein Signal an ein Kernelobjekt oder den Abschluss einer E/A-Operation. Die andere Möglichkeit für einen solchen Prozess ist Angehalten, was angezeigt wird, wenn alle Threads in dem Prozess angehalten sind. Es ist sehr unwahrscheinlich, dass dies durch den Prozess selbst verursacht wird, lässt sich aber programmgesteuert durch den Aufruf der nicht dokumentierten nativen API NtSuspendProcess für den Prozess erreichen, gewöhnlich mithilfe eines Tools (beispielsweise gibt es in dem weiter hinten beschriebenen Process Explorer eine solche Option). Für Prozesse mit Benutzerschnittstelle bedeutet der Statuswert Wird ausgeführt, dass die Benutzerschnittstelle reagiert. Mit anderen Worten, der Thread, der die Fenster erstellt hat, wartet auf Benutzereingaben (technisch gesehen auf die mit ihm verbundene Nachrichtenwarteschlange). Der Zustand Angehalten ist ebenso möglich wie bei Prozessen ohne Benutzerschnittstelle, allerdings tritt er bei Windows-Apps (also denen mit Windows Runtime) gewöhnlich auf, wenn die Anwendung vom Benutzer minimiert wird und dadurch ihren Vordergrundstatus einbüßt. Solche Prozesse werden nach fünf Sekunden angehalten, damit sie keine CPU- und Netzwerkressourcen verbrauchen. Dadurch kann die neue Vordergrundanwendung alle Computerressourcen erhalten. Das ist insbesondere auf akkubetriebenen Geräten wie Tablets und Smartphones wichtig. Dieser und ähnliche Mechanismen werden ausführlich in Kapitel 9 von Band 2 beschrieben. Der dritte mögliche Wert für Status lautet Reagiert nicht. Das kann geschehen, wenn ein Thread in dem Prozess für die Benutzerschnittstelle seine Nachrichtenwarteschlange für Aktivitäten im Zusammenhang mit der Schnittstelle mindestens fünf Sekunden lang nicht überprüft hat. Der Prozesse (eigentlich der Thread, dem das Fenster gehört) kann mit irgendwelchen CPU-intensiven Arbeiten beschäftigt sein oder auf etwas völlig anderes warten (z. B. auf den Abschluss einer E/A-Operation). In jedem Fall friert die Benutzeroberfläche ein, was Windows dadurch kennzeichnet, dass die fraglichen Fenster blasser dargestellt und ihren Titeln der Zusatz (reagiert nicht) hinzugefügt wird.Jeder Prozess verweist außerdem auf seinen Elternprozess (bei dem es sich um seinen Erstellerprozess handeln kann, aber nicht muss). Existiert der Elternprozess nicht mehr, so wird diese Angabe auch nicht mehr aktualisiert. Daher kann es sein, dass ein Prozess auf einen Elternprozess verweist, den es nicht mehr gibt. Das ist jedoch kein Problem, da es nichts gibt, was eine aktuelle Angabe darüber benötigt. Dieses Verhalten wird durch das folgende Experiment veranschaulicht. (Im Tool Process Explorer wird der Startzeitpunkt des Elternprozesses berücksichtigt, um zu verhindern, dass ein Kindprozess auf der Grundlage einer wiederverwendeten Prozesskennung angefügt wird.)
Wann ist der Elternprozess nicht mit dem Erstellerprozess identisch? Bei einigen Prozessen, die von bestimmten Benutzeranwendungen erstellt werden, kann die Hilfe eines Makler- oder Hilfsprozesses erforderlich sein, der die API zur Prozesserstellung aufruft. In einem solchen Fall wäre es verwirrend (oder sogar falsch, wenn eine Vererbung von Handles oder Adressräumen erforderlich ist), den Maklerprozess als Ersteller anzuzeigen, weshalb eine Umdefinition des Elternprozesses erfolgt. Mehr darüber erfahren Sie in Kapitel 7, »Sicherheit«.
Experiment: Die Prozessstruktur einsehen
Die meisten Werkzeuge zeigen für einen Prozess nicht die ID des Eltern- oder des Erstellerprozesses an. Diesen Wert können Sie jedoch in der Leistungsüberwachung (oder programmgesteuert) gewinnen, indem Sie Prozesskennung erstellen abrufen (was eigentlich »Kennung des erstellenden Prozesses« heißen müsste). In Tlist.exe aus den Debugging Tools for Windows können Sie die Prozessstruktur mithilfe des Optionsschalters /t anzeigen lassen. Im Folgenden sehen Sie eine Beispielausgabe von tlist /t:
System Process (0)
System (4)
smss.exe (360)
csrss.exe (460)
wininit.exe (524)
services.exe (648)
svchost.exe (736)
unsecapp.exe (2516)
WmiPrvSE.exe (2860)
WmiPrvSE.exe (2512)
RuntimeBroker.exe (3104)
SkypeHost.exe (2776)
ShellExperienceHost.exe (3760) Windows Shell Experience Host
ApplicationFrameHost.exe (2848) OleMainThreadWndName
SearchUI.exe (3504) Cortana
WmiPrvSE.exe (1576)
TiWorker.exe (6032)
wuapihost.exe (5088)
svchost.exe (788)
svchost.exe (932)
svchost.exe (960)
svchost.exe (976)
svchost.exe (68)
svchost.exe (380)
VSSVC.exe (1124)
svchost.exe (1176)
sihost.exe (3664)
taskhostw.exe (3032) Task Host Window
svchost.exe (1212)
svchost.exe (1636)
spoolsv.exe (1644)
svchost.exe (1936)
OfficeClickToRun.exe (1324)
MSOIDSVC.EXE (1256)
MSOIDSVCM.EXE (2264)
MBAMAgent.exe (2072)
MsMpEng.exe (2116)
SearchIndexer.exe (1000)
SearchProtocolHost.exe (824)
svchost.exe (3328)
svchost.exe (3428)
svchost.exe (4400)
svchost.exe (4360)
svchost.exe (3720)
TrustedInstaller.exe (6052)
lsass.exe (664)
csrss.exe (536)
winlogon.exe (600)
dwm.exe (1100) DWM Notification Window
explorer.exe (3148) Program Manager
OneDrive.exe (4448)
cmd.exe (5992) C:\windows\system32\cmd.exe - tlist /t
conhost.exe (3120) CicMarshalWnd
tlist.exe (5888)
SystemSettingsAdminFlows.exe (4608)
Die Einrückungen in der Liste zeigen die Beziehungen zwischen Eltern- und Kindprozessen. Prozesse, deren Elternprozesse nicht mehr existieren, sind nicht eingerückt (wie explorer.exe im vorstehenden Beispiel), denn selbst wenn der Großelternprozess noch vorhanden wäre, gäbe es keine Möglichkeit, diese Beziehung herauszufinden. Windows führt nur die Kennungen der Erstellerprozesse, aber keine Verbindungen zurück zu den Erstellern der Ersteller usw.
Die Zahl in Klammern ist die Prozesskennung, der bei einigen Prozessen folgende Test der Titel des Fensters, das von dem Prozess angelegt wurde.
Um zu beweisen, dass Windows sich nicht mehr merkt als die Kennung des Elternprozesses, führen Sie die folgenden Schritte aus:
1. Drücken Sie , geben Sie cmd ein und drücken Sie , um eine Eingabeaufforderung zu öffnen.2. Geben Sie titel Parent ein, um den Titel des Fensters in Parent zu ändern.3. Geben Sie start cmd ein, um eine zweite Eingabeaufforderung zu öffnen.4. Geben Sie titel Child an der zweiten Eingabeaufforderung ein.5. Geben Sie an der zweiten Eingabeaufforderung mspaint ein, um Microsoft Paint zu starten.6. Kehren Sie wieder zu der zweiten Eingabeaufforderung zurück und geben Sie exit ein. Paint wird weiterhin ausgeführt.7. Drücken Sie , um den Task-Manager zu öffnen.8. Wenn sich der Task-Manager im Übersichtsmodus befindet, klicken Sie auf Details.9. Klicken Sie auf die Registerkarte Prozesse.10. Suchen Sie die Anwendung Windows Command Processor und erweitern Sie ihren Knoten. Wie im folgenden Screenshot sollten Sie jetzt den Titel Parent sehen.11. Rechtsklicken Sie auf Windows Command Processor und wählen Sie Zu Details wechseln.12. Rechtsklicken Sie auf diesen cmd.exe-Prozess und wählen Sie Prozessstruktur beenden.13. Klicken Sie im Bestätigungsdialogfeld des Task-Managers auf Prozessstruktur beenden.Das Fenster mit der ersten Eingabeaufforderung verschwindet, aber das Paint-Fenster wird nach wie vor angezeigt, da es nur der Enkel des beendeten Eingabeaufforderungsprozesses ist. Da der Zwischenprozess (der Elternprozess von Paint) beendet wurde, gibt es keine Verbindung mehr zwischen dem Elternprozess und seinem Enkel.
Der Process Explorer aus Sysinternals zeigt mehr Einzelheiten über Prozesse und Threads an als jedes andere verfügbare Werkzeug, weshalb wir ihn in vielen Experimenten in diesem Buch verwenden. Unter anderem gibt Ihnen Process Explorer die folgenden einzigartigen Angaben und Möglichkeiten:
Ein Prozesssicherheitstoken, z. B. Listen von Gruppen und Rechten und des Virtualisierungszustands
Hervorhebungen von Veränderungen in der Liste der Prozesse, Threads, DLLs und Handles
Eine Liste der Dienste in Diensthostingprozessen einschließlich Anzeigename und Beschreibung
Eine Liste zusätzlicher Prozessattribute wie Abschwächungsrichtlinien und deren Prozessschutzebene
Prozesse, die zu einem Job gehören, und Angaben zu dem Job
Prozesse für .NET-Anwendungen mit .NET-spezifischen Angaben wie die Aufzählung der Anwendungsdomänen, der geladenen Assemblies sowie CLR-Leistungsindikatoren
Prozesse für Windows Runtime (immersive Prozesse)
Startzeitpunkt von Prozessen und Threads
Vollständige Liste aller Dateien, die im Speicher zugeordnet wurden (nicht nur der DLLs)
Die Möglichkeit, einen Prozess oder Thread anzuhalten
Die Möglichkeit, einen einzelnen Thread zwangsweise zu beenden
Leichte Identifizierung der Prozesse, die im Laufe der Zeit die meisten CPU-Ressourcen verbrauchen
Die Leistungsüberwachung kann die CPU-Nutzung eines Satzes von Prozessen darstellen, zeigt dabei aber nicht automatisch auch Prozesse an, die nach dem Start dieser Überwachungssitzung erstellt wurden. Das können Sie nur mit einer manuellen Ablaufverfolgung im binären Ausgabeformat erreichen.
Des Weiteren bietet Process Explorer leichten, zentralen Zugriff auf Informationen wie die folgenden:
Die Prozessstruktur, wobei es möglich ist, einzelne Teile davon reduziert darzustellen
Offene Handles in einem Prozess, einschließlich nicht benannter Handles
Liste der DLLs (und im Arbeitsspeicher zugeordneten Dateien) in einem Prozess
Threadaktivität in einem Prozess
Thread-Stacks im Benutzer- und im Kernelmodus, einschließlich der Zuordnung von Adressen zu Namen mithilfe der
Dbghelp.dll
, die in den Debugging Tools for Windows enthalten ist
Genauere Angabe des prozentualen CPU-Anteils mithilfe des Threadzykluszählers – eine noch bessere Darstellung der genauen CPU-Aktivität (siehe
Kapitel 4
, »
Threads
«)
Integritätsebene
Einzelheiten des Speicher-Managers wie Spitzenwert des festgelegten virtuellen Speichers und Grenzwerte für ausgelagerte und nicht ausgelagerte Pools des Kernelspeichers (während andere Werkzeuge nur die aktuelle Größe zeigen)
Das folgende Experiment dient zur Einführung in Process Explorer.
Experiment: Einzelheiten über Prozesse mit Process Explorer einsehen
Laden Sie die neueste Version von Process Explorer von Sysinternals herunter und führen Sie sie aus. Das können Sie mit Standardbenutzerrechten tun, aber alternativ auch auf die ausführbare Datei rechtsklicken und Als Administrator ausführen wählen. Wenn Sie Process Explorer mit Administratorrechten ausführen, wird ein Treiber installiert, der mehr Funktionen bietet. Die folgende Beschreibung funktioniert jedoch unabhängig davon, wie Sie Process Explorer starten.
Bei der ersten Ausführung von Process Explorer sollten Sie die Symbole konfigurieren, da Sie anderenfalls eine entsprechende Meldung bekommen, wenn Sie auf einen Prozess doppelklicken und die Registerkarte Threads wählen. Bei ordnungsgemäßer Konfiguration kann Process Explorer auf Symbolinformationen zugreifen, um die Symbolnamen für die Startfunktion des Threads sowie die Funktion auf seinem Aufrufstack anzuzeigen. Das ist praktisch, um zu ermitteln, was die Threads innerhalb eines Prozesses tun. Für den Zugriff auf Symbole müssen die Debugging Tools for Windows installiert sein (siehe die Beschreibung weiter hinten in diesem Kapitel). Klicken Sie auf Options, wählen Sie Configure Symbols und geben Sie den Pfad zu Dbghelp.dll im Ordner von Debugging Tools sowie einen gültigen Symbolpfad an. Wenn die Debugging Tools for Windows auf einem 64-Bit-System im Rahmen des WDK im Standardspeicherort installiert sind, können Sie beispielsweise folgende Konfiguration verwenden:
Hier wird der Symbolserver verwendet, um auf Symbole zuzugreifen, und die Symboldateien werden auf dem lokalen Computer im Ordner C:\symbols gespeichert. (Wenn Sie Speicherplatz sparen müssen, können Sie diesen Ordner auch durch einen anderen Ordner ersetzen, auch durch einen auf einem anderen Laufwerk.) Weitere Informationen darüber, wie Sie die Verwendung des Symbolservers einrichten, erhalten Sie auf https://msdn.microsoft.com/en-us/library/windows/desktop/ee416588.aspx.
Sie können den Microsoft-Symbolserver einrichten, indem Sie die Umgebungsvariable_NT_SYMBOL_PATHauf den Wert aus der vorstehenden Abbildung setzen. Mehrere Werkzeuge suchen automatisch nach dieser Variablen, darunter Process Explorer, die Debugger aus den Debugging Tools for Windows, Visual Studio u. a. Dadurch können Sie es sich ersparen, jedes Tool einzeln zu konfigurieren.
Beim Start zeigt Process Explorer standardmäßig die Prozessstruktur an. Sie können den unteren Bereich erweitern, um die offenen Handles oder die im Arbeitsspeicher zugeordneten DLLs und anderen Dateien anzuzeigen (siehe auch Kapitel 5, »Speicherverwaltung«, und Kapitel 8 von Band 2). Wenn Sie den Mauszeiger über den Namen eines Prozesses halten, werden auch QuickInfos über die Prozessbefehlszeile und den Pfad eingeblendet. Bei einigen Arten von Prozessen enthält die QuickInfo auch zusätzliche Angaben, darunter die folgenden:
Die Dienste innerhalb eines Diensthostingprozesses (z. B. Svchost.exe)Die Tasks innerhalb eines Taskhostingprozesses (z. B. TaskHostw.exe)Das Ziel eines Runddl32.exe-Prozesses für Elemente der Systemsteuerung und andere MerkmaleAngaben zur COM-Klasse, wenn sich der Prozess in einem Dllhost.exe-Prozess befindet (auch Standard-COM+-Ersatz genannt)Anbieterinformationen für WMI-Hostprozesse (Windows Management Instrumentation) wie WMIPrvSE.exe (siehe Kapitel 8 in Band 2)Paketinformationen für Windows-Apps-Prozesse (Prozesse mit Windows Runtime, die weiter vorn in diesem Kapitel im Abschnitt »Die Windows-Laufzeitumgebung« vorgestellt wurden)Führen Sie die folgenden Schritte aus, um einige Grundfunktionen von Process Explorer kennenzulernen:
Machen Sie sich mit den farbigen Hervorhebungen vertraut: Prozesse für Dienste werden standardmäßig rosa hinterlegt, Ihre eigenen Prozesse dagegen blau. Diese Farben können Sie ändern, indem Sie das Dropdownmenü öffnen und Options > Configure Colors auswählen.Halten Sie den Mauszeiger über den Imagenamen eines Prozesses. In einer QuickInfo wird der vollständige Pfad angezeigt. Wie zuvor erwähnt, enthält die QuickInfo bei bestimmten Arten von Prozessen weitere Angaben.Klicken Sie auf der Registerkarte Process Image auf View und wählen Sie Select Columns, um den Imagepfad hinzuzufügen.Klicken Sie auf den Kopf der Spalte Process, um die Prozesse zu sortieren. Dabei verschwindet die Strukturansicht. (Sie können nur entweder die Struktur anzeigen lassen oder eine Sortierung nach einer der Spalten durchführen.) Klicken Sie erneut auf den Kopf von Process, um eine Sortierung von Z zu A zu erreichen. Klicken Sie ein drittes Mal darauf, um wieder die Strukturansicht anzuzeigen.Öffnen Sie das Menü View und deaktivieren Sie Show Processes from All Users, damit nur Ihre Prozesse angezeigt werden.Klicken Sie auf das Menü Options, wählen Sie Difference Highlight Duration und ändern Sie den Wert auf drei Sekunden. Starten Sie dann einen (beliebigen) neuen Prozess. Dabei wird der neue Prozess drei Sekunden lang grün hervorgehoben. Beenden Sie den neuen Prozess. Dabei wird er drei Sekunden lang rot hervorgehoben, bevor er aus der Anzeige verschwindet. Diese Funktion ist nützlich, um sich einen Überblick über die Prozesse zu verschaffen, die auf dem System erstellt und beendet werden.Doppelklicken Sie auf einen Prozess und schauen Sie sich die verschiedenen Registerkarten an, die in der Anzeige der Prozesseigenschaften zur Verfügung stehen. (In verschiedenen Experimenten in diesem Buch werden wir auf diese Registerkarten hinweisen und die darauf befindlichen Angaben erklären.)Ein Thread ist eine Entität in einem Prozess, die Windows zur Ausführung einplant. Ohne einen Thread kann das Programm des Prozesses nicht ausgeführt werden. Ein Thread schließt die folgenden grundlegenden Komponenten ein:
Den Inhalt eines Satzes von CPU-Registern, die den Zustand des Prozessors darstellen
Zwei Stacks: einen für Kernel- und einen für den Benutzermodus
Einen privaten Speicherbereich, der als lokaler Threadspeicher (
Thread-Local Storage, TLS
) bezeichnet und von Teilsystemen, Laufzeitbibliotheken und DLLs verwendet wird
Einen eindeutigen Bezeichner, der als
Threadkennung
oder
Thread-ID
bezeichnet wird (und der zu einer internen Struktur namens
Client-ID
gehört; Prozess- und Thread-IDs werden aus demselben Namespace generiert, weshalb sie niemals überlappen)
Darüber hinaus haben Threads manchmal auch einen eigenen Sicherheitskontext oder ein Token, das häufig von Multithread-Serveranwendungen verwendet wird, um den Sicherheitskontext der Clients anzunehmen, deren Anforderungen sie verarbeiten.
Die flüchtigen Register, die Stacks und der private Speicherbereich bilden den sogenannten Kontext des Threads. Da sie sich zwischen den einzelnen Maschinenarchitekturen unterscheiden, auf denen Windows läuft, ist diese Struktur notgedrungen architekturspezifisch. Die Windows-Funktion GetThreadContext bietet Zugriff auf diese architekturspezifischen Informationen (den sogenannten CONTEXT-Block).
Da an der Umschaltung der Ausführung von einem Thread zu einem anderen der Kernelscheduler beteiligt ist, kann dieser Vorgang sehr kostspielig sein, insbesondere wenn dies häufig zwischen immer denselben Threads geschieht. In Windows gibt es zwei Mechanismen, um die Kosten dafür zu senken, nämlich Fibers und UMS (User-Mode Scheduling).
Die Threads einer 32-Bit-Anwendung, die auf einer 64-Bit-Version von Windows läuft, enthalten sowohl 32- als auch 64-Bit-Kontexte, was Wow64 (Windows on Windows) dazu verwendet, die Anwendung bei Bedarf vom 32- in den 64-Bit-Modus umzuschalten. Diese Threads haben zwei Benutzerstacks und zweiCONTEXT-Blöcke. Die üblichen Windows-API-Funktionen geben stattdessen aber den 64-Bit-Kontext zurück, die FunktionWow64GetThreadContextdagegen den 32-Bit-Kontext. Mehr Informationen über Wow64 erhalten Sie in Kapitel 8 in Band 2.
Fibers ermöglichen es einer Anwendung, ihre eigenen Ausführungsthreads zu planen, anstatt sich auf den prioritätsgestützten Mechanismus von Windows zu verlassen. Sie werden oft auch als schlanke Threads (»lightweight threads«) bezeichnet. Da sie in Kernel32.dll im Benutzermodus implementiert sind, sind sie für den Kernel nicht sichtbar. Um Fibers zu nutzen, müssen Sie zunächst die Windows-Funktion ConvertThreadToFiber aufrufen, die den Thread in eine laufende Fiber umwandelt. Anschließend können Sie die neue Fiber nutzen, um mit der Funktion CreateFiber weitere Fibers zu erstellen. (Jede Fiber kann ihren eigenen Satz von Fibers haben.) Anderes als bei einem Thread jedoch beginnt die Ausführung einer Fiber erst dann, wenn sie über einen Aufruf der Funktion SwitchToFiber manuell ausgewählt wird. Die neue Fiber wird ausgeführt, bis sie mit einem Aufruf von SwitchToFiber beendet wird, der eine andere Fiber zur Ausführung auswählt. Weitere Informationen entnehmen Sie bitte der Dokumentation des Windows SDK über Fiberfunktionen.
Es ist gewöhnlich nicht gut, Fibers zu verwenden, da sie für den Kernel nicht sichtbar sind. Außerdem gibt es bei ihnen Probleme durch die gemeinsame Nutzung des lokalen Threadspeichers (TLS), da in einem Thread mehrere Fibers laufen können. Es gibt zwar auch lokalen Fiberspeicher (FLS), der allerdings nicht alle Probleme der gemeinsamen Verwendung löst. An die E/A gebundene Fibers zeigen auch bei der Verwendung von FLS eine schlechte Leistung. Des Weiteren können Fiber nicht gleichzeitig auf mehreren Prozessoren laufen und sind auf ko-operatives Multitasking beschränkt. In den meisten Situationen ist es besser, dem Windows-Kernel die Planung zu überlassen, indem Sie die geeigneten Threads für die vorliegende Aufgabe auswählen.
UMS-Threads (User-Mode Scheduling) stehen nur in den 64-Bit-Versionen von Windows zur Verfügung. Sie bieten die gleichen grundlegenden Vorteile wie Fibers, aber nur wenige von deren Nachteilen. UMS-Threads haben ihren eigenen Kernelthreadstatus und sind daher für den Kernel sichtbar, was es ermöglicht, dass mehrere UMS-Threads Ressourcen gemeinsam nutzen, darum konkurrieren und blockierende Systemaufrufe ausgeben. Wenn zwei oder mehr UMS-Threads Arbeit im Benutzermodus verrichten müssen, können sie regelmäßig den Ausführungskontext im Benutzermodus wechseln (durch Zurücktreten eines Threads zugunsten eines anderen), anstatt den Scheduler zu bemühen. Aus der Sicht des Kernels läuft weiterhin derselbe Kernelthread, weshalb sich für ihn nichts geändert hat. Führt ein UMS-Thread eine Operation durch, die einen Eintritt in den Kernel erfordert (z. B. einen Systemaufruf), dann schaltet er zu seinem eigenen Kernelmodusthread um (was als direkter Kontextwechsel bezeichnet wird). Es ist zwar immer noch nicht möglich, UMS-Threads gleichzeitig auf mehreren Prozessoren auszuführen, doch zumindest folgen sie einem präemptiven und nicht vollständig kooperativen Modell.
Threads haben zwar ihren eigenen Ausführungskontext, doch alle Threads in einem Prozess teilen sich seinen virtuellen Adressraum (neben den anderen Ressourcen des Prozesses) und haben vollständigen Lese- und Schreibzugriff darauf. Allerdings ist es nicht möglich, dass ein Thread versehentlich auf den Adressraum eines anderen Prozesses verweist, sofern nicht dieser andere Prozess Teile seines privaten Adressraums als freigegebenen Speicherbereich verfügbar macht (was in der Windows-API als Dateizuordnungsobjekt [File Mapping Object] bezeichnet wird) oder ein Prozess das Recht hat, andere Prozesse zur Verwendung von prozessübergreifenden Speicherfunktionen zu öffnen, z. B. ReadProcessMemory und WriteProcessMemory. (Dieses Recht kann ein Prozess, der in demselben Benutzerkonto und nicht innerhalb eines Anwendungscontainers oder einer anderen Art von Sandbox läuft, standardmäßig erwerben, wenn der Zielprozess keine entsprechenden Schutzvorkehrungen aufweist.)
Neben dem privaten Adressraum und einem oder mehr Threads verfügt jeder Prozess auch über einen Sicherheitskontext und einen Satz von offenen Handles für Kernelobjekte wie Dateien, freigegebene Speicherbereiche oder Synchronisierungsobjekte wie Mutexe, Ereignisse oder Semaphoren (siehe Abb. 1–2).
Abbildung 1–2Ein Prozess und seine Ressourcen
Der Sicherheitskontext eines Prozesses wird jeweils in einem Objekt namens Zugriffstoken gespeichert. Es enthält die Sicherheitsidentifizierung und die Anmeldeinformationen für den Prozess. Standardmäßig haben Threads keine eigenen Zugriffstokens. Sie können allerdings eines erwerben, sodass einzelne Threads die Identität des Sicherheitskontextes eines anderes Prozesses annehmen können – auch von Prozessen auf einem anderen Windows-System –, ohne andere Threads in dem Prozess zu beeinträchtigen. (Weitere Einzelheiten zur Prozess- und Threadsicherheit erhalten Sie in Kapitel 7.)
Die VADs (Virtual Address Descriptors) sind Datenstrukturen, die der Speicher-Manager nutzt, um sich über die vom Prozess verwendeten virtuellen Adressen auf dem neuesten Stand zu halten. Diese Datenstrukturen werden in Kapitel 5 ausführlicher beschrieben.
In Windows gibt es Jobs als Erweiterung des Prozessmodells. Der Hauptzweck von Jobs besteht darin, die Verwaltung und Bearbeitung von Prozessgruppen als eine Einheit zu ermöglichen. Diese Objekte erlauben es, bestimmte Attribute zu steuern, und bieten Grenzwerte für die mit ihnen verknüpften Prozesse. Sie zeichnen auch grundlegende Buchführungsinformationen für alle verknüpften Prozesse auf, sowohl die aktuellen als auch diejenigen, die bereits beendet wurden. In gewisser Hinsicht bilden Jobs einen Ersatz für den fehlenden strukturierten Prozessbaum in Windows. In manchen Aspekten sind sie jedoch leistungsfähiger als ein Prozessbaum nach Art von UNIX.
Der Process Explorer kann die von einem Job verwalteten Prozesse anzeigen (standardmäßig in Braun), aber diese Funktion müssen Sie erst aktivieren. Dazu öffnen Sie das Menü Options und wählen Configure Colors. Auf den Eigenschaftenseite solcher Prozesse gibt es außerdem die zusätzliche Registerkarte Jobs, auf der Sie Informationen über das zugehörige Jobobjekt finden.
Weitere Informationen über die interne Struktur von Prozessen und Jobs erhalten Sie in Kapitel 3. Threads und Algorithmen zu ihrer Planung sind Thema von Kapitel 4.
Windows richtet ein virtuelles Speichersystem auf der Grundlage eines linearen Adressraums ein, das jedem Prozess die Illusion gibt, über einen riesigen, privaten Adressraum für sich selbst zu verfügen. Der virtuelle Speicher bietet eine logische Sicht des Arbeitsspeichers, die nicht unbedingt mit dem physischen Aufbau übereinstimmen muss. Zur Laufzeit bildet der Speicher-Manager, unterstützt von der Hardware, die virtuellen Adressen auf die physischen Adressen ab (oder ordnet sie ihnen zu), an denen die Daten tatsächlich gespeichert werden. Durch Schutzvorkehrungen und durch Steuern dieser Zuordnung sorgt das Betriebssystem dafür, dass einzelne Prozesse nicht kollidieren und gegenseitig Betriebssystemdaten überschreiben.