Informatica-di-base-2-LIBRI-•-INFORMATICA-PER-PRINCIPIANTI-Pisciotta_-Francesco-2021-6c931f3a814067a.pdf

Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...

Full Transcript

INFORMATICA DI BASE 2 LIBRI: INFORMATICA PER PRINCIPIANTI INFORMATICA PER PRINCIPIANTI - GLI APPROFONDIMENTI - Un progetto: Informatica per principianti www.informaticaperprincipianti.it [email protected]...

INFORMATICA DI BASE 2 LIBRI: INFORMATICA PER PRINCIPIANTI INFORMATICA PER PRINCIPIANTI - GLI APPROFONDIMENTI - Un progetto: Informatica per principianti www.informaticaperprincipianti.it [email protected] FB: informaticaperprincipianti FRANCESCO PISCIOTTA INFORMATICA PER PRINCIPIANTI scopri l’avvincente mondo dell’informatica spiegata in maniera semplice e chiara Francesco Pisciotta Copyright © 2021 Tutti i diritti riservati I testi, le immagini e la grafica contenuti nel libro sono soggetti a copyright e altre forme di tutela della proprietà intellettuale. È vietata qualsiasi utilizzazione, totale o parziale dei contenuti inseriti nel presente libro. Chiunque desiderasse copiare, citare, riprodurre immagini o porzioni di esse deve essere espressamente autorizzato. Eventuali richieste di qualsiasi natura devono essere inoltrate direttamente all’autore mediante indirizzo email. «I computer sono incredibilmente veloci, accurati e stupidi. Gli uomini sono incredibilmente lenti, inaccurati e intelligenti. L'insieme dei due costituisce una forza incalcolabile.» Albert Einstein CONTENUTI LIBRO 1: INFORMATICA PER PRINCIPIANTI PARTE PRIMA: INTRODUZIONE 1 - COS’È L’INFORMATICA 2 - HARDWARE E SOFTWARE 3 - LA SOCIETÀ DELL’INFORMAZIONE PARTE SECONDA: ARCHITETTURA DEI CALCOLATORI 4 – SEGNALI ANALOGICI E DISCRETI 5 - QUANDO 1+1 FA 10 6 - IL LINGUAGGIO DEI COMPUTER 7 -L’ALGEBRA BOOLEANA 8 - I MATTONCINI DEI SISTEMI DIGITALI 9 – DENTRO UN MODERNO CALCOLATORE 10 - LA MEMORIA NEI CALCOLATORI ELETTRONICI 11 – IL FILE SYSTEM 12 - L’ESECUZIONE DEI PROGRAMMI 13 - LE ARCHITETTURE PARALLELE PARTE TERZA: ELABORAZIONE DELLE INFORMAZIONI 14 - IL CONCETTO DI INFORMAZIONE 15 – QUANTO PESA L’INFORMAZIONE? 16 - GLI ALGORITMI 17 - LA SCRITTURA DI UN PROGRAMMA 18 - I LINGUAGGI DI PROGRAMMAZIONE 19 - I LINGUAGGI A OGGETTI 20 - I DATABASE 21 - UNA STRUTTURA PER OGNI OCCASIONE 22 – CI SI PUÒ FIDARE DI UN BANCOMAT? 23 – I SISTEMI OPERATIVI 24 – LA CENA DEI FILOSOFI 25 – IL CICLO DI VITA DEL SOFTWARE 26 – IL SOFTWARE PERFETTO PARTE QUARTA: RETI DI COMPUTER 27 - LE BASI DELLA COMUNICAZIONE 28 - LA MODULAZIONE DEI SEGNALI 29 – TANTE POSSIBILI RETI 30 - LA RETE DELLE RETI: INTERNET 31 - IL WORLD WIDE WEB 32 – SERVIAMO IL NUMERO 33 - LA SICUREZZA INFORMATICA 34 – L’INGEGNERIA SOCIALE 35 - COME NASCONDERE LE INFORMAZIONI 36 - LA COMPRESSIONE DEI DATI PARTE QUINTA: STORIA DELL’INFORMATICA 37 - IL CALCOLO COME NECESSITÀ 38 – IL CAMMINO COMINCIA 39 – I PRIMI COMPUTER DELLA STORIA 40 – ALAN TURING E LA SUA MACCHINA 41 – UN’ARCHITETTURA VINCENTE 42 – IL CONTRIBUTO DELL’ITALIA 43 – IL MOUSE E LE FINESTRE 44 – IL SOFTWARE LIBERO 45 – IL PENSIERO DIGITALE 46 – IL COMMESSO VIAGGIATORE 47 – IL CLOUD E LA VIRTUALIZZAZIONE CONCLUSIONE LIBRO 2: INFORMATICA PER PRINCIPIANTI - GLI APPROFONDIMENTI - I MOTORI DI RICERCA COME FUNZIONA L’EMAIL IL CONCETTO DI SISTEMA LA MEMORIA RAM IL WORLD WIDE WEB LO STREAMING DEI DATI IL PHISHING IL DEEP WEB E IL DARK WEB IL DIGITAL DIVIDE ORDINARE CON LE BOLLICINE IL LINGUAGGIO DI ANALISI UML COME FUNZIONA UN ANTIVIRUS LE FUNZIONI HASH COS’È IL RAID DEI DISCHI L’ALGEBRA BINARIA LA CRITTOGRAFIA L’APPRENDIMENTO DIGITALE COME FUNZIONA GOOGLE COS’È LA BLOCKCHAIN L’ARCHITETTURA A TRE LIVELLI COME NASCONO I MICROPROCESSORI IL BIT DI PARITÀ LA SAN PER MEMORIZZARE LA FIBRA OTTICA I CODICI DI CORREZIONE DEGLI ERRORI LE MACCHINE VIRTUALI COME FUNZIONANO GLI HARD DISK LE CRIPTOVALUTE E I BITCOIN LA FIRMA ELETTRONICA LA RIVOLUZIONE DEL CLOUD WINDOWS VS LINUX LA TORTA AL CIOCCOLATO SCRIVIAMO UN PROGRAMMA 1/2 SCRIVIAMO UN PROGRAMMA 2/2 CONCLUSIONE PREMESSA A nzitutto congratulazioni! Se hai questo libro fra le mani è perché sei una persona curiosa, che vuole imparare e scoprire sempre cose nuove. Probabilmente parti da un livello di informatica basso, ma non ti preoccupare, sei nel posto giusto! Vedrai che man mano che leggerai il libro, inizierai a familiarizzare e capire sempre meglio questo mondo davvero interessante. Nel primo libro affronteremo l’informatica a 360 gradi. Ti mostrerò tutti gli aspetti principali e capirai anche tante cose che, magari, davi per scontato o non sapevi spiegarti. Nel secondo libro approfondiremo alcuni aspetti visti superficialmente nel primo libro, ma non solo, vedremo anche diversi argomenti nuovi e molto interessanti. Inoltre questo libro è anche in formato video corso , in cui vengono spiegati tutti gli argomenti mediante delle video lezioni animate. Puoi acquistare il corso su Udemy , la più grande piattaforma di corsi al mondo. Approfitta delle offerte che propongono. Vai su: https://tinyurl.com/informaticaperprincipianti Per qualsiasi comunicazione mi puoi scrivere al seguente indirizzo email: [email protected] Infine, se hai apprezzato il libro, ti chiedo di lasciare una recensione su Amazon, per me conta molto, grazie. Buon apprendimento! \fp PARTE PRIMA INTRODUZIONE 1 - COS’È L’INFORMATICA V erso la metà del secolo scorso, qualcosa di nuovo e inatteso iniziò a verificarsi. Nei paesi più industrializzati il progresso tecnologico raggiunse ben presto una velocità mai osservata prima. I cospicui investimenti nella ricerca scientifica, infatti, permisero sempre più di ottenere importanti risultati. Molti processi, prima ripetitivi, riuscivano ad essere via via completamente o in parte automatizzati. Il tutto con una maggiore velocità, precisione e sicurezza assolutamente impensabili fino a qualche decennio prima. La fiducia che l’uomo riponeva nelle nuove tecnologie era il vero carburante di questo straordinario cambiamento. In particolare stava venendo alla luce una disciplina completamente nuova: l’ informatica. All’origine era solo qualcosa di misterioso, roba complicata riservata agli scienziati e ai cervelloni, ma che via via iniziò a definirsi sempre di più. Col passare degli anni l’informatica assunse un ruolo sempre più indispensabile in diversi campi. Una vera e propria trasformazione epocale , tanto che i sociologi hanno battezzato questo periodo come la terza rivoluzione industriale. Abbiamo davvero tanto da vedere in questo libro, ma partiamo dal principio: che cos’è l’informatica? Contrariamente a quello che molte persone pensano, l’informatica è una disciplina estremamente vasta, al cui interno troviamo tanti ambiti anche molto diversi fra loro. A tal proposito, ancor prima di cercare una possibile definizione, andiamo a scoprire i principali campi di questa disciplina. Anzitutto possiamo per semplicità suddividere l’informatica in due categorie principali: l’ informatica teorica e l’ informatica applicata. L’ informatica teorica raggruppa delle discipline che studiano la natura della computazione e di conseguenza si propone di fornire metodologie di calcolo sempre più efficienti. Al suo interno possiamo evidenziare i seguenti campi: La Teoria della computazione --- il cui fine è quello di capire quali problemi possono essere risolti, la complessità dei calcoli e le risorse necessarie. I linguaggi di programmazione --- ossia l’analisi e la creazione di nuovi linguaggi per descrivere la soluzione a dei problemi. Gli algoritmi e le strutture dati --- è l’ambito che studia e propone strumenti e metodologie per la progettazione di soluzioni corrette ed efficienti ai più svariati problemi. Il calcolo distribuito --- è quel vasto campo dell’informatica che si occupa dei sistemi distribuiti, cioè sistemi in cui più elaboratori comunicano fra loro tramite una rete. L’ informatica applicata , invece, si preoccupa maggiormente degli aspetti più pratici. Possiamo individuare al suo interno campi come: Architettura dei calcolatori --- in cui si studiano e realizzano i calcolatori elettronici. Ingegneria del software --- che copre l’intero ciclo di vita di un software, dall’analisi, all’implementazione, con lo scopo di garantire una loro alta qualità, affidabilità ed efficienza. Basi di dati --- dove si studiano le basi di dati, o database, che sono strutture usate per la memorizzazione di informazioni fra loro correlate secondo opportuni criteri logici. La sicurezza informatica --- l’importante campo nato per valutare i rischi di un sistema informatico e le soluzioni possibili per metterlo in sicurezza. Questo vuol dire renderlo virtualmente invulnerabile, sia da attacchi esterni da parte di malintenzionati, sia dal furto o perdita di informazioni private. Le reti di calcolatori --- una rete di calcolatori è un insieme distribuito di calcolatori, o più in generale dovremmo dire di risorse, collegate in qualche modo tra loro, allo scopo di scambiarsi informazioni o risolvere un problema condiviso. L’interazione uomo-computer --- in cui si fa ricerca e sviluppo di sistemi in grado di far interagire gli esseri umani con dei dispositivi elettronici, nel miglior modo possibile. L’intelligenza artificiale --- è un campo molto complesso, che si pone l’ambiziosa sfida di realizzare delle macchine capaci di simulare l’intelligenza e l’apprendimento umano. Non devi preoccuparti se alcuni termini ancora non li conosci o non li hai mai sentiti! Approfondiremo tutto nei prossimi capitoli. Quindi come puoi vedere, l’informatica abbraccia un ampio numero di discipline e non si limita assolutamente nella conoscenza e utilizzo di programmi più o meno complicati, né tantomeno saper ‘smanettare’ al computer. Il famoso scienziato olandese Edsger W. Dijkstra, che incontreremo più avanti nel libro, disse con una certa ironia che «l’informatica riguarda i computer come l’astronomia riguarda i telescopi». Inoltre l’informatica nella pratica si fonde spesso con altri ambiti come l’elettronica e le telecomunicazioni, difatti l’equivalente termine anglosassone, ormai entrato nell’uso comune, è ICT , acronimo di Information and Communications Technology. Torniamo un po’ indietro… Stavamo cercando una definizione di informatica. Per il momento accontentiamoci di una visione generale: L’informatica è la scienza che si occupa del trattamento dell’informazione mediante procedure automatiche e con l’ausilio di calcolatori elettronici. Vedremo presto anche cosa si intende di preciso per informazione e cosa è un calcolatore elettronico. Prima però dobbiamo fare una importante distinzione… 2 - HARDWARE E SOFTWARE A llora, partiamo dalle basi: la differenza tra hardware e software. Forse non conosci ancora il significato di questi termini, ma scommetto che li avrai comunque sentiti. Molto semplicemente possiamo intendere con hardware tutto ciò che ha a che fare con la parte fisica di un calcolatore elettronico, o di altri dispositivi. Infatti in inglese hard significa duro e ware manufatto. Per cui è hardware il contenitore metallico del pc, le schede che ci sono dentro, i cavi, il monitor, la stampante, ecc. Con il termine software, invece, ci si riferisce ai programmi che vengono eseguiti grazie all’hardware stesso. In questo contesto soft , cioè morbido, ha la connotazione di inconsistente, immateriale. Il software, pertanto, è nient’altro che tutti quei programmi che usiamo quotidianamente per lavorare, studiare o per divertimento. Avremo modo di approfondire più avanti. Inoltre, l’insieme di hardware e software viene chiamato generalmente sistema informatico. Un sistema informatico può essere, ad esempio, un insieme di computer connessi fra loro da una rete. 3 - LA SOCIETÀ DELL’INFORMAZIONE N ella società moderna l'informazione ricopre un ruolo di primissimo piano. Anzi, a dirla tutta, questa risorsa immateriale e sfuggente è oggi di gran lunga fra le più importanti per l’uomo. Disporre delle giuste informazioni il più rapidamente possibile è assolutamente strategico per qualsiasi azienda che operi nel mercato globale. Ma questo è vero anche per ciascuno di noi nella vita di ogni giorno; ogni volta che ci troviamo davanti a diverse possibili opzioni e dobbiamo fare una scelta, avere le corrette informazioni può equivalere a prendere la decisione migliore o, tutt’al più, la meno peggio. Oggigiorno, grazie a tecnologie come Internet e la telefonia mobile, siamo in grado di far arrivare le nostre informazioni in qualsiasi parte del mondo e in tempi sempre più brevi. La conoscenza viaggia a velocità istantanea in modo sempre più capillare. È risaputo che perfino alcune rivolte sociali sono state innescate grazie all’ausilio di queste tecnologie. Non si può negare l’evidenza: il mondo che abitiamo sta cambiando rapidamente e, che lo vogliamo o no, è impossibile ormai rimanerne in disparte. Le barriere sono cadute, i popoli e le nazioni si sono avvicinati ed è necessario ridefinirne continuamente i confini. Va sottolineato, però, che al giorno d’oggi l’accesso ai sistemi informatici non è purtroppo omogeneo nel mondo, anzi, ci sono ancora profondissime differenze in base alla latitudine, al sesso e alla cultura. Inoltre in alcuni paesi vige un’opprimente censura che, non solo impedisce ai cittadini l’accesso alle informazioni, ma le distorce sistematicamente per fare propaganda. Tutto questo ha creato quello che viene definito digital divide o divario digitale. Vediamo meglio di che si tratta. Possedere un computer o usare Internet è qualcosa che noi diamo ormai per scontato. Tuttavia non è così per una grossa fetta della popolazione mondiale, che a volte non può neanche contare su una regolare fornitura di energia elettrica. Ma spesso anche all’interno di uno stesso paese tecnologicamente progredito, come il nostro, ci sono importanti disparità, ad esempio fra grandi città e paesini sperduti, in cui portare Internet a banda larga ha un costo troppo alto, che spesso ai fornitori non conviene sostenere. Il risultato è che l’arretratezza tecnologica genera un circolo vizioso che tende col tempo ad allontanare sempre più questi paesi e questi popoli da chi ha invece la possibilità di usufruire dell’enorme quantità di informazioni e possibilità che Internet offre. Tutto questo fa bruciare ricchezza e opportunità alle popolazioni più svantaggiate. Le mappe geografiche che mostrano la diffusione di Internet a livello mondiale evidenziano chiaramente un netto divario fra i paesi. Le zone con maggiore densità tecnologica (più scure nella mappa) sono gran parte dell'Europa, il Nord America, l’Australia e il Giappone, specie nelle aree metropolitane, subito dopo troviamo alcuni stati dell’America Latina. Fanalini di coda Asia e Africa, quest’ultima praticamente tagliata fuori dalla Rete. A questo punto potresti osservare che più informazioni si hanno e meglio è. Paradossalmente non è così. Infatti avere una quantità enorme di informazioni, come è facilmente possibile oggi, può essere addirittura controproducente. Viene chiamato sovraccarico informativo ed è l’ostacolo diametralmente opposto al digital divide. Anche se a prima vista può apparire poco intuitivo, avere troppe informazioni rende più difficile individuare qualcosa di preciso e puntuale che ci serve in quel dato momento, facendoci perdere tempo se non siamo abbastanza bravi da saperci districare. Ma non è solo un problema di quantità, bensì anche di qualità. Infatti, sebbene la libertà di partecipare attivamente su Internet sia certamente una cosa positiva, genera purtroppo anche una enorme quantità di informazione spazzatura, spesso non filtrata e verificata. Addirittura questo sovraccarico di informazioni può provocare in rari casi un vero e proprio disagio sociale e psicologico. Esistono anche degli insiemi di tecnologie, che rientrano nel termine data mining , in grado di estrarre delle informazioni utili da enormi quantità di dati, sebbene non facilmente individuabili. Sono tecnologie essenziali per le grandi aziende perché grazie ad esse è possibile dedurre o predire delle informazioni che a prima vista sfuggono a delle analisi più superficiali. L'automazione in questo campo è molto spinta per due ovvi motivi. Il primo è che la quantità di dati da esaminare è davvero ingente e il secondo motivo è che potrebbero esistere correlazioni fra i dati stessi che sfuggono a delle semplici analisi eseguite da delle persone fisiche. Si tratta di software che operano su oggetti come enormi database, ne studiano le strutture e cercano di capire se ci sono possibili dipendenze tra i dati. In caso affermativo si cerca di estrapolare una conoscenza che può sicuramente tornare utile all’azienda, ad esempio, per stimare gli andamenti e le previsioni sul futuro. PARTE SECONDA ARCHITETTURA DEI CALCOLATORI 4 – SEGNALI ANALOGICI E DISCRETI A nche se a prima vista potrebbe sembrarti un argomento non strettamente correlato con l’informatica, è tuttavia fondamentale che tu capisca da subito cosa è un segnale. Partiamo subito con la definizione: In generale possiamo definire un segnale come la variazione nel tempo di una particolare grandezza fisica. Ad esempio, se considero la temperatura dell’aria durante l’arco della giornata posso stabilire una relazione fra il tempo, espresso in ore, e la temperatura stessa, espressa in gradi centigradi. Oppure posso misurare la velocità di un’automobile mentre corre in autostrada. Il punto evidente è che un segnale, qualunque esso sia, porta con sé un’informazione, nel primo esempio abbiamo l’andamento della temperatura nella giornata, nel secondo l’andamento della velocità di un’automobile. Questo punto è molto importante, ma ci torneremo più avanti. I dispositivi elettronici funzionano con la corrente elettrica ovviamente, per cui nel nostro caso quelli che ci interessano sono i segnali elettrici. Bene, consideriamo pertanto un semplice circuito formato da un generatore variabile di tensione elettrica e una comune lampadina. Non preoccuparti non entreremo negli aspetti fisici, l’importante è afferrare il concetto. Tale circuito sarà percorso da una corrente che permetterà alla lampadina di illuminare. Ora supponiamo di modificare la tensione aumentandola e diminuendola. Ovviamente cambierà anche la luminosità della lampadina in accordo con la tensione fornita. In questo caso la tensione elettrica ha per così dire ‘trasferito’ dell’informazione dalla sorgente (il generatore) alla destinazione (lampadina). In altre parole la variazione della tensione ha prodotto una variazione di luminosit à. La tensione elettrica quando varia lo fa assumendo in modo continuo tutti i possibili valori fra un minimo e un massimo. Si dice pertanto che è un segnale analogico o continuo. Anche la variazione della temperatura che percepiamo è una grandezza continua poiché si passa da un valore all’altro in modo continuo, per quanto sia brusca la variazione. Ci sono però dei segnali che hanno un comportamento diverso. Alcuni segnali, infatti, possono assumere solo determinati valori in ben precisi istanti di tempo. Ad esempio il numero di persone che sale su un autobus a ciascuna fermata è una grandezza che può assumere solo valori interi come: 2, 3, 6,1. Non ha nessun senso dire che 4,3 persone salgono sull’autobus. Questo tipo di segnale è detto discreto. Spesso sono anche chiamati segnali digitali. Infine ci sono i segnali binari , che sono dei segnali digitali con la proprietà aggiuntiva che possono assumere solo 2 possibili valori, che per convenzione vengono indicati come zero e uno. Ciascuno di essi viene chiamato BIT. Approfondiremo il tutto più avanti. I calcolatori elettronici, gli smartphone, i tablet, ecc. lavorano tutti con i segnali binari. Tutti i loro componenti elettronici conoscono e parlano solo questa lingua, costituita dai valori zero e uno. Questi BIT, lo 0 (zero) e l’1 (uno), corrispondono a due ben precisi valori di tensione elettrica, in genere 0 Volt e 5 Volt. I valori possono essere leggermente diversi, ma per ora non importa, ciò che è fondamentale è che tu afferri il concetto. Pertanto ricapitolando abbiamo due tipologie di segnali: Segnali analogici Segnali discreti Quest’ultima tipologia, inoltre, comprende quelli che per l’informatica e l’elettronica sono i più importanti in assoluto: Segnali binari Nei prossimi capitoli approfondiremo ulteriormente questo aspetto. 5 - QUANDO 1+1 FA 10 N o, non c’è un errore nel titolo del capitolo. D’accordo, lo so che 1+1 fa 2, ma questo vale solo nel sistema di numerazione decimale , un sistema che fa uso di dieci cifre, dallo 0 al 9. È quello che usiamo tutti i giorni e probabilmente tale scelta fu favorita dalla praticità nel fare i calcoli con le mani, proprio per il fatto che l’uomo ha dieci dita. Tuttavia ci sono alcune situazioni in cui risulta più semplice ricorrere a differenti sistemi numerici. Se ti sembra un discorso astruso, fidati, alla fine del capitolo ti sarà più chiaro. Per esempio il sistema cosi detto ottale fa uso di meno simboli, per la precisione 8, per rappresentare un qualsiasi numero. Questi simboli sono le cifre dallo 0 al 7. Invece l’otto e il nove neanche esistono qui. Vediamo alcuni numeri decimali a cosa corrispondono nel sistema ottale. decimale ottale 0 0 1 1 2 2 3 3 4 4 5 5 6 6 7 7 8 10 9 11 10 12 11 13 12 14 13 15 14 16 15 17 16 20 17 21 18 22 19 23 20 24 50 62 100 144 200 310 1000 1750 Come puoi vedere, i primi 7 numeri sono identici, ma per quelli maggiori di 7? Beh, si fa proprio come nel nostro sistema decimale, cioè si usano più cifre. Per cui 8 decimale si rappresenta come uno-zero in ottale, nove come uno-uno e così via tutti gli altri, facendo attenzione a usare sempre e solo le cifre dallo 0 al 7 per i numeri in ottale. A prima vista può sembrare un’inutile complicazione, ma ci sono numerose situazioni in cui risulta preferibile ricorrere a diversi sistemi numerici. Un altro sistema di numerazione che trova molte applicazioni nell’informatica è il sistema numerico esadecimale. Qui i simboli utilizzati sono 16, per cui le sole 10 cifre decimali non sono sufficienti. Pertanto si ricorre anche alle prime sei lettere dell’alfabeto A, B, C, D, E, e F. Vediamo gli stessi numeri dell’esempio precedente, tradotti con il sistema esadecimale. Come puoi notare al crescere dei valori, sono necessarie meno cifre del sistema decimale, ad esempio per rappresentare il numero mille sono necessarie 4 cifre nel decimale e solo 3 nell’esadecimale. decimale esadecimale 0 0 1 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8 9 9 10 A 11 B 12 C 13 D 14 E 15 F 16 10 17 11 18 12 19 13 20 14 50 32 100 64 200 C8 1000 3E8 Ma il più importante di tutti è senz’altro il sistema binario. Appare subito evidente che usando meno simboli (solo due invece dei dieci del sistema decimale) me ne serviranno di più per rappresentare lo stesso numero. Anche in questo caso a titolo d’esempio riportiamo la corrispondenza di alcuni numeri decimali con i relativi del sistema binario. decimale binario 0 0 1 1 2 10 3 11 4 100 5 101 6 110 7 111 8 1000 9 1001 10 1010 11 1011 12 1100 13 1101 14 1110 15 1111 16 10000 17 10001 18 10010 19 10011 20 10100 50 110010 100 1100100 200 11001000 1000 1111101000 Ovviamente ci sono delle regole aritmetiche che ci consentono agilmente di passare da un sistema a un altro, ma al momento non è il caso di approfondire. Per ora l’importante è che tu sappia che il sistema numerico decimale che noi usiamo quotidianamente non è l’unico possibile, proprio come le tante lingue parlate nel mondo. Di tutti questi sistemi numerici quello binario, formato da due soli simboli, lo zero e l’uno, è di fondamentale importanza nel mondo dell’informatica. Questo perché è l’unico linguaggio che un dispositivo digitale può interpretare. Vediamone il motivo. Consideriamo un generico componente elettronico di un computer. Per lui esistono solo due tipi di tensione elettrica per cui lavora, 5 volt e 0 volt. Pertanto facciamo corrispondere il valore 5 volt con il simbolo ‘+’ e zero volt con il simbolo ‘-‘, come in figura. Supponiamo inoltre che in un dato istante sui connettori ci siano le tensioni elettriche così come rappresentate graficamente. Ecco quindi come ragiona un componente elettronico: se gli arriva una corrente elettrica con tensione di 5 volt, per lui sarà un 1, altrimenti lo interpreterà come uno 0. Semplice no? Ripetiamo, questo punto è molto importante: nell’elettronica digitale ad una tensione di 5 volt corrisponde il BIT 1 e a quella di 0 volt il BIT 0. Pertanto, se noi usiamo il sistema a dieci cifre perché è più semplice, allo stesso modo un computer, o qualsiasi altro dispositivo digitale, usa il sistema binario perché per lui è più facile lavorare con due sole cifre. Spero che questo importantissimo concetto ti sia chiaro. Sottolineo che i valori di tensione possono anche essere leggermente diversi, ma il punto fondamentale è che ai BIT 0 e 1 sono associate due distinte tensioni elettriche. Finora, però, non ho ancora giustificato il titolo del capitolo. Perché 1+1 fa 10? Dovrebbe essere chiaro adesso che non mi riferivo al sistema decimale bensì a quello binario, dove 1+1 fa proprio 10. Infatti, così come nel sistema decimale, anche in quello binario posso fare tutte le normali operazioni aritmetiche. Facciamo un esempio di addizione, consideriamo i numeri 9 e 5. Abbiamo visto che 9 e 5 si scrivono in binario rispettivamente come 1001 (uno-zero-zero-uno) e 101 (uno-zero-uno), per cui facendo la somma e utilizzando i riporti si ha che: E infatti, 1110 corrisponde proprio al numero 14 in decimale. Le operazioni aritmetiche in binario seguono le stesse regole di quelle in decimale, facendo bene attenzione, però, che le cifre da usare sono sempre e solo l’1 e lo 0. 6 - IL LINGUAGGIO DEI COMPUTER N el capitolo precedente abbiamo visto che per un componente elettronico, un BIT corrisponde a nient’altro che un valore di tensione elettrica. Bene, facciamo adesso un passo ulteriore, aiutandoci con un esempio… Supponiamo di avere un componente trasmettitore, lo indichiamo con TX e un ricevitore, RX, per adesso non ha importanza entrare nel dettaglio. E supponiamo anche che TX e RX siano connessi da un cavo in cui circola corrente elettrica. Se TX volesse comunicare con RX potrebbe far variare la tensione elettrica in base a un certo codice che anche RX conosce. Diciamo che il nostro codice è composto da 4 soli valori: per semplicità chiamiamoli A, B, C e D. A questo punto la domanda è: quanti BIT mi servono per codificare 4 valori? È evidente che ne servono 2: ossia 00 per A, 01 per B, 10 per C e 11 per D. La seguente figura mostra questa configurazione. Siccome abbiamo un solo cavo di collegamento se TX vuole trasmettere il simbolo A, dovrà inviare prima uno 0 (valore di tensione 0 Volt) e subito dopo ancora uno 0 (sempre tensione a 0 Volt). Se deve trasmette il simbolo B invierà prima il BIT a destra, ossia 1 (tensione 5 Volt) e poi quello a sinistra, uno 0 (tensione di nuovo a 0 Volt). E così per tutti gli altri simboli. Quindi stiamo usando due diversi valori di tensione elettrica per comunicare con questo codice. Ripetiamo i valori: 5 volt per il BIT 1 0 volt per il BIT 0 Bene, a questo punto, però, nasce spontanea una domanda «Ma perché usare solo due valori di tensione? Se ne usassimo quattro che corrispondono ad esempio a: A=0 volt B=5 volt C=10 volt D=15 volt si potrebbe inviare il simbolo A, B, C o D in un’unica volta, quindi, evidentemente, avremmo una comunicazione più veloce». Ok corretto, ma facendo così sono necessari valori più alti di tensione e di corrente, di conseguenza costi più alti. Non solo, ma ci sarebbe anche più calore prodotto dai circuiti e questa non è mai una cosa positiva. Allora un’altra ipotesi potrebbe essere provare a restringere l’intervallo fra i valori minimo e massimo suddividendo un solo volt in quattro parti uguali e assegnarli così: A= 0,25 volt B=0,5 volt C=0,75 volt D=1 volt Purtroppo anche questa non è una buona idea, infatti in questo modo l’intero sistema risulterebbe più suscettibile a degli errori poiché i valori di tensione scelti sono troppo vicini fra loro e anche un piccolo disturbo sul mezzo trasmissivo, dovuto ad esempio a degli sbalzi di tensione o a campi elettromagnetici lungo il percorso, potrebbe trasformare un simbolo in un altro, falsando l’informazione che voglio trasmettere. Si dice che il sistema non è robusto ai disturbi esterni. Inoltre con più valori possibili invece di due soli, la circuiteria necessaria di TX e RX diventerebbe molto più complessa. Per tutti questi motivi la tensione elettrica viene fatta variare sempre tra soli due possibili valori, che rappresentano il BIT 0 e il BIT 1. Torneremo più avanti a riprendere questo argomento quando parleremo della comunicazione fra due sistemi in modo più dettagliato. Per comprendere meglio le potenzialità del sistema binario dobbiamo ora introdurre un nuovo fondamentale argomento. 7 -L’ALGEBRA BOOLEANA G eorge Boole fu un grande matematico e logico del XIX secolo ed è diventato celebre soprattutto per la formulazione dell’algebra che porta il suo nome. L’algebra di Boole , o booleana, è fondamentale per il trattamento dei dati nell’informatica e nell’elettronica digitale. Fa uso dei numeri binari, che abbiamo visto nel capitolo precedente, e di alcuni operatori logici, che sono delle semplici funzioni di trasformazione. Non preoccuparti è molto più semplice di quanto pensi… In parole povere un operatore logico prende in input (cioè in ingresso) dei BIT e dà in output (cioè in uscita) altri BIT, secondo una particolare regola. Possiamo affermare che ogni operatore logico ha una sua propria regola specifica. Gli operatori logici principali sono tre: NOT , AND , OR. Per rappresentarle si usano i seguenti simboli grafici. Ad esempio la porta logica del NOT è un triangolino che termina con un piccolo cerchio, con un solo ingresso e una sola uscita. Iniziamo col vedere il funzionamento del più semplice, il NOT. Questo operatore riceve in ingresso un BIT, ne calcola l’opposto e lo dà in uscita. Cioè, molto semplicemente, se l’input è 1 l’output è 0 e se l’input è 0 l’output è 1. L’AND (dall’inglese “e” congiunzione) prende in ingresso due o più BIT e, se e solo se sono tutti uguali a 1, dà in uscita 1, negli altri casi darà 0. Nell’esempio di sopra ho due ingressi, se questi sono 0-0, 0-1 oppure 1-0 l’uscita sarà sempre 0. Se gli ingressi sono entrambi uguali a 1 allora l’uscita sarà uguale a 1. Ti ricordo che per i componenti elettronici i BIT 0 e 1 corrispondono a delle tensioni di correnti diverse. L’OR (“o” in inglese), invece, funziona in maniera opposta, cioè l’uscita è uguale a 1 se anche un solo ingresso è pari ad 1, altrimenti, se gli ingressi sono tutti uguali a 0, l’uscita sarà 0. Ogni operatore logico ha, da un punto di vista pratico, la sua equivalente porta logica, cioè un vero e proprio circuito elettronico che realizza la relativa funzione. Nella figura precedente vediamo una porta logica AND. Degli otto connettori, un paio sono gli ingressi, uno l’uscita e gli altri sono per l’alimentazione e controllo. Le tre tabelle che abbiamo visto prima per gli operatori e che descrive il funzionamento di un circuito logico, si chiama tabella della verità ed è un metodo immediato ed efficace per sintetizzare il comportamento di una porta logica o di un circuito. Per capire meglio le porte AND e OR possiamo fare un’analogia e considerare un semplice circuito elettrico formato da una pila, una lampadina e degli interruttori. Una AND a due ingressi è come un circuito con due interruttori in serie, la lampadina si accende (quindi l’output è uguale a 1) se e solo se entrambi gli interruttori sono chiusi, cioè uguali a 1. Se anche uno solo è aperto, la lampadina non si accende (quindi l’output è zero). Lo stesso circuito ma con gli interruttori posizionati in parallelo simula il funzionamento della porta OR. Anche se un solo interruttore è aperto, cioè uguale a zero, la lampadina si accende lo stesso, perché la corrente può fluire dall’altro ramo. La lampadina si spegne (quindi output uguale a zero) se e solo se entrambi gli interruttori sono uguali a 0, cioè aperti. Le porte logiche sono importantissime perché è proprio grazie alla combinazione di centinaia, migliaia o milioni di questi elementi, opportunamente connessi fra loro come fossero mattoncini, sono progettati i circuiti integrati, detti anche chip. Ma queste porte logiche come sono fatte al loro interno? Sono realizzate usando un piccolissimo ma fondamentale elemento: il transistor. Vediamo di che si tratta nel prossimo capitolo. Solo una precisazione, la porta logica rappresentata prima è usata esclusivamente a scopo didattico, in realtà quelle che costituiscono i chip elettronici di un dispositivo digitale sono in realtà molto molto più piccole, addirittura invisibili a occhio nudo. 8 - I MATTONCINI DEI SISTEMI DIGITALI I l transistor è il componente elettronico che più di tutti ha rivoluzionato la storia recente del progresso scientifico e tecnologico. Non a caso i suoi inventori: Brattain, Bardeen e Shockley, furono insigniti del premio Nobel per la fisica nel 1956. Esistono diverse tipologie di transistor ma tutti per funzionare sfruttano le capacità dei semiconduttori, materiali con delle proprietà molto interessanti… Come già saprai in natura esistono i materiali capaci di condurre corrente elettrica, come i metalli e i materiali che al contrario non la conducono come ad esempio la gomma. Esiste però un’altra categoria di materiali che è una via di mezzo fra le due appena citate, i materiali semiconduttori. Un semiconduttore , come si intuisce dal nome, si può comportare sia da conduttore, e quindi far passare la corrente, sia da isolante e bloccarla. Pertanto funzionano proprio come degli interruttori automatici che possono essere di volta in volta accesi o spenti, ovviamente non da una persona esterna, ma in base a un’altra tensione elettrica a cui sono sottoposti. È vero, probabilmente non è un argomento proprio semplicissimo, tuttavia per ora l’importante è sapere che i transistor sono degli interruttori speciali e sono costruiti con dei materiali chiamati semiconduttori. I transistor sono i componenti principali di un qualunque sistema elettronico, sono generalmente realizzati in silicio, un materiale per fortuna molto abbondante sul nostro pianeta. Quindi ricapitoliamo facendo uno zoom, un computer è fatto da schede, le quali sono composte dai circuiti integrati o chip. A loro volta questi funzionano con le porte logiche le quali infine sono realizzate con i transistor. In realtà nei nostri apparati i transistor sono così miniaturizzati che su un singolo chip delle dimensioni di un francobollo ce ne possono essere tranquillamente centinaia di milioni! Al contrario di quello che si potrebbe pensare, un computer è un oggetto fondamentalmente stupido, pertanto chiamarlo cervello elettronico, come talvolta si sente, è davvero impreciso. Un computer, per quanto complesso sia, non può replicare le funzionalità di un cervello umano, almeno fino a oggi. Va bene, potresti obiettare, « ma allora un computer come fa a pensare? » Risposta: il computer non pensa affatto, ma si limita semplicemente a eseguire le istruzioni che noi gli abbiamo fornito. Tutto qui. Queste istruzioni vengono date nell’unico linguaggio che un computer può davvero capire: il linguaggio binario, che consiste in pratica in una lunga sequenza di BIT, zero e uno. Bene, ma come gli forniamo queste istruzioni? Un po’ di pazienza, lo vedremo più avanti quando parleremo di algoritmi. 9 – DENTRO UN MODERNO CALCOLATORE V ediamo ora com’è fatto internamente un calcolatore elettronico. Sebbene la sua architettura possa variare a seconda della particolare specializzazione, possiamo tuttavia individuare i seguenti componenti principali: Il microprocessore La memoria di lavoro La memoria di massa Le periferiche di input e output Il BUS di interconnessione Facciamo uno schema esemplificativo dell’architettura, mettendo ben in evidenza tutte le sue parti, poi le analizzeremo nel dettaglio. Il componente elettronico più importante è senza dubbio il microprocessore (o più semplicemente processore), conosciuto anche come CPU ( Central Processing Unit ). È quel dispositivo che ha il compito di eseguire le istruzioni che riceve sotto forma di sequenze di BIT. Sottolineo che in questo testo i termini CPU, microprocessore e processore sono da considerarsi equivalenti. Le memorie servono invece per conservare i programmi e i dati. Più avanti le vedremo da vicino. Le periferiche di input e di output , invece, sono tutti quei sistemi che permettono di interagire con il computer inserendo, input, delle informazioni, come la tastiera o il mouse, oppure portandole fuori, output, come un monitor o una stampante. Ovviamente tutti questi componenti devono comunicare in qualche modo fra loro, ecco quindi a cosa serve il BUS , che è una sorta di collegamento elettrico. Vediamo ora qualche dettaglio in più sul microprocessore. Abbiamo detto che il suo compito è quello di eseguire le istruzioni, come i calcoli aritmetici. Al suo interno possiamo individuare tre elementi: l’ unità di calcolo , detta anche ALU ( Arithmetic-Logic Unit ), l’ unità di controllo e i registri. L’ALU è il circuito adibito al calcolo vero e proprio, mentre l’unità di controllo si preoccupa di coordinare il flusso dei dati e delle istruzioni all’interno del microprocessore. Inoltre la CPU si avvale di alcuni registri di memoria, questi permettono la memorizzazione temporanea di informazioni, e sono molto veloci. Un’altra caratteristica importante della CPU è il clock. Questo è un segnale periodico, cioè che si ripete sempre uguale nel tempo, costituito da una serie di impulsi. Il suo compito è essenziale, poiché serve a sincronizzare il lavoro della CPU, un po’ come il metronomo scandisce il ritmo del musicista. La CPU, ogni volta che le arriva un impulso di clock, esegue un’istruzione, poi si ferma e aspetta il prossimo segnale di clock, quindi esegue la successiva operazione e così via. È ovvio che più veloce è la frequenza del clock, maggiore saranno le operazioni che la CPU esegue in un certo tempo. Ritornando alla nostra architettura, oltre ai dispositivi di input e output già visti, abbiamo la memoria di lavoro, una memoria che deve essere molto veloce perché la CPU stessa la usa costantemente durante l’esecuzione dei programmi. Quando un computer viene spento, ossia si interrompe l’energia elettrica che lo fa funzionare, la memoria di lavoro perde immediatamente tutto il suo contenuto, come se si svuotasse. Per questo è necessario affiancare sempre una memoria di massa, in genere un disco fisso o hard disk in inglese. Questo è capace, grazie a dei componenti magnetici e meccanici, di mantenere i programmi e i dati elaborati anche quando il computer è spento. Approfondiremo le memorie dal prossimo capitolo. Questa architettura, su cui si basa ancora la maggior parte dei calcolatori odierni, è conosciuta con il nome di Von Neumann, in onore proprio di John Von Neumann, lo scienziato che la ideò nei lontani anni ’40 e che incontreremo più avanti Ritorniamo al nostro componente più importante, la CPU. La velocità del suo clock si misura in hertz , quindi ad esempio 10 hertz sono 10 operazioni elementari al secondo. Va detto, per la precisione, che un ciclo di clock non corrisponde necessariamente a un intero calcolo aritmetico. Per esempio un’addizione per essere completata ha bisogno di qualche impulso di clock, una moltiplicazione, che è già più complessa, un po’ di più. La frequenza delle moderne CPU è talmente elevata che si preferisce ricorrere ai multipli dell’hertz, come i megahertz (milioni di hertz) o i gigahertz (miliardi di hertz). Una moderna CPU Esiste una legge, detta legge di Moore enunciata nel 1965 da Gordon Moore, uno dei fondatori della Intel, la quale afferma che il numero dei transistor che costituisce un microprocessore raddoppia ogni diciotto mesi. Questa previsione si è dimostrata estremamente esatta, tanto che è usata per stabilire gli obiettivi delle aziende di microelettronica di tutto il mondo. Tuttavia oggi questa legge sta diventando sempre meno applicabile. Infatti i processi costruttivi dei circuiti elettronici permettono ormai di raggiungere livelli di miniaturizzazione talmente alti, che a un certo punto non potranno essere più superati per limiti fisici. Più avanti vedremo che, ad ogni modo, esistono altre modalità per aumentare le prestazioni dei microprocessori. 10 - LA MEMORIA NEI CALCOLATORI ELETTRONICI N ell’architettura di Von Neumann la memoria svolge un ruolo fondamentale. Abbiamo visto che la CPU è quel componente elettronico che legge le istruzioni dei programmi e le esegue. Ma non potrebbe mai svolgere questo compito senza l’ausilio della memoria, ossia di uno spazio usato per conservare delle informazioni al fine di poterle poi rileggere. Per informazioni intendiamo sia i dati , sia le istruzioni dei programmi che ne fanno uso. Bene, adesso scendiamo più nel dettaglio per scoprire le principali tipologie di memorie presenti in un calcolatore elettronico. Un moderno calcolatore elettronico è costituito da diversi supporti di memorizzazione. Questi supporti hanno funzioni e caratteristiche differenti. Facciamo prima un elenco gerarchico, successivamente le vedremo più nel dettaglio. Tipicamente si rappresentano come una sorta di piramide. Come già detto l’utilizzatore principale è la CPU, per cui la posizioniamo in cima alla piramide. Partendo dal fondo abbiamo i nastri magnetici , la memoria di massa , la memoria di lavoro , la memoria cache e i registri. Iniziamo da quest’ultimi. I registri non sono altro che delle celle di memoria localizzate in numero limitato nella CPU stessa, la quale li utilizza come appoggio provvisorio per i suoi calcoli. Nello schema della CPU visto in precedenza e composto dall’Arithmentic Logic Unit e dall’Unit Control, si affiancano anche i registri. Questi, essendo costruite sullo stesso chip della CPU, sono estremamente veloci. A un livello più basso abbiamo la cache. Questa è una memoria anch’essa situata vicino alla CPU, per cui è molto veloce. Il suo compito è contenere le informazioni che di volta in volta possono servire alla CPU, ad esempio perché le ha già usate recentemente. Infatti è dimostrato che la CPU ha più probabilità a utilizzare dei dati o delle istruzioni a cui ha fatto riferimento poco tempo prima. Quando il microprocessore deve leggere qualcosa dalla memoria di lavoro, prima cerca tale informazione nella cache, se esiste la prende da lì evitando di usare il BUS e rallentare le operazioni. In caso contrario dovrà necessariamente ricorrere alla memoria di lavoro. Dei moduli di RAM Scendendo di un gradino nella piramide c’è la memoria di lavoro. Il suo importantissimo scopo è quello di cooperare con la CPU mantenendo i programmi in esecuzione e i relativi dati. È fondamentale che la CPU possa accedere a questa memoria in un tempo quanto più possibile basso, affinché non subisca rallentamenti e inefficienze. Proseguendo c’è la memoria di massa. Sicuramente la tipologia principale è costituita dagli hard disk (o dischi fissi), composti, appunto, da diversi dischi magnetici in rotazione e da testine che senza alcun contatto si spostano per accedere alle informazioni. Dispongono di grandi quantità di spazio, ma essendo basate su parti meccaniche, risultano molto più lente delle memorie appena viste. L’interno di un hard disk Oltre agli hard disk ci sono anche ulteriori tipi di memorie di massa che sfruttano differenti tecnologie come i cd, i dvd e le memorie usb. Infine l’ultimo gradino è occupato dalle memorie a nastro. Questi sono dei dispositivi usati dalle grandi aziende che hanno la necessità di archiviare una mole importante di dati. Come dice il nome stesso, i supporti di memorizzazione sono dei nastri magnetici, che offrono una velocità di lettura e scrittura molto bassa. Le informazioni, infatti, vengono memorizzate su un nastro che scorre lentamente sotto una testina. Tuttavia per dei dati a cui si accede raramente può essere una buona soluzione, considerando il loro prezzo relativamente contenuto. Una libreria a nastri magnetici Esistono diversi criteri per classificare le memorie. Uno è sicuramente la modalità di accesso ai dati contenuti. La memoria di lavoro è più conosciuta come RAM random access memory , cioè memoria ad accesso casuale, nel senso di arbitrario. In altre parole è possibile leggere o scrivere un dato, semplicemente conoscendo il suo indirizzo e puntandolo direttamente. Il tempo che la CPU deve attendere non dipende dalla posizione del dato all’interno della RAM. Questo tipo di memorie sono estremamente veloci. I nastri magnetici, invece, sono ad accesso sequenziale, poiché per leggere una particolare informazione è necessario attendere che il nastro scorra sotto la testina fino ad arrivare al punto che si vuole leggere o scrivere. I dischi fissi, invece, appartengono a una tipologia intermedia detta ad accesso diretto, in cui il tempo per accedere al dato memorizzato dipende da quanto si deve spostare la testina di lettura e questo dipende a sua volta da dove era situata fisicamente sul disco il dato precedente. Un’altra importante distinzione la si può fare in base alla permanenza del dato sul dispositivo. I dispositivi come la RAM, la cache e i registri devono essere costantemente alimentati dalla corrente elettrica per poter funzionare. Se questa viene a mancare, anche per pochi secondi, tutto il loro contenuto viene irrimediabilmente perso. Queste sono dette memorie volatili. Si intuisce quindi che le memorie non volatili sono in grado di persistere l’informazione anche quando non sono più alimentate dalla corrente. Un disco fisso o un nastro sono in grado di conservare le informazioni memorizzate al loro interno, anche se vengono disconnesse per molto tempo dalla rete elettrica. Vediamo di seguito uno schema riassuntivo. Rappresentare le tipologie di memoria in una struttura piramidale ci permette di avere alcune ulteriori informazioni. Infatti, partendo dal basso e proseguendo verso la cima, troviamo memorie via via più veloci. Ciò è dovuto principalmente alla tecnologia, ma anche al fatto che in alto ci sono memorie costruite fisicamente vicino alla CPU, quindi con un accesso diretto. Le dimensioni di cui generalmente si dispone sono molto alte per le memorie alla base e sempre più contenute man mano che si sale. Questo è dovuto essenzialmente per i costi molto alti delle memorie più vicine alla CPU. 11 – IL FILE SYSTEM A questo punto probabilmente ti starai chiedendo perché invece di usare diverse tipologie di memoria non si piazzi da qualche parte nel computer un’unica memoria molto capiente da usare per tutto, come una specie di enorme ‘bidone’. Questa idea purtroppo non va bene e il motivo è semplice. Facciamo un parallelo con la vita quotidiana… Immaginiamo di dare uno sguardo nell’ufficio di un impiegato che sta lavorando su un progetto complesso. La sua scrivania è invasa da libri, ricerche, note, quaderni, appunti e scartoffie varie. Potrebbe tenere tutto questo materiale sulla sua piccola scrivania? Probabilmente no, non ci sarebbe neanche lo spazio sufficiente. La soluzione più logica è sicuramente quella di avere sulla scrivania gli elementi più importanti come la rubrica telefonica e degli appunti che usa più frequentemente. Invece alcuni manuali importanti che saltuariamente consulta troverebbero posto in un cassetto della scrivania, insieme a dei quaderni e dei raccoglitori. Infine ha anche bisogno di fare delle ricerche su dei libri, ma siccome ne ricorre raramente, non è necessario che siano posti vicino a lui. Può andare a prenderli nella vicina libreria, portarli sulla sua scrivania per consultarli e, quando finito, riporli dove sono stati prelevati. Nel nostro esempio possiamo immaginare la libreria come l’hard disk, ha infatti molto spazio ed è più lenta nell’accesso (l’impiegato, infatti, deve alzarsi per prendere un libro). I cassetti sono la RAM, ha poco spazio su cui poggiare i documenti, ma permette di avere velocemente tutto vicino, grazie un rapido accesso. La scrivania di lavoro sono la cache e i registri. La quantità di elementi che può contenere è decisamente minore rispetto alla libreria e ai cassetti, ma permette all’impiegato di avere tutto sotto mano, per cui riserverà la sua scrivania per i documenti che usa più spesso. In questo modo i diversi livelli di memoria hanno ciascuno delle funzioni specifiche. Inoltre diversificando le tipologie di memoria, si riesce a contenere in modo significativo i costi totali. Nei capitoli precedenti abbiamo visto le memorie, cosa sono e le loro caratteristiche principali. Abbiamo anche aggiunto che la loro funzione è di conservare le informazioni, al fine di essere recuperate dopo un certo tempo, quando diventerà necessario. La domanda che ti potresti porre a questo punto è: come sono organizzate queste informazioni al loro interno? Disporre di una memoria velocissima e molto capiente sarebbe perfettamente inutile se non esistesse nessun modo per recuperare le informazioni che sono state immesse in precedenza. Sarebbe come possedere un immenso archivio per conservare i nostri documenti, ma non avere alcun modo di sapere dove ciascuno di essi sia stato messo! Per fortuna esiste una soluzione, ma dobbiamo prima introdurre il concetto di file. Puoi immaginare un file come una sorta di contenitore di informazioni. Un file può essere ad esempio un documento oppure una foto, un audio, un video o anche un software. Viene individuato da un nome e da una estensione separate da un punto. L’estensione è generalmente composta da 3 caratteri e ci dà indicazione sulla tipologia del file stesso. Esistono inoltre dei particolari file, chiamati cartelle o directory , che sono come dei contenitori di altri file e vengono usati per avere un ordine gerarchico. Ma ritorniamo ora al problema dell’organizzazione dei dati, che viene gestito da un componente fondamentale: il File System. Un file system è in sostanza un modello di archiviazione dei file su un dispositivo di memorizzazione di massa, come gli hard disk, una struttura possiamo dire. Ad ogni file sono associate diverse proprietà come ad esempio la dimensione, la data di creazione, i permessi di chi può accedervi e la loro posizione fisica sul supporto. Il file system è una parte integrante in un sistema informatico. Puoi immaginarlo come una sorta di mappa per ritrovare tutti i file salvati in memoria. Dal punto di vista di una persona che usa un computer un file è sempre un singolo elemento, ma fisicamente è probabile che questo sia stato ‘spezzettato’ in più parti e memorizzate in diversi punti del supporto. Facciamo un esempio pratico. Consideriamo un’ipotetica porzione di un hard disk, la quale è suddivisa in piccole unità di ugual misura chiamate cluster. Un file su disco può occupare diversi cluster, a seconda della sua dimensione. Supponiamo di avere un primo file che occupa 3 unità, un secondo di 4 unità e gli ultimi due di rispettivamente 2 e 3 cluster. Dopo un certo tempo viene cancellato il secondo file e quindi lo spazio che occupava torna ad essere disponibile. Poco dopo è necessario memorizzare un ulteriore file (FILE X) di dimensione 5 cluster. Il file verrà scritto inizialmente nello spazio vuoto e l’eccedenza andrà a occupare altri cluster, anche se non contigui. Per cui il file risulta scomposto in più parti sparpagliate in punti diversi del disco. Il File System pertanto dovrà necessariamente tenerne conto per accedervi e recuperarlo correttamente. Un File System può essere rappresentato concettualmente come un albero rovesciato. In cima abbiamo la radice (in inglese root ), cioè il punto di partenza, poi abbiamo delle diramazioni, le cartelle. Ogni cartella può contenere a sua volta altre cartelle o file. Pertanto per individuare un file da un punto di vista logico è necessario conoscere il suo percorso ( path ). Ma ricorda che questo è solo un modo logico e ordinato di organizzare il file system, ed è utile all’utente per leggere e scrivere le informazioni, ma che non ha alcuna corrispondenza fisica sul disco, in cui i file sono sparsi e molto spesso, come abbiamo visto, frammentati in più parti. 12 - L’ESECUZIONE DEI PROGRAMMI A questo punto potresti chiederti cosa succede nella CPU durante l’esecuzione di un programma. Bene, a tal proposito riprendiamo per un attimo la struttura di una CPU che avevamo già visto in un capitolo precedente. Abbiamo visto come la CPU sia composta principalmente dall’unità aritmetico-logica, dall’unità di controllo e da diversi registri. Ricapitoliamo quanto già detto in un precedente capitolo. L’unità aritmetico-logica si occupa dell’esecuzione vera e propria delle istruzioni, l’unità di controllo è adibita alla gestione del flusso dei dati mentre i registri hanno il compito di memorizzare temporaneamente le informazioni durante l’esecuzione di un programma. Due di questi registri sono particolarmente importanti durante l’esecuzione di un programma: il primo è l’ Instruction Pointer , abbreviato IP , il quale tiene traccia ogni istante dell’indirizzo di memoria della prossima istruzione del programma da eseguire. L’altro è l’ Instruction Registry o IR che contiene istante per istante l’istruzione vera e propria da eseguire. Vediamo quali sono i passi principali che una CPU compie durante l’esecuzione di un programma. Supponiamo che questo programma si trovi inizialmente sull’hard disk. Per prima cosa viene copiato dall’hard disk alla RAM, più precisamente in una zona riservata alle sole istruzioni, mentre un’altra porzione sarà riservata esclusivamente ai dati da elaborare. Ricordiamo che un programma è un insieme di istruzioni da eseguire. Queste istruzioni dovranno essere di volta in volta copiate dalla RAM alla CPU per essere eseguite. Ci sono pertanto tre fasi ben distinte: la lettura dell’istruzione (in inglese conosciuta come fetch ), la sua decodifica ( decode ) e infine l’esecuzione ( execute ). Ma affinché un programma venga eseguito è necessario caricare le sue istruzioni dalla RAM, una dopo l’altra, all’interno della CPU che potrà così eseguirle una alla volta. Il tutto avviene in 3 fasi distinte. La prima fase è la lettura dell’istruzione. È l’Instruction Pointer che indica nella RAM qual è l’istruzione da eseguire. Pertanto questa viene trasferita all’interno della CPU e più precisamente nell’Instruction Registry. Contemporaneamente il valore dell’Instruction Pointer viene incrementato di uno affinché la CPU possa puntare all’istruzione successiva. La seconda fase è la decodifica, ossia la decomposizione dell’istruzione in singole parti, ad opera dell’unità di controllo. Nell’ultima fase l’istruzione viene finalmente eseguita dai circuiti della CPU, ricorrendo se occorre all’unità aritmetico-logica. Se l’istruzione richiede di leggere o scrivere dei dati nella RAM, la CPU accederà alla memoria per recuperarli o memorizzarli. Va detto, che nella realtà intervengono tanti altri dettagli e anche molto complessi spesso brevettate dalle case produttrici, ma in sostanza la CPU per eseguire una qualsiasi operazione deve sempre eseguire in ordine le tre fasi: lettura, decodifica e scrittura. Intel Pentium Pro, una CPU di fascia alta del 1995 creative commons – credit: [email protected] credit: [email protected] 13 - LE ARCHITETTURE PARALLELE I n un capitolo precedente abbiamo descritto la CPU. Si è visto che per funzionare ha bisogno del clock, ossia un segnale sempre uguale nel tempo, che serve a scandire le sue operazioni. Approfondiamo il tema… Qualsiasi microprocessore per poter funzionare correttamente ha bisogno del segnale di clock, immaginalo come uno strumento per dagli il tempo, potremmo dire il ritmo. Non a caso infatti clock in inglese vuol dire orologio. È facile intuire che se aumentassimo la frequenza del clock, la CPU riuscirebbe a eseguire un maggior numero di operazioni nello stesso intervallo di tempo. Prendiamo come riferimento un secondo e supponiamo che la CPU effettui una operazione ogni volta che il segnale del clock sia al suo massimo, e invece aspetti nel resto del tempo. Si vede nel primo grafico. Consideriamo il seguente diagramma temporale: La CPU eseguirà pertanto 3 operazioni al secondo. Ora supponiamo di aumentare la frequenza del clock. Nel secondo caso la CPU eseguirà 6 operazioni a secondo, nel terzo ne eseguirà 12. Piccola prima curiosità, anche se 1 hertz, cioè un’operazione al secondo è ridicola oggi, una tale velocità era quella che avevano realmente i primi calcolatori elettromeccanici a cavallo fra gli anni ’30 e gli anni ’40. Seconda piccola curiosità, se ti stai chiedendo in che modo sia possibile inviare un segnale così regolare e preciso come il clock, la risposta è in un particolare minerale usato anche per sincronizzare gli orologi: il quarzo, il quale ha la caratteristica di vibrare grazie alla sua proprietà di risonanza meccanica. Un oscillatore al quarzo Tuttavia aumentare il valore del clock indefinitamente è possibile solo in teoria, ma in pratica c’è un limite, sia per un problema di tecnologia costruttiva dei circuiti digitali, sia perché a frequenze sempre più elevate corrispondono temperature sempre più alte. Infatti una CPU sotto sforzo si surriscalda velocemente, al punto che fonderebbe come un panetto di burro in pochi secondi se non venisse opportunamente raffreddata con ventole e dissipatori termici. Non possiamo proprio ignorare queste conseguenze. Quindi, qual è la strada per migliorare le prestazioni di un calcolatore, oltre ad aumentare il clock del microprocessore? In realtà c’è un’altra strada… facciamo un esempio. Supponiamo che io debba imbiancare una grande stanza. Nonostante non sia del mestiere è un lavoro che sono capace di fare ma so già per certo che impiegherò non meno di sei ore. Se volessi impiegare meno tempo potrebbe essere una buona idea farmi aiutare da un generoso amico, in questo modo potrei finire di imbiancare tutta la stanza in circa cinque ore. Probabilmente con un’altra persona a darmi una mano, ci vorrebbero quattro ore. Tornando al nostro calcolatore, il concetto rimane lo stesso. Per completare prima l’esecuzione di un programma devo usare più microprocessori che lavorino in parallelo ciascuno su diverse parti del programma iniziale. Evidentemente prima che le CPU lavorino sulla loro parte, è necessario che un gestore suddivida il programma e ne assegni loro le varie parti. Per chiarire meglio, supponiamo di avere un problema iniziale da risolvere, ad esempio dei calcoli matematici e supponiamo anche che questo problema possa essere suddiviso in due parti. Normalmente in un’architettura mono-processore le due parti del problema iniziale verrebbero eseguite una dopo l’altra dall’unica CPU. In un sistema multiprocessore abbiamo una situazione diversa, ipotizziamo di avere nel nostro caso due CPU fra loro identiche, come nello schema. Le due parti del problema verranno assegnate una per ciascuna CPU. Dopodiché le CPU risolveranno la loro parte del problema in contemporanea e produrranno ciascuna le rispettive soluzioni parziali. Infine queste due parti verranno aggregate fra loro per comporre la soluzione finale e definitiva del problema. A questo punto ci potremmo fare le seguenti domande: Primo -> fino a che punto è possibile parallelizzare la soluzione di un problema? Secondo -> che succede alla velocità di esecuzione di un programma se aggiungo più CPU al mio sistema? Terzo -> per rendere più veloce l’esecuzione di un intero programma quale delle sue parti mi conviene migliorare? Per avere delle risposte è doveroso chiamare in causa l’informatico e ricercatore statunitense Gene Amdahl. Egli ha dimostrato che il grado di parallelizzazione di un programma complesso dipende da come è scritto il programma stesso e non dal numero di processori del sistema di calcolo. Da questa legge derivano le risposte alle precedenti domande. Fino a che punto è possibile parallelizzare la soluzione di un problema? Il grado di parallelizzazione non può essere infinito. In altre parole se scomponiamo un problema in parti elementari, arriveremo ad un punto in cui non potremmo più scomporlo, oppure non avremo alcun vantaggio a farlo. Per chiarire facciamo un banale esempio. Consideriamo la seguente operazione aritmetica F=(10+20)x(30+40). Se avessi una sola CPU la soluzione sarebbe: 1. Prima attività: la CPU esegue la somma 10+20 e salva il risultato da parte. 2. Seconda attività: la CPU esegue la somma 30+40 e salva anche questo risultato da parte. 3. Terza attività: la CPU esegue il prodotto delle precedenti somme e restituisce 2100. Abbiamo una sola CPU, pertanto dobbiamo fare tutto solo con essa. Se invece avessi 2 CPU lo scenario sarebbe diverso: 1. Prima attività: le CPU1 e CPU2 eseguono nello stesso istante rispettivamente le somme 10+20 e 30+40 e i risultati salvati in uno spazio temporaneo. 2. Seconda attività: una delle due CPU, ad esempio la prima esegue il prodotto AxB. che, come prima, è uguale a 2100. Quindi con 2 CPU ho ottenuto il medesimo risultato più velocemente, cioè in due passi piuttosto che tre. Anche se l’esempio è molto semplice, dimostra come possono essere parallelizzate le operazioni in modo opportuno. Ma a questo punto sorge una domanda: è possibile parallelizzare ulteriormente la procedura per calcolare il risultato finale? La risposta è negativa, infatti non posso eseguire anche la moltiplicazione nel passo 1, poiché per eseguirla ho bisogno delle due somme parziali, quindi per iniziare la moltiplicazione si dovrà necessariamente attendere la loro esecuzione. Da questa considerazione deriva una seconda domanda: Di quanto aumenterebbe la velocità di esecuzione se aggiungessi una terza CPU? Evidentemente di zero, poiché una CPU aggiuntiva, per questo problema non verrebbe nemmeno usata. Anzi probabilmente rallenterebbe il tutto considerando che ho più componenti da gestire. Il succo del discorso è che è impossibile parallelizzare il 100% delle istruzioni, poiché alcune di esse dipendono da altre precedenti che devono essere necessariamente completate prima di andare avanti. Che succede alla velocità di esecuzione di un programma se aggiungo CPU al mio sistema? Elaboratori multiprocessore della IBM creative commons – credit: [email protected] Lo abbiamo appena detto, si arriverà a un punto in cui l’aggiunta di più CPU non apporterebbe alcun beneficio. Pertanto la velocità di esecuzione di un programma non cresce linearmente con l’aumentare del numero di processori, ma tenderà prima o poi ad assestarsi. Infine l’ultima domanda: Per rendere più veloce l’esecuzione di un intero programma quale delle sue parti mi conviene migliorare? Qui Amdahl afferma che il miglioramento che si ottiene su una parte del sistema è proporzionale al tempo in cui tale attività è eseguita. Ma questo che vuol dire? Semplicemente che in genere conviene concentraci a ridurre il tempo di esecuzione di quelle funzioni che sono usate più spesso in un software. Infatti se ci fai caso un qualsiasi software propone agli utenti molteplici funzionalità. Prendiamo a titolo di esempio un programma di videoscrittura e alcune delle sue innumerevoli funzioni come aprire un file, salvarlo, inserire un grafico, creare un disegno, usare il correttore ortografico e stampare su carta. Alcune di queste funzioni sono più utilizzate di altre, ad esempio il salvataggio del file è una operazione che l’utente esegue molto più frequentemente della ricerca di errori all’interno del documento. Amdahl ci dice che per rendere più efficiente il software da un punto di vista dell’utente bisogna concentrare il nostro lavoro sulle funzioni che hanno maggior probabilità di essere usate più a lungo dall’utente all’interno del programma. Ricapitolando, un sistema multiprocessore ha gli indubbi vantaggi di velocizzare l’esecuzione del software e di rendere più affidabile il sistema nel suo complesso. Questo perché il danneggiamento di una sua parte non va ad interrompere il lavoro che prosegue anche se in maniera deteriorata. Ma porta anche diversi svantaggi, o comunque, degli aspetti da tenere in conto, quali, una maggiore complessità dei circuiti elettronici, infatti è necessario un livello in più che gestisca il lavoro delle CPU, smistando ad esse le istruzioni. Una scrittura del software che deve tener in conto della presenza di più processori e infine un maggior uso di corrente elettrica e produzione di calore. Ovviamente si può estendere il concetto anche ad altre parti di un calcolatore elettronico, come gli hard disk, la memoria RAM, ecc., fino a interi computer connessi fra loro a costituire quello che si definisce sistema distribuito. Attualmente il più celebre progetto di sistema distribuito in funzione è il SETI@home che fa parte dell’ambizioso programma SETI ( Search for Extra-Terrestrial Intelligence ) per la ricerca di forme di vita nell’universo. Questo progetto venne iniziato nel maggio del 1990 presso l'Università di Berkeley. L'esistenza di questo progetto significa che chiunque può essere coinvolto nella ricerca, semplicemente scaricando da Internet un software. Oltre 5 milioni di computer in centinaia di nazioni offrono gratuitamente la loro capacità computazionale per analizzare delle piccole porzioni di dati inviati loro dalle sonde centrali, per poi restituirne i risultati. PARTE TERZA ELABORAZIONE DELLE INFORMAZIONI 14 - IL CONCETTO DI INFORMAZIONE A rrivati a questo punto ti invito a prestare particolare attenzione, perché i concetti qui esposti sono fondamentali. Se ricordi bene in precedenza abbiamo provato a dare una forma e un significato alla parola informatica, ricordi? l’informatica è la scienza che si occupa del trattamento dell’informazione mediante procedure automatiche e con l’ausilio di calcolatori elettronici. La parola chiave è proprio informazione , ed è necessario capire molto bene cosa sia, perché su di essa si basa il concetto stesso di informatica. Per comprendere cos’è l’informazione facciamo un esempio: Consideriamo un comune dado e supponiamo di lanciarlo su un tavolo. Quando terminerà di rotolare m mostrerà una faccia. So già che ho sei possibili risultati. Però fintanto che il dado rotola sul tavolo io ho un’ incertezza , poiché ancora non conosco l’esito dell’evento. Dopo poco il dado smette di rotolare e si ferma, esce un numero ben definito, ad esempio il 2. In questo momento la situazione cambia per me poiché conosco il numero che è uscito, cioè ho una certezza. Ecco, posso dire che ho ricevuto un’informazione. Quindi possiamo affermare che, dato un evento in cui ci siano almeno due possibili risultati, l’informazione è ‘quel qualcosa’ che trasforma un’incertezza in una certezza o, analogamente, l’ignoto nel noto. Se adesso è un po’ più chiaro, facciamo un altro piccolo passo in avanti. Supponiamo che Luca incontri Anna e le dica «Ciao Anna, ti devo dire una cosa: lo sai che domani la Luna continuerà a girare attorno alla Terra». A questo punto Anna, oltre a dubitare seriamente della sanità mentale del suo amico, penserà che dopotutto lui non le abbia dato nessuna informazione rilevante, poiché è praticamente certo che la Luna continuerà a seguire la sua orbita attorno al nostro pianeta anche il giorno successivo. In termini probabilistici Luca ha dato un’informazione molto bassa, perché l’evento di cui parla (domani la Luna girerà attorno alla Terra), ha un’altissima probabilità che si verifichi. A questo punto Anna per risollevare il livello della conversazione gli confida un’incredibile verità «Sai? Ho appena visto le previsioni meteo e domani sicuramente nevicherà in città». Il suo amico rimane molto stupito di sentire questo perché in fondo sono in un caldissimo agosto. Anna in questo caso gli ha fornito un’informazione estremamente alta, perché, la probabilità che accada quanto detto, cioè che nevichi in piena estate, è statisticamente bassissima. Pertanto possiamo affermare che la quantità di informazione è legata alla probabilità: più un evento è probabile che si verifichi, meno informazione porta con sé, viceversa, meno un evento è probabile che si verifichi più informazione contiene. Come già sappiamo un BIT può assumere solo due possibili valori, lo zero e l’uno. In una generica situazione pertanto un BIT potrà essere uguale a zero con una probabilità del 50% e uguale a uno sempre con una probabilità del 50%. Ciò significa che un BIT può assumere due valori equiprobabili. Questo vuol dire che se ho un evento con due possibili risultati aventi uguale probabilità di verificarsi, l’esito di tale evento produrrà un’informazione di 1 BIT. Queste considerazioni ci portano alla seguente affermazione: Il BIT è l’unità di misura dell’informazione. Proprio come il litro lo è del volume o il secondo del tempo. Il BIT è definito come quella quantità di informazione che si ha al verificarsi di un evento, il quale ha due possibili risultati aventi uguale probabilità di verificarsi. Per chiarire facciamo subito un paio di esempi. Supponiamo di avere un sacchetto contenente due sfere, una gialla e una rossa e di estrarne una a caso. Il risultato dell’evento ‘estrazione sfera dal sacchetto’, corrisponde a un’informazione esatta di un BIT, poiché le due possibilità hanno la stessa probabilità di verificarsi. Identico discorso vale per il lancio di una moneta, sapere che è uscita testa o croce è ancora un’informazione di un BIT. Ma cosa succede se invece ho un evento che ha più di due possibili esiti? Prendiamo ancora il lancio di un dado. Sappiamo che possono uscire 6 valori. Bene, ma questi 6 valori li posso rappresentare tutti con un solo BIT? Ovviamente no, con un BIT posso rappresentare solo i primi due risultati e non di più. Dunque come faccio? La soluzione è semplice: uso più BIT per ogni risultato. Vediamo quanti ne occorrono, facciamo un tentativo con due BIT. Come ci accorgiamo subito con 2 BIT posso rappresentare fino a 4 valori. Per scoprirlo vediamo tutte le combinazioni che posso ottenere: Numero 1 primo BIT = 0 secondo BIT = 0 Numero 2 primo BIT = 0 secondo BIT = 1 Numero 3 primo BIT = 1 secondo BIT = 0 Numero 4 primo BIT = 1 secondo BIT = 1 Ho quattro possibili combinazioni, non sono sufficienti, a noi ne servono sei, per cui proviamo ad aggiungere un altro BIT. Con tre BIT riusciamo finalmente a raggiungere otto possibili combinazioni. A noi ne sono sufficienti sei, quindi gli ultimi due non verranno usati. Numero 1 primo BIT = 0 secondo BIT = 0 terzo BIT = 0 Numero 2 primo BIT = 0 secondo BIT = 0 terzo BIT = 1 Numero 3 primo BIT = 0 secondo BIT = 1 terzo BIT = 0 Numero 4 primo BIT = 0 secondo BIT = 1 terzo BIT = 1 Numero 5 primo BIT = 1 secondo BIT = 0 terzo BIT = 0 Numero 6 primo BIT = 1 secondo BIT = 0 terzo BIT = 1 Non usato primo BIT = 1 secondo BIT = 1 terzo BIT = 0 Non usato primo BIT = 1 secondo BIT = 1 terzo BIT = 1 Quello che abbiamo appena fatto è creare un codice. Codificare vuol dire associare dei BIT a dei valori, come delle cifre decimali, delle lettere o le facce di un dado. Più grande è il numero di simboli che vogliamo codificare, più BIT mi serviranno. Quindi se conoscere il colore della pallina estratta nell’esempio precedente o la faccia di una moneta equivaleva a un’informazione di un BIT, conoscere la faccia di un dado equivale a ottenere un’informazione di tre BIT. Prendiamo adesso la tastiera di un PC, ci sono lettere, cifre, segni di punteggiatura e simboli speciali come la chiocciolina o l’asterisco. Quanti BIT sono necessari per codificare tutto questo insieme? Tre BIT sono troppo pochi, mi basterebbero solo per otto, come abbiamo appena visto nell’esempio del dado. Per questa codifica venne introdotto negli anni 60 il codice internazionale ASCII (pronuncia ‘ aski ’), che sta per American Standard Code for Information Interchange. Questo codice utilizza 7 BIT per la codifica di tutti gli elementi che ho descritto. Vediamo di seguito alcuni esempi del codice ASCII: A 1000001 B 1000010 a 1100001 z 1111011 1 0110001 2 0110010 ; 0111011 ! 0100001 $ 0100100 @ 1000000 Con sette BIT posso ottenere ben 128 possibili combinazioni, a ognuna delle quali è associato un elemento diverso. Questa codifica è riconosciuta in tutto il mondo e fa sì che un software eseguito sul mio computer possa dialogare correttamente con un altro software eseguito da un computer in un’altra parte del mondo, senza il rischio che possa avvenire un’interpretazione errata. 15 – QUANTO PESA L’INFORMAZIONE? A bbiamo visto come il BIT sia l’unità di misura dell’informazione, esattamente come può essere il litro per i volumi e il chilo per il peso. A dire il vero, molto spesso nelle applicazioni pratiche il BIT è un’unità di misura troppo piccola e quindi poco pratica da usare. Sarebbe come usare il metro per esprimere le distanze fra continenti. Pertanto quello che si fa è semplicemente ricorre ai suoi multipli, proprio come per qualsiasi altra unità di misura. Il multiplo più importante è il byte. Un byte equivale a 8 BIT. 1 byte = 8 BIT Da questo punto in poi i multipli crescono di mille in mille e prendono i seguenti nomi: 1 chilobyte = mille byte 1 megabyte = mille chilobyte 1 gigabyte = mille megabyte 1 terabyte = mille gigabyte 1 petabyte = mille terabyte ecc. Tuttavia c’è da dire che quando ci riferiamo a unità di misure comunemente usate, come il litro o il metro, riusciamo bene o male ad avere un’idea della quantità espressa. Tutti abbiamo percezione di quanto sia un litro di acqua, oppure a che quantità corrispondono due kili di pane. Invece per l’informazione è generalmente più difficile averne un’idea, specialmente se non abbiamo molta familiarità. Proviamo con la fantasia a fare delle analogie per capire meglio le proporzioni. Per far questo proviamo a paragonare l’informazione con il peso di alcuni oggetti. Prendiamo 1 BIT e supponiamo che corrisponda a una moneta da 1 Euro, come peso. Bene, pertanto un Byte, che sono otto monete da un euro, avrà un peso corrispondente più o meno a un comune mouse. Il multiplo superiore è il chilobyte, cioè 1000 byte, che peserebbe, secondo le proporzioni rispetto al peso di un BIT, quanto un bel cagnolone grande. Andando avanti troviamo il megabyte, che sarebbe composto da un milione di monete da un euro, il cui peso è paragonabile alla stazza del vagone di un treno. Salendo, un gigabyte in proporzione avrebbe il peso di una portaerei. I numeri si stanno facendo importanti. A questo punto un terabyte ha un peso di mille volte quello della portaerei di prima e potrebbe essere ad esempio un enorme iceberg artico. Infine un petabyte avrebbe un peso enorme, per darti l’idea immaginalo come un grande asteroide! Questo era un esperimento divertente che ci fa rendere l’idea di queste grandezze e di come, magari, le stimiamo incorrettamente. Ma da un punto di vista di quantità di informazione che memorizzata a cosa corrisponderebbero questi multipli? Facciamo anche qui degli esempi e vediamo l’informazione che corrisponde a ciascun multiplo. 1 BIT = testa o croce 1 byte = un carattere della tastiera 1 kilobyte = una pagina di testo 1 megabyte = una fotografia di media qualità 1 gigabyte = un film di 2 ore 1 terabyte = 250 mila brani musicali 1 terabyte = 500 miliardi di pagine di testo E dopo il petabyte cosa c’è? Ci sono altri multipli, sempre di mille in mille, ma sono molto difficili da raggiungere. Ad esempio mille petabyte sono un exabyte. Difficile rendere l’idea di questa enorme mole di dati. Si stima, tanto per fare un parallelo grossolano, che un exabyte sia la quantità di dati prodotta dal genere umano ogni sei mesi. Bene, dal prossimo capitolo cambieremo argomento e parleremo di algoritmi e software. 16 - GLI ALGORITMI N ei capitoli precedenti abbiamo visto come l’informatica sia un campo molto vasto e trovarne una definizione univoca è difficile. Ci abbiamo provato all’inizio affermando che l’informatica tratta le informazioni mediante elaboratori elettronici. E abbiamo anche visto che cosa consideriamo per informazione. Tuttavia se ci astraiamo ad un livello più alto, possiamo anche dare la seguente definizione: l’informatica è quella scienza che studia gli algoritmi, le loro caratteristiche e le loro implementazioni in sistemi elettronici. Facciamo subito luce sulla parola chiave di questa seconda definizione: algoritmo. Un algoritmo è semplicemente un insieme finito di passi che ha un inizio e una fine. Puoi immaginarlo come una strada che viene percorsa per raggiungere un obiettivo finale. È pensato e scritto allo scopo di raggiungere il risultato che vogliamo, cioè la soluzione a un nostro problema ed è un concetto cardine nello sviluppo del software. Il termine algoritmo nacque più di mille anni fa e porta il nome del matematico arabo Al–Khwarizmi che per primo fece riferimento a questo costrutto in un suo libro. Tuttavia un algoritmo da solo non è molto utile, infatti è necessario qualcosa che sia in grado poi di compiere effettivamente questi passi. In termini generali si parla di esecutore , un’entità capace di interpretare le istruzioni dell’algoritmo e attuarle. Si dice quindi che l’esecutore esegue l’algoritmo. Avrai già capito quindi che in informatica gli algoritmi sono i programmi o software, mentre gli esecutori sono quei dispositivi elettronici che li eseguono, come il computer, un tablet o un cellulare. Capito che cos’è un algoritmo dobbiamo precisare che, qualsiasi algoritmo deve sempre rispettare le seguenti proprietà fondamentali: ATOMICITÀ: i passi che compongono devono essere ‘elementari’, cioè non più ulteriormente scomponibili in altri sotto-passi. FINITEZZA: l'algoritmo deve essere composto da un numero finito di passi e richiedere una quantità finita di dati in input NON AMBIGUITÀ: i passi costituenti devono essere interpretabili in modo univoco dall'esecutore, sia esso umano o artificiale TERMINAZIONE: l'esecuzione deve avere termine dopo un tempo finito EFFETTIVITÀ: l'esecuzione deve portare a un risultato univoco Bene, vediamo adesso un esempio molto semplice di algoritmo. Immaginiamo di trovarci in un supermercato per fare la nostra solita spesa. Quello che ogni volta svolgiamo, anche se non ce ne rendiamo effettivamente conto, è un algoritmo. Proviamo a modellare la soluzione al problema ‘Fare la spesa’. I passi potrebbero essere: 1) Passo uno - Leggo la lista della spesa 2) Passo due - Cerco i prodotti da mettere nel carrello 3) Passo tre - Vado alla cassa e pago 4) Passo quattro - Esco con la spesa Quello che abbiamo schematizzato è un algoritmo formato dai 4 passi individuati. L’esecutore che avrà il compito di attuarlo è, ovviamente, un essere umano. Ma andiamo avanti, questi quattro passi possono essere a loro volta scomposti in attività più elementari, vediamo come: 1) Prendo il carrello 2) Leggo dalla lista della spesa qual è il successivo prodotto 3) Cerco il prodotto sugli scaffali 4) Se lo trovo lo metto nel carrello 5) Ripeto i punti 2, 3 e 4 finché non termino la lista della spesa 6) Vado alla cassa e pago la spesa 7) Se ho diritto al resto lo prendo 8) Esco dal supermercato con la spesa Questo processo di scomposizione può essere ripetuto ancora, fino a quando non riteniamo di aver raggiunto un dettaglio sufficiente. Ora, però, facciamo un piccolo salto in avanti e proviamo a tradurre l’algoritmo finale da una forma discorsiva a una più strutturata e non ambigua. L’algoritmo inizia con la ricerca del primo prodotto sulla lista della spesa e se presente sugli scaffali del supermercato andrà messo nel carrello. Poi si prosegue con tutti gli altri prodotti fintanto che la lista non sarà esaurita. Quindi si va alla cassa per pagare la spesa e ritirare eventualmente il resto. Questo schema che segue è chiamato anche diagramma di flusso ed è una forma grafica di un algoritmo. È abbastanza intuitivo da interpretare, si parte dal blocco Inizio e lo si scorre nel senso delle frecce. A volte capita che secondo un valore o una scelta, si debba seguire una strada piuttosto che un’altra. Questa situazione è rappresentata con un rombo da cui partono due o più possibili ramificazioni. Ad esempio il blocco ‘Ci sono altri prodotti sulla lista?’ può avere solo e soltanto due diramazioni, una che corrisponde al Sì e l’altra al No. Se la risposta è positiva, bisogna cercare il prodotto, altrimenti vuol dire che la spesa è finita. Un’altra esigenza che capita spesso è il dover ripetere più volte delle istruzioni in modo ciclico, fino a che non si verifica una particolare condizione. Nel nostro esempio, la ricerca dei prodotti da acquistare è una cosa che dobbiamo fare più volte, finché non abbiamo usato tutta la lista della spesa. Questo ciclo è rappresentato da una freccia che ritorna alla condizione da verificare ‘Ci sono altri prodotti sulla lista?’. Ovviamente la nostra soluzione è una versione semplificata, infatti non sono state tenute in conto altre possibili situazioni, per esempio potrei voler sostituire un prodotto esaurito con un altro simile o voler pagare con la carta di credito. Un buon algoritmo deve prevedere sempre tutti i possibili casi che possono presentarsi. Esiste un teorema, enunciato nel 1966 e conosciuto col nome di teorema di Böhm-Jacopini, il quale afferma che è possibile implementare un qualsiasi algoritmo per la soluzione di un problema, usando soltanto tre strutture: la sequenza , la selezione e il ciclo. Vediamoli da vicino. La sequenza è una successione di operazioni da eseguire in rigoroso ordine una dopo l’altra. Ad esempio per rifornire l’auto di benzina è necessario prima recarsi ad un distributore, poi riempire il serbatoio e infine pagare. Non posso invertire l’ordine di questi passi. Nella selezione viene valutato un predicato P, cioè un’affermazione, che può essere o vera o falsa e dipendentemente da questa valutazione, l’esecuzione proseguirà in una direzione piuttosto che nell’altra. Un esempio di predicato può essere il seguente: P=’Sta piovendo’. Questa può essere vera o falsa. Se è vera allora prendi l’ombrello, altrimenti prendi gli occhiali da sole. Il ciclo (o iterazione) è utile quando si ha la necessità di rieseguire più volte gli stessi passi. Si ricorre anche qui a un predicato P il quale, a seconda che sia vero o falso, permette di rieseguire il ciclo o uscirne fuori. Ad esempio se P fosse ‘E’ completata la stampa del documento?’ il ciclo si ripeterebbe in caso di risposta negativa, con l’operazione di stampa della pagina successiva. In caso contrario si uscirebbe dal ciclo. Il predicato P da valutare può essere posto sia all’inizio del ciclo, sia alla fine. Se questo predicato risulta soddisfatto si prosegue alla prossima istruzione, altrimenti verranno ripetute le operazioni del ciclo. Bene, sperando che tutto questo ti sia più chiaro, facciamo ancora un esempio di algoritmo, ma questa volta l’esecutore sarà un computer. Supponiamo di voler scrivere un programma per eseguire delle operazioni aritmetiche, come una semplice calcolatrice. Limitiamoci per ora alle sole quattro operazioni fondamentali applicate a soli numeri che l’utente sceglierà durante l’utilizzo del programma. La nostra calcolatrice dovrà funzionare nel seguente modo: 1) Chiedere che operazione si vuole fare: addizione, sottrazione, moltiplicazione o divisione 2) Richiedere due valori in ingresso 3) Effettuare l’operazione scelta 4) Mostrare all’utente il risultato Fin qui sembra facile. Bisogna però farsi una domanda: quando l’utente che usa il programma inserirà i due numeri, questi dove saranno messi? Per rispondere dobbiamo introdurre il fondamentale concetto di variabile. Puoi immaginare una variabile come una scatola al cui interno puoi conservare un dato. Pertanto una variabile può essere scritta o anche letta, il che equivale a inserire in essa un dato oppure a recuperarlo per vederne il contenuto. Da un punto di vista fisico una variabile non è altro che un registro o una locazione di memoria in cache o in RAM. Per definire una variabile sono necessarie due cose: un nome e il tipo di dato che vogliamo debba contenere. Tornando al nostro esempio, quante variabili ci serviranno? Se analizziamo bene il problema ce ne vorranno almeno 4. Due variabili serviranno per memorizzare i numeri inseriti dall’utente, un’altra per il tipo di operazione aritmetica e una quarta per il risultato finale. Queste variabili che tipi di dato conterranno? I due valori dati in input saranno dei numeri decimali, l’operazione da eseguire è un input di tipo stringa quello in output potranno essere numeri decimali. L’operazione da eseguire, che è sempre un input, sarà di tipo stringa. Una stringa è in sostanza un insieme di caratteri, numeri e simboli. L’output sarà di nuovo un valore numerico decimale. Ora proviamo a vedere quali possono essere i passi logici dell’algoritmo: 1) Definisco le variabili numero1 , numero2 , risultato di tipo numero decimale e operazione di tipo stringa 2) Chiedo all’utente che operazione vuole fare 3) Memorizzo la sua scelta nella variabile operazione 4) Chiedo all’utente il primo numero 5) Lo memorizzo nella variabile numero1 6) Chiedo all’utente il secondo numero 7) Lo memorizzo nella variabile numero2 8) Effettuo l’operazione richiesta 9) Metto il risultato nella variabile risultato 10) Visualizzo all’utente la variabile risultato Quest’algoritmo può essere senz’altro migliorato e ottimizzato, ad esempio bisogna evitare che l’utente per sbaglio inserisca delle lettere o dei valori non congrui. Tuttavia diciamo che per il nostro scopo va più che bene. Ricorda che quasi sempre non esiste solo una singola soluzione al problema, anzi, spesso esistono più strade per raggiungere il nostro obiettivo. Nella prossima pagina possiamo vedere il relativo diagramma di flusso. 17 - LA SCRITTURA DI UN PROGRAMMA N el capitolo precedente abbiamo costruito un algoritmo per descrivere un semplice problema. Benissimo, ma adesso da questo algoritmo come possiamo ottenere un programma? Un programma, come ti ho già anticipato, è un insieme di istruzioni che un calcolatore elettronico esegue per trovare la soluzione a un problema. Per rendere l’idea possiamo dire che un programma è la traduzione di un algoritmo in un linguaggio più comprensibile per un calcolatore elettronico, che poi dovrà eseguirlo. Approfondiremo meglio questo aspetto più avanti. Per ora focalizziamoci su come tradurre l’algoritmo dell’esempio precedente in un programma da far eseguire poi a un computer. Nella prima parte vengono definite tutte le variabili che saranno usate nel programma. In questo modo verranno predisposte le locazioni di memoria necessarie per memorizzarle. A questo punto vengono richieste in input le informazioni all’utente: i due numeri e il tipo di operazione aritmetica. Immediatamente dopo inizia la fase di elaborazione del risultato e finalmente la restituzione in output all’utente. In questo semplice esercizio sono ben evidenti i blocchi che costituiscono il programma: per prima cosa abbiamo la definizione delle variabili, poi La fase di input, la fase di elaborazione e la fase di output. INIZIO *** Definizione variabili *** { numero1 : decimale; numero2 : decimale; operazione : stringa; risultato : decimale;} *** Elaborazione *** scrivi (“Che operazione vuoi fare?”) → operazione ; scrivi (“Inserisci il primo numero”) → numero1 ; scrivi (“Inserisci il secondo numero”) → numero2 ; se operazione = “addizione” allora risultato = numero1 + numero2 ; altrimenti se operazione = “sottrazione” allora risultato = numero1 - numero2 ; altrimenti se operazione = “moltiplicazione” allora risultato = numero1 x numero2 ; altrimenti risultato = numero1 / numero2 ; *** Visualizzazione risultato *** scrivi (“Il risultato è uguale a: ”); scrivi risultato ; FINE In questo esempio abbiamo utilizzato un linguaggio fittizio a scopo puramente di esempio. Più avanti entreremo nel dettaglio dei linguaggi di programmazione. Vediamo in dettaglio il significato di alcuni passaggi. Le istruzioni: scrivi (“Che operazione vuoi fare?”) → operazione ; scrivi (“Inserisci il primo numero”) → numero1 ; scrivi (“Inserisci il secondo numero”) → numero2 ; Nella fase di input, in particolare, vengono mostrati all’utente dei messaggi per invitarlo a inserire i dati. Questi verranno memorizzati nelle variabili dichiarate precedentemente. Si parte dall’analisi del problema che stiamo affrontando: ‘che cosa voglio ottenere?’. Poi si pensa a una soluzione: ‘ come posso ottenerlo?’. Generalmente la prima cosa da fare è modellare questa soluzione con l’ausilio di diagrammi come quelli di flusso. Questi modelli vengono via via sempre più raffinati, affrontando ogni volta più dettagli possibili. Solo come ultima fase c’è lo sviluppo del programma vero e proprio, detto codice sorgente. Per scriverlo abbiamo a disposizione un gran numero di linguaggi di programmazione. Ma quanti tipi di software esistono? Fondamentalmente ci sono due grandi categorie, i software applicativi e i sistemi operativi. I primi sono quelli che usiamo tutti i giorni, come il browser per navigare in Internet, un programma per scrivere un testo, per fare dei calcoli o un videogioco. I sistemi operativi sono invece dei programmi particolari, ma ne parleremo più avanti. 18 - I LINGUAGGI DI PROGRAMMAZIONE A llora, chiariamo subito una cosa: il computer è una macchina stupida. Sì proprio così! È complessa, veloce, precisa, ma è sostanzialmente stupida. Siamo noi che dobbiamo dirgli esattamente cosa fare, punto per punto e con estrema precisione. Purtroppo però, come abbiamo visto in precedenza, un computer non conosce la nostra lingua, ma ne parla una tutta sua, composta da un alfabeto di soli due simboli, che per convenzione chiamiamo 0 e l’1. Ritornando all’esempio di prima ed estremizzando per rendere chiaro il concetto, non possiamo istruire un computer dicendo qualcosa come: «Scusa, mi crei un programma che faccia le quattro operazioni aritmetiche su due numeri che ti dirò io, per favore?». Nonostante la gentilezza e la buona educazione non otterremmo un bel niente, questo perché quello che voglio fare l’ho espresso nella mia lingua parlata e sfortunatamente per un computer non ha nessun senso! Quindi in che modo possiamo risolvere questo problema? L’unica soluzione è di istruire il computer su cosa fare e come farlo in una lingua che lui riesca a interpretare. Lui capisce solo zeri e uno. Dovremmo quindi formulare la soluzione al nostro problema come una specie di lunga sequenza di BIT? Esatto, proprio così, non abbiamo altra scelta! Ovviamente questo sarebbe troppo difficoltoso per non dire improponibile, se non fosse che esistono dei particolari strumenti pensati appositamente per tradurre il codice sorgente , scritto dal programmatore, nella sua corrispondente sequenza di BIT da dare in pasto al computer. Questi strumenti sono i compilatori , particolari software in grado di capire un linguaggio che è in qualche modo vicino a quello umano, ma anche nello stesso tempo rigoroso e preciso. Il compilatore leggerà le istruzioni che abbiamo scritto, controllerà come prima cosa se abbiamo fatto errori nella scrittura, dopodiché, se è tutto corretto, lo trasformerà in una sequenza di BIT detto codice macchina. Solo a questo punto, finalmente, il computer capirà esattamente e senza ambiguità cosa vogliamo fare ed eseguirà il codice. Alla luce di tutto questo, possiamo capire perché prima abbiamo trasformato il nostro algoritmo in una serie di righe di codice. Ebbene, quello è il codice sorgente per risolvere il problema iniziale. È abbastanza semplice e intuitivo per un programmatore che lo deve scrivere ma anche facilmente traducibile da un compilatore. Ricapitolando, abbiamo un problema iniziale che vogliamo risolvere grazie all’aiuto di un computer. Per prima cosa dobbiamo modellare accuratamente il problema, per renderlo strutturato e univoco, a tale scopo possiamo ricorrere a diversi strumenti, come il già citato diagramma di flusso. Dopodiché dovremmo tradurre il diagramma di flusso in un codice, utilizzando un appropriato linguaggio di programmazione. A questo punto un software particolare chiamato compilatore si preoccuperà di codificare il nostro listato nel codice macchina, una lunga sequenza di BIT, zero e uno. Solo a questo punto interviene il calcolatore che può eseguire il nostro algoritmo. Il processo di codifica dal codice sorgente al codice macchina viene fatto solo la prima volta dal compilatore, a meno che per qualche motivo non

Use Quizgecko on...
Browser
Browser