Le componenti di un calcolatore CPU Memoria volatile Hard disk, dispositivi USB, PC Card Rete RAM Memorie di massa Intel x86, AMD Wired e wireless LAN Bluetooth Altri dispositivi Porte di comunicazione (seriale, parallela, USB, firewire, ecc.) Il linguaggio della CPU 31 22 21 12 11 PDE (10 bit) 20 bits PTE (10 bit) 12 bits 1023 20 bits OFFSET (12 bit) 12 bits 0 Page Directory 0 4GB 1023 0 PAGE 4KB Page Table CR#3 ix86 FA 00 08 CF AA 21 88 ………. RAM 0 Il linguaggio della CPU Codici operativi e dati Indirizzi di memoria, porte di comunicazione, ecc. Istruzioni direttamente eseguibili dal processore Molto difficili da ricordare… Molta potenza… nessun controllo!! Estrema possibilità di fare errori nella scrittura Nessuno strumento di verifica del codice Nessun approccio “logico” alla scrittura del codice Solo istruzioni di basso livello Il sistema operativo Windows, Unix/Linux, VMS, OS/400, ecc. Inizialmente Un insieme di servizi per consentire alle applicazioni di non dover “reinventare tutte le volte la classica ruota” Una serie di controlli per evitare che le applicazioni possano “danneggiarsi” tra loro Oggi Tutto quello appena detto più.. Una interfaccia grafica sulle risorse del sistema Un punto di controllo e configurazione del nostro PC Come funziona Windows? Parliamo ovviamente di Windows NT/2000/XP!! Un kernel che fornisce tutti i sistemi di base Un insieme di interfacce di programmazione (API) per accedere ai servizi del kernel Gestione dei processi in esecuzione Gestione della memoria Controllo su tutti i dispositivi attraverso drivers Librerie di funzioni: USER, GDI, KERNEL, ecc. Diffici da utilizzare direttamente Una shell, o interfaccia grafica, per permettere l’interazione con l’utente Le caratteristiche fondamentali Windows è un sistema multi-threading Windows è un sistema basato sul concetto di memoria virtuale Programmi e operazioni diverse possono essere eseguite in parallelo (se abbiamo più CPU..) Ogni programma ha a disposizione 4Gb di memoria “fittizia” Il sistema operativo si occupa di assegnare lo spazio nella memoria fisica e nel file di paginazione ai vari programmi I programmi non possono “danneggiare” il kernel I programmi sono “isolati” e non possono danneggiarsi tra loro Come si programma Windows? Dipende dal tipo di applicazione che vogliamo realizzare Basata su finestre grafiche Web Un servizio di sistema Scrivendo un programma in un linguaggio di programmazione che viene trasformato in “codice macchina” Compilato Interpretato Il programma interagisce con il sistema operativo attraverso le API Per disegnare una finestra Per scrivere sulla stampante, ecc. Un esempio di applicazione Windows L’introduzione delle macchine virtuali Inizialmente i programmi Windows erano scritti in linguaggio C, poi C++ Molta potenza per il programmatore Poco controllo sull’accesso ai servizi di sistema Molto difficile da utilizzare in modo corretto Ogni linguaggio aveva le sue caratteristiche I suoi tipi di dati Le sue librerie di funzioni Il suo modo di gestire la memoria, gli errori, ecc. L’introduzione delle macchine virtuali C’era la necessità di trovare qualcosa che funzionasse da “astrazione” dal sistema operativo per permettere al programmatore di concentrarsi su un “modello virtuale” di sistema Concetto apparso inizialmente in ambito accademico Java è probabilmente l’implementazione più famosa di questo concetto Il .NET Framework di Microsoft è la soluzione creata per tutta la famiglia Windows Applicazioni monolitiche Applicazion e Codice e strutture dati L’era di COM / CORBA C++ / Java / VB IDL Marshaling COM e CORBA consentono di integrare dei componenti. Ogni componente deve però fornire dei “punti di contatto” e gli oggetti non possono interagire direttamente .NET: oltre l’era di COM Con “.NET Framework Common Language Runtime”, i componenti sono costruiti su uno strato comune. Gli oggetti interagiscono direttamente. Perché .NET Difficile effettuare sviluppo omogeneo Molto tempo viene dedicato a far comunicare i vari “strati” Serve un salto qualitativo per semplificare lo scenario Ma non c’era COM ? Architettura .NET Framework VB C++ C# J# … Common Language Specification User Interface Data and XML Base Class Library Common Language Runtime Visual Studio.NET Web Services Cosa è .NET È un ambiente di esecuzione (runtime environment) È una serie di librerie e di strumenti per lo sviluppo di applicazioni Per client Windows Per il Web Per la realizzazione di Web Services Semplifica lo sviluppo e il deployment Aumenta l’affidabilità del codice È completamente indipendente da COM È fortemente integrato con COM Unifica il modello di programmazione Ambiente di esecuzione Concetti chiave: MSIL: Microsoft Intermediate Language CLR: Common Language Runtime CTS: Common Type System CLS: Common Language Specification Codice MSIL Sorgenti Compilatore .NET Codice MSIL (Assembly) .EXE/.DLL Compilatore JIT Codice nativo Output Codice MSIL Sorgenti Compilatore .NET Codice MSIL (Assembly) .EXE/.DLL Codice + metadati Compilatore JIT Codice nativo Output Codice MSIL Sorgenti Compilatore JIT Ambiente di Compilatore esecuzione .NET .NET Runtime Codice nativo Codice MSIL (Assembly) .EXE/.DLL Output Common Language Runtime IL CLRcode offre vari Managed (MSIL) servizi alle applicazioni Common Language Runtime (CLR) Funzionalità specifiche di CLR (es. Garbage Collection) Sistema operativo (Win32, …) Funzionalità esistenti (es. I/O su file) mediate da CLR Common Language Runtime Base Class Library Support Thread Support COM Marshaler Type Checker Exception Manager Security Engine Debug Engine IL to Native Compilers Code Manager Class Loader Garbage Collector Runtime Host Esecuzione di un’applicazione .NET MYCOMCLASS.DLL Managed World KERNEL.DLL MYNETCLASS.DLL MSCOREE.DLL Marshaling MSCORLIB.DLL Processo Win32 (app.exe) Runtime Host MSCOREE.DLL “Ultima” DLL COM rimasta... MSCORLIB.DLL _CorDllMain: Entry-point del loader per caricare ed eseguire il codice IL Implementa CTS (Common Type System) Contiene BCL (Base Class Library) Non si vede con DEPENDS.EXE, usare ADEPENDS.EXE Diversi tipi processi host Shell exe, ASP.NET, Internet Explorer, Servizi NT Sviluppo semplificato Ambiente object-oriented Qualsiasi entità è un oggetto Classi ed ereditarietà pienamente supportati Anche tra linguaggi diversi ! Riduzione errori comuni di programmazione Linguaggi fortemente tipizzati Errori non gestiti Meno memory leak: Garbage Collector Indipendenza dalla piattaforma .NET è un’implementazione di CLI CLI è uno standard ECMA, definito con C# Common Language Infrastructure ECMA-334, ECMA-335 Esistono già altre implementazioni di CLI: SSCLI (Microsoft, per Windows, FreeBSD e Macintosh) Mono (per Linux) DotGNU Intel OCL (Open CLI Library) … Distribuzione semplificata delle applicazioni Assembly Unità minima per la distribuzione, il versioning e la security Simile alle DLL, ma aggiunge meta-dati sul contenuto attraverso il “Manifest” Può essere composto da uno o più file Il manifest può risiedere in un file EXE/DLL separato, oppure in un EXE/DLL che contiene codice dell’assembly Assembly Modulo (file PE) Codice IL Metadati Manifest Assembly a modulo singolo Sicurezza e affidabilità del codice Separazione spazi di memoria in un processo con AppDomain Controllo del codice e sicurezza dei tipi Sono impediti cast non sicuri, variabili non inizializzate, accessi ad array oltre i limiti di allocazione Garbage Collector per tutti gli oggetti .NET Gestione delle eccezioni Miglioramento della diagnostica di errore Integrata con Windows SEH Type safety Isolamento della memoria Type safety (sicurezza dei tipi) Consente l’esecuzione sicura di più applicazioni nello stesso processo Assicura isolamento della memoria Assicura operazioni corrette rispetto al sistema di sicurezza Non è richiesta dal Runtime Verification Assicura type safety Type safety Si eliminano: Cast non sicuri Variabili non inizializzate Indici di array fuori limite (out-of-bounds) PEVERIFY.EXE Tool linea di comando per verificare requisiti di type safety di un assembly Application Domain Unità di elaborazione in .NET Un processo può avere più AppDomain Si può scaricare un AppDomain, non un assembly Relazione thread – AppDomain Runtime host creano AppDomain ASP.NET, Internet Explorer, Shell, … Gestione diretta degli AppDomain Garbage Collector Gli oggetti vengono distrutti automaticamente quando non sono più referenziati A differenza di COM, non ci si basa sul Reference Counting Maggiore velocità di allocazione Consentiti i riferimenti circolari Perdita della distruzione deterministica Algoritmo Mark-and-Compact Garbage Collector - fase 1: Mark NextObjPtr Root set Oggetti “vivi” Oggetti non raggiungibili Spazio libero Garbage Collector - fase 2: Compact Spazio recuperato NextObjPtr Root set Oggetti “vivi” Spazio libero Piattaforma multi-linguaggio Libertà di scelta del linguaggio Tutte le funzionalità di .NET Framework sono disponibili a tutti i linguaggi .NET I componenti di un’applicazione possono essere scritti con diversi linguaggi Impatto sui tool Tool disponibili per tutti i linguaggi: Debugger, Profiler, Analisi “Code coverage”, ecc. CTS: Common Type System Sistema di tipi comune Progettato per linguaggi object-oriented, procedurali e funzionali Alla base di tutti i linguaggi .NET Esaminate caratteristiche di 20 linguaggi Tutte le funzionalità disponibili con IL Ogni linguaggio utilizza alcune caratteristiche Common Language Specification (CLS) Sottoinsieme di CTS Regole di compatibilità tra linguaggi CTS: Common Type System Alla base di tutto ci sono i tipi (le classi) Fortemente tipizzato (compile-time) Object-oriented Campi, metodi, tipi nidificati, proprietà, ... Overload di funzioni (compile-time) Dispatch metodi virtuali risolto a runtime Ereditarietà singola di implementazione Ereditarietà multipla di interfacce Common Type System Qualsiasi applicazione .NET è realizzata definendo un insieme di tipi + utilizzo (istanziazione) di questi ultimi insieme a quelli predefiniti da MS (Base Class Library) Due categorie di tipi: Tipi reference (riferimento) Tipi value (valore) Allocati su heap gestito Allocati su stack o in oggetti gestiti (reference) Tutti i tipi value possono essere visti come tipi reference Boxing Estendibilità tipi value I value type comprendono: Tipi primitivi (built-in) Tipi definiti dall’utente Enum Strutture I tipi value definiti dall’utente hanno le stesse capacità dei tipi primitivi Tipi value e reference in memoria public struct Size { public int height; public int weight; } public class CSize { public int height; public int weight; } void Main() { Size v; // v.height = 100; // CSize r; // r.height = 100; // r = new CSize(); // r.height = 100; // } v.height v.width v istanza di Size ok r è un reference illegale, r non assegnato r fa riferimento a un CSize ok, r inizializzata height width r Stack Heap Class CSize Tipi nativi CLR C# VB.NET Object object Object String string String Boolean bool Boolean Char char Char Single float Single Double double Double Decimal decimal Decimal SByte sbyte n.d. Byte byte Byte Int16 short Short UInt16 ushort n.d. Int32 int Integer UInt32 uint n.d. Int64 long Long UInt64 ulong n.d. Boxing I tipi value si possono sottoporre a “boxing” per supportare le funzionalità tipiche degli oggetti Un tipo value “boxed” è un clone indipendente Un tipo value “boxed” può tornare ad essere value (unboxing) System.Object è il tipo universale Boxing Stack i int i = 123; object o = i; int k = (int)o; Heap 123 int i = 123; o int 123 object o = i; k Boxing 123 int j = (int)o; Unboxing Gestione degli errori Uniforme per tutte le classi Gestione strutturata delle eccezioni Concetto implementato nel CTS Disponibile in tutti i linguaggi con sintassi diverse Concetti universali: Lanciare un’eccezione Catturare un’eccezione Codice di uscita da un blocco controllato (finally) Non ha costi elevati (codice/prestazioni) Gestione strutturata delle eccezioni a() b() Try c() d() Catch e As Exception f() End Try g() Sub c r() s() t() End Sub Sub s Dim a As MyClass a = null a.z() a.w() a.x() End Sub Principali servizi del CLR Garbage collector Reflection Analisi dei metadati di un assembly Generazione di un assembly dinamico Remoting Gestione del ciclo di vita degli oggetti Problema della distruzione deterministica Chiamata di componenti remoti (.NET) Interoperabilità (COM, Platform Invoke) Elaborazione sincrona e asincrona Elaborazione sincrona a() b() c() d() e() f() g() h() Tempo Elaborazione asincrona a() f o r k c() e() g() b() d() f() j o i n h() Thread 1 Thread 2 Elaborazione sincrona e asincrona Programmazione asincrona possibile da tutti i linguaggi Chiamate asincrone Thread Thread pool Componenti remoti A volte è “involontaria”... Nuovo problema: componenti thread-safe Anche per gli sviluppatori VB!! Dove sono gli assembly Assembly privati Assembly condivisi Directory applicazione (e sub-directory) Global Assembly Cache (GAC) c:\windows\assembly Assembly scaricati da URL Download cache c:\windows\assembly\download GACUTIL.EXE Tool per esaminare GAC e download cache Deployment degli assembly XCOPY .CAB Applicazioni ASP.NET Applicazioni Windows Forms - Code Download .MSI (Windows Installer) Applicazioni Windows Forms Installazione in GAC di assembly condivisi Configurazione shortcut Metadati Descrizione di un assembly Descrizione dei tipi Identità: nome, versione, cultura [, pubblic key] Tipi esportati Assembly da cui dipende Permessi necessari per l’esecuzione Nome, visibilità, classe base, interfacce implementate Attributi custom Definiti dall’utente Definiti dal compilatore Definiti dal Framework Strong Name Sinonimo: “shared name” Traduzione ufficiale: “nome sicuro” Lo scopo è garantire: Identità dell’assembly Nessuna modifica del codice Riferimenti univoci Non garantisce identità dell’autore Nel caso usare tecnologie come la firma digitale con certificati Strong Name Nome completo assembly: Name (di solito è il nome del file) Version (major/minor/build/revision) CultureInfo* (lingua/zona) Originator/PublicKey* (identità assembly) Nome assembly visualizzato * = opzionale nomeassembly, Version=1.2.3.4, Culture=en-US, PublicKeyToken=1234123412341234 Codice C# using System.Reflection; [assembly: AssemblyVersion(“1.2.3.4”)] [assembly: AssemblyCulture(“en-US”)] [assembly: AssemblyKeyFile(“mycompany.snk”)] Strong Name Assembly firmato digitalmente Coppia di chiavi pubblica/privata Chiave pubblica 1024 bit nell’assembly Riferimenti all’assembly con Public Token hash 64-bit della chiave pubblica completa Hash di tutto il file Digital Signature SN.EXE per gestire file di chiavi Attributi [AssemblyKeyFile()] e [AssemblyDelaySign()] per associare chiavi agli assembly Firma digitale dell’assembly Library.dll Assembly Codice IL Public Key Metadati Private Key Manifest Public Key Hash File RSA Digital Signature RSA Digital Signature Public Key RSA Digital Signature Hash File Firma digitale dell’assembly Tool e attributi: SN.EXE per gestire file di chiavi Attributi [AssemblyKeyFile()] e [AssemblyDelaySign()] Integrazione con compilatori/VS.NET In alternativa: AL.EXE Strong Name & Strong Reference using System.Reflection; [assembly: AssemblyKeyFile( “publicprivate.snk”)] [assembly: AssemblyDelaySign( false )] csc /t:library StrongLib.cs StrongLib.dll PE/COFF Header Public Key (128 bytes + header 32 bytes) Private Key (436 bytes) Public Key (128 bytes + header 32 bytes) Signature CLR Header Code StrongApp.exe stronglib PE/COFF Header Publicprivate.snk Public Key Token (8 bytes) Assembly Reference CLR Header Code Librerie di classi VB C++ C# J# … Common Language Specification User Interface Data and XML Base Class Library Common Language Runtime Visual Studio.NET Web Services Estendibilità delle classi Il Framework non è una “scatola nera” Qualsiasi classe .NET può essere estesa mediante ereditarietà Diversamente da COM, si usa e si estende la classe stessa, non uno strato intermedio (wrapper) L’ereditarietà è cross-language .NET Framework Web Services User Interface Data Xml Base Class Library .NET Framework System.Web Compilation System.Windows.Forms UI HtmlControls Design ComponentModel WebControls Handlers System.Drawing Hosting Caching Security Drawing2D Printing Configuration SessionState Imaging Text System.Data System.Xml OleDb Common Xsl Schema SqlClient SQLTypes XPath Serialization System Collections IO Security Configuration Reflection Text Diagnostics Resources Threading Globalization Runtime InteropServices Remoting Serialization Linguaggi La piattaforma .NET è neutrale rispetto al linguaggio (nessuno è favorito) Tutti i linguaggi .NET hanno le stesse possibilità Si possono sfruttare skill già esistenti Common Language Specification Consumer: Può usare .NET Framework Extender: Può estendere .NET Framework Linguaggi Microsoft fornisce: VB, C++, C#, J# Linguaggi di terze parti: APL, COBOL, Pascal, Eiffel, Haskell, ML, Oberon, Perl, Python, Scheme, Smalltalk, … Visual Studio .NET Un solo tool per tutti i linguaggi Creazione e consumo di servizi Web Modello a oggetti del codice in editor Debugger integrato … Considerazioni finali Un nuovo modello di sviluppo per la piattaforma applicativa Microsoft Un nuovo ambiente di esecuzione integrato tra diverse tipologie di applicazioni Framework di classi già molto esteso Ma soprattutto coerente! Quasi tutto completamente estendibile Alta integrabilità con il codice esistente A prima vista è tutto semplice, ma è bene andare a dare uno sguardo dietro le quinte!!