Eccovi! In questa sezione troverete  le lezioni del corso di sistemi operativi.

 

A:”Ma tu allora non capisci che esigenze abbiamo noi nonvedenti!”
B:”Invece si!”
A:”Si vede, si vede!”
B:”Ok, guardate: essendo un nonvedente anch’io so che in un testo lungo siamo svantaggiati. Così hoposizionato dei segnalibri durante il testo ed un indice
all’inizio! Così la consultazione sarà molto più rapida!”
A:”Evvaiiiii!”

 

Indice

“Presentazione”:

Parte 1

Parte 2: Importanza di un sistema operativo

Parte 3: Avvio di un so

Parte 4

Evoluzione dei sistemi operativi I

Evoluzione dei sistemi operativi II

“Evoluzione dei sistemi operativi III:”

Parte 1 di 5

Parte 2 di 5

Parte 3 di 5

Parte 4 di 5

Parte 5 di 5

“Gestione dei processi I:”

Parte 1 di 5

Parte 2 di 5

Parte 3 di 5

Parte 4 di 5

Parte 5 di 5

“Gestione dei processi II:”

Parte 1 di 4

Parte 2 di 4

Parte 3 di 4

Parte 4 di 4

“Gestione della memoria I:”

Parte 1 di 5

Parte 2 di 5

Parte 3 di 5

Parte 4 di 5

Parte 5 di 5

“Gestione della memoria II:”

Parte 1 di 5

Parte 2 di 5

Parte 3 di 5

Parte 4 di 5

Parte 5 di 5

“Gestione del file system”Lezione 12

Parte 1 di 5

Parte 2 di 5

Parte 3 di 5

Parte 4 di 5

Parte 5 di 5

“Funzioni di un SO: gestione della memoria secondaria e dell’I/O”Lezione 13

Parte 1 di 5

Parte 2 di 5

Parte 3 di 5

Parte 4 di 5

Parte 5 di 5

 

Software Planet - Corso di Sistemi Operativi - Presentazione

 

Corso di Sistemi Operativi

 

Presentazione

(parte 1)

 

Con  questa  puntata  iniziamo  un interessante excursus  all'interno di   un  campo  molto   vario   ed affascinante,  quello dei  sistemi operativi, del quale vedremo

differenti   aspetti   di   sicuro interesse,     sia     per     gli appassionati del genere sia per  i comuni utenti del classico PC.

Il     corso     si     articolerà essenzialmente  in tre  parti:  la prima parte introdurrà i  concetti teorici   di  base   dei   sistemi operativi   tradizionali;    nella seconda

parte  vedremo  una  rassegna  dei sistemi  operativi attualmente  in circolazione, dai classici sistemi Microsoft all'affermato Linux agli emergenti BeOS e

QNX;  infine, nella  terza  parte, approfondiremo la conoscenza della filosofia  GNU  e  della  sua  GPL (General  Public  License),  e  di Linux in particolare, alla

diffusione  del  quale  si   deve, principalmente,        l'impetuosa avanzata  dell'Open  Source   alla quale stiamo tuttora assistendo.

Data la loro maggiore  diffusione, prenderemo    in    considerazione principalmente   le   architetture Intel    e    quelle    ad    esse compatibili, evidenziando,  quando possibile,     disponibilità     e caratteristiche   per   le   altre piattaforme.

Per   eventuali   suggerimenti   e segnalazioni      potete      fare riferimento    direttamente     al redattore   del   corso    (Angelo Carpenzano)

o al webmaster di Software  Planet (Tommaso Trani).

 

Cominciamo   ricordando   che   un sistema di elaborazione può essere suddiviso,        in         prima approssimazione,      in       due componenti:   l'hardware   e    il software.

Con il termine hardware si intende essenzialmente    l'insieme    dei costituenti fisici di un computer: circuiti     integrati,      fili, alimentatori,    tubi   a    raggi catodici  e altri  dispositivi  di questo genere.

Con il termine software si intende una   grandissima   categoria   di programmi e applicazioni, senza  i quali  un  computer,  secondo   la definizione        dell'autorevole professore    A.   S.    Tanenbaum (http://www.cs.vu.nl/~ast/),   non sarebbe  altro che un "ammasso  di ferraglia".

E'   il  software,  infatti,   che consente  ad  un  calcolatore   di memorizzare      ed      elaborare informazioni,    di   inviare    e ricevere  e-mail da  Internet,  di far  girare un gioco  d'avventura, di  eseguire  tutta una  serie  di compiti, più o meno complessi, che lo  rendono  utile  e,  ai  nostri giorni, indispensabile per molti

(pensiamo  a quante persone ci  si guadagnano da vivere!).

Non bisogna dimenticare, tuttavia, che  il software esiste  anche  in moltissime  altre macchine di  cui si  fa  uso  abitualmente:   dalle centraline   di  controllo   delle automobili    ai   programmi    di lavaggio delle moderne  lavatrici, dai    sistemi   di    navigazione aerospaziale      ai      telefoni cellulari...

E'  comunque  evidente  che  tutti questi  sistemi sono  dedicati  ad uno scopo ben preciso e, con  rare e lievi eccezioni, durante il loro ciclo   di  vita   non   subiscono modifiche  di  comportamento;   in questo   si   differenziano    dai computer,  oltre  che  per   ovvie caratteristiche   fisiche    quali dimensioni, forma e complessità.

Un    calcolatore    può    essere anch'esso adibito ad un solo  uso: si   pensi,  ad  es.,  ai   grossi mainframe   che  si  occupano   di raccogliere  ed elaborare  i  dati provenienti dai satelliti e  dalle stazioni  orbitanti   sparpagliate intorno al nostro pianeta.

Diverso  è  il caso  dei  personal computer, ai quali, invece,  viene chiesto  di  soddisfare  un  ampio ventaglio di esigenze diverse;  si suole  dire  che il PC  è  general purpose,   per  indicare   proprio questa  caratteristica di  estrema varietà di applicazioni ed usi che gli vengono assegnati.

In un sistema del genere è  chiaro che  i  problemi  si   complicano, perché   si   richiede   che   più applicazioni                girino contemporaneamente   e   che   più utenti   possano   simultaneamente accedere   alle   risorse    della macchina per stampare,  collegarsi ad Internet, accedere ad un server remoto in una rete locale, e tanto altro ancora.

E' in uno scenario di questo  tipo che  sorge  l'esigenza  di   avere qualcosa che si occupi di  gestire questa complessità.

Questo   qualcosa  è  proprio   il sistema    operativo,    di    cui cominceremo  a parlare  a  partire dalla prossima puntata.

 

A Cura di Angelo Carpenzano (  (c) )

 

Software Planet - Corso di Sistemi Operativi   -  Importanza  di   un sistema operativo

 

Corso di Sistemi Operativi

 

Importanza di un sistema operativo

(parte 2)

 

Nella  puntata precedente  abbiamo accennato  alla  complessità   che caratterizza  un  calcolatore,   a partire  proprio dal semplice  PC, di cui tutti (o quasi) disponiamo.

In virtù di questa complessità, il software  di  un  calcolatore  può essere  suddiviso  in  due  grosse categorie: i programmi di  sistema (che  controllano  e  regolano  il comportamento   del    calcolatore stesso) e i programmi  applicativi (che  servono per  la  risoluzione dei  più disparati problemi  degli utenti).

I programmi applicativi sono  noti a tutti gli utenti di un  computer e  possono essere di  vario  tipo: editor, word processor, foglio  di calcolo, browser Internet, giochi, programmi per la riproduzione e la creazione di file multimediali,  e così via.

I programmi di sistema sono quelli che,  in gran parte nascosti  agli occhi degli utenti comuni, rendono difficile,  ma allo  stesso  tempo interessante e stimolante, la vita degli  esperti  del  settore;  tra questi  il  più  importante  è  il sistema operativo, croce e delizia di   almeno  due  generazioni   di programmatori e studiosi.

Il   sistema  operativo  (che   in seguito indicheremo con l'acronimo SO)     svolge    una     funzione fondamentale:     agisce      come intermediario  tra l'utente  e  il calcolatore  stesso,  controllando tutte  le risorse dell'hardware  e mettendo    a   disposizione    un ambiente  nel  quale  eseguire   i programmi applicativi.

Esaminiamo innanzitutto il  motivo per  il quale esistono  i  sistemi operativi.

Un   calcolatore  moderno   è   un sistema     molto      articolato, costituito    da   uno    o    più processori, da una certa  quantità di  memoria principale (la  famosa RAM),  da uno o più dischi,  dalla tastiera, dal monitor, dal  mouse, dalla   stampante,  dalla   scheda video,  dalla  scheda  audio,  dal modem, dalle interfacce di rete  e da  tanti  altri  dispositivi   di basso   livello,  di   cui   molti ignorano l'esistenza.

Se chi scrive un programma dovesse tener   conto  di   tutti   questi componenti e usarli correttamente, curandosi  dei  dettagli  con  cui essi  lavorano e delle  decine  di cose che potrebbero andare  storte durante    ognuna    delle    loro possibili  operazioni,  certamente ci  penserebbe due volte prima  di complicarsi     la     vita      e probabilmente molti programmi  non sarebbero mai stati scritti.

Molti anni fa ci si rese conto che era   necessario   nascondere   al programmatore    la    complessità dell'hardware, sia per un problema di  efficienza dei programmi,  sia per  permettere il  trasporto  del software da una macchina all'altra con    caratteristiche    hardware differenti.

Venne allora introdotto uno strato di    software   al    di    sopra dell'hardware nudo e crudo, che si occupasse di controllare tutte  le parti  del  sistema,   presentando all'utente   un'interfaccia    più semplice da capire e più facile da programmare: il sistema operativo, appunto.

Riepilogando  possiamo   affermare che  un SO ha  principalmente  due compiti:

gestire i dispositivi hardware;

supervisionare  l'esecuzione   dei programmi,  assegnando in  maniera opportuna  le risorse e  rilevando eventuali errori.

Per    comprenderne     pienamente l'importanza  diamo  uno   sguardo all'architettura  interna  di   un calcolatore,  di  cui  uno  schema semplificato è riportato in figura

2.1.

 

Fig.  2.1. Struttura a livelli  di un calcolatore digitale

 

Come       possiamo        vedere, l'architettura  di un  elaboratore può essere strutturata in livelli, ognuno dei quali comunica solo con quelli adiacenti.

E'  interessante  notare  che   il linguaggio  macchina, pur  essendo un   software,  viene   annoverato all'interno     del     componente hardware: ciò è dovuto al fatto

che esiste un legame  strettissimo tra  le istruzioni del  linguaggio macchina  e i  dispositivi  fisici che le implementano.

Ogni   piattaforma  (Intel,   AMD, Motorola,     IBM,    ecc.)     ha caratteristiche           hardware differenti dalle altre ed è dotata di un proprio linguaggio macchina; se   non  esistesse   il   sistema operativo,    un     programmatore dovrebbe preoccuparsi di  scrivere una versione del proprio programma per ognuna di esse, o limitarsi ad ignorarne  alcune,  seguendone  le evoluzioni per adattarvisi.

Per   ovviare  a   questo   enorme inconveniente,  il SO fornisce  al programmatore,  e agli  utenti  in genere,   un'unica    interfaccia, qualsiasi   sia   la   piattaforma sottostante:  è  compito  di   chi scrive il SO far sì che le  azioni decise  dal  programmatore   siano tradotte      nelle      opportune istruzioni per la macchina.

Nella  puntata successiva  vedremo cosa succede quando accendiamo  un calcolatore.

 

A Cura di Angelo Carpenzano (  (c) )

 

Software Planet - Corso di Sistemi Operativi - Avvio di un SO

 

Corso di Sistemi Operativi

 

Avvio di un SO

(parte 3)

 

Nella  lezione precedente  abbiamo compreso    che    il    SO     ha un'importanza fondamentale, perché si  addossa la  responsabilità  di gestire il calcolatore liberandoci

dall'obbligo   di  conoscerne   la struttura interna.

Prima     di     esaminare      le caratteristiche dei SO,  spendiamo qualche   parola  su  quello   che avviene  al nostro PC  al  momento dell'accensione, ossia durante  la cosiddetta  fase di boot,  facendo riferimento    alla    piattaforma hardware i386 (Intel) non  potendo avere  accesso  ad altri  tipi  di architettura.

Per   prima  cosa  il   processore carica  da  una  ROM  (Read   Only Memory  - memoria a sola  lettura) il  firmware della  scheda  madre, ossia  un programma  che  provvede alla gestione dei primi istanti di funzionamento   della    macchina, fornendo una serie di funzionalità che    verranno    sfruttate    da programmi      successivi      per completare l'avviamento.

Guardando   con   attenzione    le scritte  che  vengono  mostrate  a video  non  appena si  accende  il computer,  possiamo vedere che  il bios   (cioè  il  firmware   degli elaboratori  i386)  esegue  alcuni test,  riconoscendo l'hard disk  e altre  periferiche collegate  alla scheda  madre: questa fase  prende il  nome di post, ovvero power  on self test.

Al termine di questa fase, il bios carica   il  master  boot   record (spesso  indicato  con  l'acronimo MBR),  costituito  da  un  settore localizzato  nei  primi  512  byte dell'hard disk, contenente, tra le altre cose, il programma  deputato al    caricamento   del    sistema operativo,   il  cosiddetto   boot loader.

Nel caso di un sistema  contenente un  solo SO, questo viene  avviato automaticamente, spesso  mostrando a  video  delle  informazioni  che permettono    di   sapere    quali operazioni esso sta compiendo;  se il  nostro  sistema  contiene  più sistemi operativi, un boot  loader opportunamente         configurato presenterà un menu o un prompt che ci  permette di specificare  quale di essi avviare.

Ogni SO ha il proprio boot  loader (ad es. il lilo di Linux), ma  non tutti  consentono  il   multiboot, cioè   la  possibilità  di   poter avviare SO differenti.

Ad es. i sistemi basati su MS-DOS, come  i diffusissimi  Windows  9x, permettono di installare un loader proprietario nell'MBR (tramite  il comando   fdisk  /mbr),  che   non consente   di   indicare   sistemi alternativi,      ma      provvede semplicemente  a caricare il  boot sector di una partizione  indicata come attiva.

Per  comprendere il meccanismo  di avviamento di un SO, soffermiamoci sull'organizzazione  di  un   hard disk,  facendo  riferimento   alla figura 3.1.

 

Fig.  3.1.  Organizzazione  di  un hard disk in due partizioni.

 

Un    hard   disk    può    essere logicamente      suddiviso      in partizioni,   ossia  in   porzioni dello  spazio  di   memorizzazione trattate  come  unità  separate  e costituite  da un piccolo  settore di avvio, il boot sector, e da una frazione   più   o   meno   grande deputata a contenere i programmi e i dati veri e propri.

La  forma con cui  una  partizione viene organizzata dipende dal tipo di file system che la gestisce.

Nel caso più semplice un hard disk è    costituito   da   una    sola partizione,  di  cui  programmi  e dati   condividono   lo    spazio; tuttavia una buona prassi è quella

di     mantenere    almeno     due partizioni,  una  per il  SO  e  i programmi applicativi e una per  i dati.

Il master boot record contiene una tavola   delle   partizioni,   che specifica  il  modo  in  cui  sono partizionati  tutti gli hard  disk connessi   al   sistema   e    gli attributi delle varie partizioni.

Tra le altre cose, una  partizione può essere:

Attiva   (serve  al  boot   loader MS-DOS   per   sapere   in   quale partizione  si  trova  il  SO   da avviare;  può  esserci  una   sola partizione attiva);

Bootable  (se contiene un  sistema operativo avviabile)

Nascosta (non viene resa  visibile dal SO all'utente)

Quando si configura un boot loader per  il multiboot, si  associa  ad ogni  voce  di SO  da  avviare  la relativa   partizione  e  il   suo programma di caricamento.

All'avvio  il SO esegue una  serie di    controlli    e     procedure d'inizializzazione   che   possono prendere  anche parecchi  secondi, dopodiché  rimane  sempre  attivo, fornendo  un ambiente  all'interno del quale le applicazioni  vengono di volta in volta aperte e chiuse.

Dalla prossima puntata cominceremo a conoscere i concetti e le teorie che     stanno     dietro     alla progettazione di un SO.

 

A Cura di Angelo Carpenzano (  (c) )

 

Software Planet - Corso di Sistemi Operativi  - Il SO  come  macchina astratta

 

Corso di Sistemi Operativi

 

Il SO come macchina astratta

(parte 4)

 

Nella   seconda  puntata   abbiamo visto  che  l'architettura  di  un generico  sistema di  calcolo  può essere  strutturata  in  un  certo numero di livelli (cfr. fig. 2.1); ogni  livello  prende il  nome  di macchina   virtuale   e   possiamo indicarlo come MV0, MV1, ..., MVn.

 

Fig.  4.1. Relazioni tra  macchine virtuali.

 

Ogni macchina virtuale MVi dispone di  un insieme di oggetti Oi e  di un linguaggio Li per la gestione e il    controllo   degli    oggetti dell'insieme Oi.

Le    istruzioni   di   Li    sono implementate    per    mezzo    di programmi  scritti nel  linguaggio Lj   con  j<i,  dove   tipicamente j=i-1;   ciò  vuol  dire  che   le istruzioni del linguaggio Li  sono generalmente realizzate per  mezzo di  programmi  del  linguaggio  al livello immediatamente inferiore.

Generalmente  le istruzioni di  Li sono   dette  meccanismi,   perché rappresentano  le azioni che  quel linguaggio è in grado di compiere; i programmi di Lj che implementano tali    meccanismi   sono    detti politiche, in quanto costituiscono il  modo  in  cui  un  determinato meccanismo è realizzato.

Quando si realizza un livello MVj, occorre  conoscere  quali  sono  i meccanismi   di   Li,   cioè   del linguaggio       al        livello immediatamente sopra, e  scegliere una politica per l'implementazione di quel meccanismo.

Generalmente   non  esistono   due sviluppatori  che implementano  lo stesso   meccanismo  alla   stessa identica  maniera: ciò  vuol  dire che   lo  stesso  meccanismo   può essere    realizzato    attraverso politiche differenti, che portano, evidentemente,  a prestazioni  con caratteristiche diverse.

Se   esaminiamo  la  struttura   a livelli di un calcolatore  secondo questo   modello,  vengono   fuori alcuni       dettagli        molto interessanti,    che   ci    fanno comprendere meglio in che modo  il SO esegue i propri compiti,  ossia controllare e allocare le  risorse in   modo  "equo"  ed   efficiente (gestione    della    concorrenza, protezione,  gestione  dei  files, etc.)  e  semplificare  l'utilizzo delle risorse da parte dell'utente (librerie  standard,   interfacce, etc.).

 

Fig. 4.2. Macchine virtuali in  un calcolatore digitale.

 

In  figura 4.2 è reso evidente  il ruolo  della macchina virtuale  SO come intermediario tra l'utente  e l'hardware,    attraverso    delle interfacce chiare e semplici verso l'uno e l'altro livello.

Analizziamo  la  figura   partendo dall'alto.

L'utente rappresenta una  macchina virtuale  che  lavora  con   degli oggetti,  quali  ad  es.  file   e database,   che  può   gestire   e controllare per mezzo di programmi

scritti   in  linguaggi  ad   alto livello.

Questi  ultimi  utilizzano   delle istruzioni, quindi dei meccanismi, che  vengono  implementate   dalle corrispondenti  politiche del  SO, il quale agisce direttamente sulle risorse  della macchina,  come  la CPU e la memoria.

Tutto ciò viene fatto grazie  alle politiche che gli vengono  offerte dalla macchina virtuale  Assembler attraverso il linguaggio  macchina (indicato   con   L/M),   le   cui istruzioni    sono   formate    da sequenze  di  cifre  binarie   che vengono interpretate dal  firmware per eseguirle sull'hardware vero e proprio.

Infine,   l'hardware  non  ha   un linguaggio  nel  pieno  senso  del termine,   perché   il   modo   di realizzare   i   meccanismi    del firmware  è di  tipo  elettronico, cioè   per   mezzo   di    segnali elettrici      che       viaggiano all'interno   di   una   struttura fisica  in grado  di  implementare funzioni logiche.

Non è nostra intenzione  procedere all'esame   del   modo   in    cui l'hardware  viene  realizzato,  ma possiamo  accennare al fatto  che, al  pari di ogni altro livello,  è possibile  realizzare  gli  stessi meccanismi del firmware per  mezzo di politiche hardware  differenti, con  conseguenti differenze  nelle prestazioni,  nell'affidabilità  e nel   consumo  di  energia   della macchina (problema, questo,  molto sentito  in  caso  di  dispositivi portatili).

Sono  proprio  le  politiche   del linguaggio macchina, del  firmware e   dell'hardware   a   fare    la differenza    tra    le    diverse architetture:  un SO che  gira  su una  macchina  può  dar  luogo   a prestazioni  del tutto diverse  da quelle  che riesce a dare  su  una macchina    con    un'architettura differente,   così  come   diverse possono essere le prestazioni  che vengono    fuori   dallo    stesso hardware  quando è gestito  da  SO distinti.

Svariati studi hanno rilevato  che le    politiche   del   SO    sono determinanti  nel decidere  quanta potenzialità dell'hardware  riesce ad   essere  sfruttata   realmente nell'esecuzione   dei    programmi utente.

E'  proprio di questi aspetti  che ci occuperemo nella seconda  parte del corso.

 

A Cura di Angelo Carpenzano (  (c) )

 

Evoluzione  dei sistemi  operativi (I)

(parte 5)

 

Prima di procedere oltre diamo una rapida  occhiata alla  storia  dei sistemi  operativi, esaminando  in che  modo si è giunti  allo  stato attuale  attraverso  un   graduale processo di astrazione che ha reso le scelte progettuali dei  sistemi operativi    indipendenti    dalle caratteristiche della macchina.

Si ritiene che il primo  prototipo di  calcolatore digitale si  debba all'inglese  Charles Babbage,  che intorno  alla metà  dell'Ottocento progettò la "macchina  analitica", un apparecchio meccanico che  egli non  potè mai vedere realizzato  a causa           dell'impossibilità tecnologica    di    allora     di realizzare  gli  ingranaggi  e  le parti meccaniche richieste con  la dovuta precisione.

Da allora fino alla seconda guerra mondiale  furono fatti  pochissimi progessi  nella  realizzazione  di calcolatori digitali.

Occorre  attendere  il  1945   per vedere    comparire    la    prima generazione     di     calcolatori automatici, quando vari professori universitari e studiosi inglesi e

americani  (tra cui  von  Neumann) riuscirono   a   costruire   delle enormi macchine di calcolo  usando delle valvole elettroniche.

Questi     apparecchi      avevano dimensioni tali da riempire intere stanze e una velocità di calcolo a dir  poco modesta in confronto  al più scarso degli attuali  personal computer.

Allora  era  lo stesso  gruppo  di persone    ad   occuparsi    della progettazione,        costruzione, programmazione  e manutenzione  di ogni macchina.

La   programmazione   era    fatta esclusivamente    in    linguaggio macchina,  ossia  secondo   codici binari  direttamente eseguiti  dal processore, ed era realizzata per

mezzo  di  una serie  di  spinotti inseriti  su  particolari   schede adibite  al  controllo  delle  più elementari     funzioni      della macchina.

I  linguaggi  di   programmazione, compreso    l'assembler,     erano sconosciuti e di sistema operativo nemmeno si parlava.

Quasi tutte le applicazioni  erano semplici  calcoli  numerici,  come produzioni  di tabelle di  seni  e coseni.

Fino  alla  metà  degli  anni   50 l'unico   progresso  riguardò   la possibilità    di    scrivere    i programmi su schede perforate, che potevano essere lette direttamente

dal calcolatore, anziché usare gli spinotti.

A    cambiare   radicalmente    la situazione              intervenne l'introduzione dei transistor, che accrebbero   l'affidabilità    dei calcolatori   così   da   renderne possibile la  commercializzazione: entra   in   scena   la    seconda generazione    dei     calcolatori digitali.

Cominciarono  allora a  delinearsi dei profili professionali distinti tra   progettisti,    costruttori, operatori, programmatori e tecnici della manutenzione.

Questi   primi   sistemi,    molto costosi,   furono  detti   sistemi batch o sistemi di elaborazione  a lotti e funzionavano nel  seguente modo.

I  calcoli  che  dovevano   essere eseguiti   dal   computer    erano memorizzati in un job, che  poteva essere  un singolo programma o  un insieme di programmi.

Un       piccolo       calcolatore (relativamente)    poco    costoso (tipicamente  l'IBM 1401)  leggeva le  schede perforate  sulle  quali erano  memorizzati  i  job  e   li trasferiva su un nastro magnetico.

Quando il nastro aveva raccolto un lotto  (batch) di  lavoro,  veniva riavvolto   e   inserito   in   un calcolatore      più       potente (prevalentemente   l'IBM    7094), dotato dell'antenato degli attuali sistemi operativi, l'IBSYS.

Questo  si occupava di leggere  in sequenza i vari job e di eseguirli uno  dopo l'altro  memorizzando  i risultati  su  un  secondo  nastro magnetico.

Una  volta  completato  il  lotto, venivano    rimossi    i    nastri d'ingresso e di uscita, riavvolti, e  il  nastro  di  uscita   veniva inserito in un altro IBM 1401 per

stampare    i    dati     ottenuti dall'elaborazione.

Tramite   l'utilizzo  dei   nastri d'ingresso  e  di  uscita,  veniva realizzata una "primordiale" forma di  concorrenza, potendo  eseguire l'elaborazione      dei      lotti contemporaneamente            alla memorizzazione      del      lotto successivo   e  alla  stampa   dei risultati di quello precedente.

Questa tecnica era detta  spooling (dal termine inglese  Simultaneous Operation On Line).

Essenzialmente i calcolatori della seconda  generazione furono  usati per eseguire calcoli scientifici e ingegneristici,  anche  perché  il loro costo poteva essere sostenuto solo  da grosse  compagnie,  dalle agenzie   governative   e    dalle università.

Furono programmati in FORTRAN e in linguaggio assembler.

Accanto   all'IBSYS   un   sistema operativo  tipico di  quegli  anni era   il  FMS   (Fortran   Monitor System).

 

A Cura di Angelo Carpenzano (  (c) )

 

Evoluzione  dei sistemi  operativi (II)

(parte 6)

 

Proseguendo il nostro viaggio  nel passato  ci  troviamo   all'inizio degli  anni 60, quando la  maggior parte     dei    produttori     di calcolatori   avevano  due   linee distinte di prodotti: da un lato i grossi   calcolatori   scientifici come  l'IBM  7094,  dall'altro   i calcolatori  commericali  di   più limitata   capacità   elaborativa, come l'IBM 1041.

Per  risolvere  tutti  i  problemi correlati ad una tale  situazione, l'IBM  (allora in  una  situazione pressoché           monopolistica) introdusse   il  System/360,   una serie  di macchine  compatibili  a livello software, che  differivano solo per prezzo e prestazioni  (si andava  dal  1041 a  macchine  più potenti del 7094).

Il  sistema 360 fu la prima  linea di   calcolatori   ad   usare   la tecnologia dei circuiti  integrati (IC),  allora  a  bassa  scala  di integrazione,      che       portò innumerevoli  vantaggi in  termini di prezzo e prestazioni.

Inutile  dire che il successo  dei calcolatori  compatibili  convinse gli   altri  costruttori  a   fare altrettanto.

La  compatibilità software  fra  i diversi computer fu un fattore  di grande  forza, ma anche  un  punto debole.

Principalmente  ciò  è  dovuto  al fatto  che  l'intenzione  era   di avere   lo  stesso  software,   SO compreso,  su tutti i modelli,  ma le    grandi   differenze    nelle caratteristiche     hardware     e nell'uso  in ambito scientifico  e commerciale   avevano    requisiti spesso in conflitto fra loro.

Il  voluminoso  sistema  operativo che venne adottato, l'OS/360,  era costituito da milioni di righe  di codice   assembler   scritto    da migliaia   di   programmatori    e conteneva centinaia di errori, che rendevano   necessarie    versioni sempre  nuove,  con  le  quali  si correggevano  i  vecchi  e  se  ne introducevano di nuovi...

Nonostante le enormi dimensioni  e gli  errori, i  sistemi  operativi della  terza  generazione  seppero soddisfare   gli   utenti,   anche grazie  all'introduzione  di   una nuova         tecnica,          la multiprogrammazione.

A causa dei costi elevatissimi dei calcolatori,    si    impose    la necessità  di ridurre la  quantità di  tempo in cui la  CPU  rimaneva inattiva, permettendo ad un job di occupare  il processore mentre  un altro   job  era  in  attesa   del completamento di un'operazione  di I/O.

Per fare ciò la memoria principale venne  divisa in  partizioni,  una dedicata  al  SO  e  le  rimanenti assegnate a vari job.

Tramite  lo  spooling  le   schede contenenti  i job venivano  subito lette  e i job caricati su  disco; in maniera analoga si operava  per la   gestione   dell'uscita    dei risultati,  eliminando  così   per sempre   la   "scocciatura"    del continuo  spostamento  di   nastri magnetici   da   un    calcolatore all'altro.

In  questi sistemi, detti a  lotti multiprogrammati, si  presentarono per    la   prima   volta    nuove problematiche:

lo  scheduling dei  job  (decidere quale tra i job nel disco caricare in memoria);

lo   scheduling   del   processore (decidere  quale  tra  i  job   in memoria mandare in esecuzione);

la    gestione    della    memoria (ottimizzarne l'utilizzo, date  le limitate dimensioni);

la   protezione   reciproca    (da eventuali              interazioni indesiderate).

 

Il desiderio di un veloce tempo di risposta   portò  ben  presto   al timesharing    (condivisione    di tempo),    una   variante    della multiprogrammazione che permetteva a più utenti di avere un terminale ciascuno.

In  questi sistemi la  CPU  veniva assegnata  a turno ai vari  utenti che ne richiedevano l'uso e  venne reso   disponibile   un   servizio interattivo     molto      veloce, sfruttando  i tempi di  inattività degli utenti che stavano pensando, parlando o prendendo il caffè  per eseguire i job degli altri.

I    primi    sistemi    operativi timesharing   furono   il    CTSS, sviluppato   dal   1962   al   MIT (Massachussets    Institute     of Technology) e l'ambizioso  MULTICS (MULTiplexed    Information    and Computing   Service),   sviluppato nella  seconda metà degli anni  60 da gruppi del MIT, dei  laboratori Bell    e   della   GE    (General Electric).

Entrambi  i  sistemi  non   ebbero rilevanza   commerciale  a   causa della  mancanza di  un  necessario hardware   per  la  protezione   e MULTICS   in  particolare  fu   un fiasco.

Tuttavia  quest'ultimo preparò  la strada  alla creazione di uno  dei più popolari ed efficienti sistemi operativi di tutti i tempi: UNIX.

Vedremo  in che modo  ciò  avvenne nella prossima puntata.

 

A Cura di Angelo Carpenzano ( (c)

 

Evoluzione  dei sistemi  operativi (III)

Lezione 7

Parte 1 di 5

 

Oltre a quanto visto nella puntata precedente,   durante   la   terza generazione    ebbe   luogo    una fenomenale      crescita       dei minicalcolatori,  a  partire   dal PDP-1 del 1961.

Nella  serie dei  PDP  successivi, fino al PDP-11, il più  importante (per   ragioni  storiche)  fu   il PDP-7, sul quale venne sviluppata, da   Ken   Thompson   (uno   degli informatici  dei  laboratori  Bell che    aveva   collaborato    alla realizzazione  di  MULTICS),   una versione   ridotta   per   singolo utente di MULTICS, chiamata per

gioco UNICS (Uniplexed Information and  Computing Service),  che  non tardò a convincere gli addetti  ai lavori, diventando ben presto UNIX (implementato  per la prima  volta proprio su un PDP-11/20).

L'evoluzione    incredibile    dei minicalcolatori   portò   ad   una migrazione  delle  caratteristiche dei SO nati per mainframe verso  i SO   usati   su   tali    sistemi,  cosicché UNIX potè  avvantaggiarsi dei progressi compiuti negli  anni precedenti.

 

A Cura di Angelo Carpenzano ( © )

 

Evoluzione  dei sistemi  operativi (III)

Lezione 7

Parte 2 di 5

 

La  quarta generazione  nasce  con l'avvento dei circuiti LSI  (Large Scale  Integration),  che   portò, alla  fine  degli  anni  70,  alla costruzione  dei  primi   personal computer,    molto    simili    ai minicalcolatori come il PDP-11, ma più economici.

Venne   introdotto   il    termine workstation  (stazione di  lavoro) per  indicare i PC  utilizzati  da uomini      d'affari,      agenzie governative ed università, sebbene

non  fossero  altro  che  personal computer   un      più   grandi, talvolta     connessi      insieme attraverso una rete.

L'aumentata     diffusione     dei calcolatori    e     l'accresciuta potenza  di  calcolo,  portò  allo sviluppo di varie case aziende per la produzione di software per PC,

il   cui  scopo   principale   era produrre  software  user-friendly, cioè amichevole, rivolto a persone che  nulla conoscevano o  volevano conoscere dei calcolatori, ma  che non    volevano   rinunciare    ad utilizzarli.

 

A Cura di Angelo Carpenzano ( © )

 

Evoluzione  dei sistemi  operativi (III)

Lezione 7

Parte 3 di 5

 

Una  di queste  aziende  nascenti, denominata    Microsoft,     venne fondata     da     un      giovane programmatore di nome Bill  Gates, che   qualche  anno  prima   aveva scritto una versione di BASIC  per Altair  (che molti considerano  il primo   vero  personal   computer, prodotto  nel 1975), che  in  poco tempo     lo    fece     diventare multimilionario  (quando  si  dice nato  con la camicia_:-);  nessuno allora  era in grado di  prevedere quanto   grande   sarebbe    stata l'influenza   di  questa   azienda nello sviluppo e la diffusione dei PC.

Sin  dall'inizio  i  due  maggiori sistemi  operativi che  dominarono la   scena   dei   PC   e    delle workstation  furono  MS-DOS  della Microsoft e UNIX.

MS-DOS (Microsoft - Disk Operating System) fu largamente usato su  PC IBM e sui sistemi compatibili  che utilizzavano  i  processori  Intel (dall'8088 ai suoi successori); le prime  versioni  erano   piuttosto primitive,    ma   le    successive vennero       arricchite        di caratteristiche  avanzate,   molte delle   quali  riprese   da   UNIX (infatti,   ironia  della   sorte, l'attuale  avversario numero 1  di Linux  -  il  più  conosciuto  dei figli  di  UNIX -  allora  era  il principale    distributore     dei sistemi UNIX :-}).

 

A Cura di Angelo Carpenzano ( © )

 

Evoluzione  dei sistemi  operativi (III)

Lezione 7

Parte 4 di 5

 

UNIX    invece    spopolava    sui calcolatori   non-Intel  e   sulle workstation,  particolarmente   in quelle equipaggiate con chip  RISC ad alte prestazioni.

In  questo  scenario,  durante  la metà degli anni 80, cominciavano a prendere piede le reti di personal computer,  sui  quali  giravano  i primi sistemi operativi di rete  e i sistemi operativi distribuiti.

La   fine   degli   anni   80    è caratterizzata dal diffondersi dei vari  dialetti  di UNIX,  che  dal progenitore di proprietà dell'AT&T (evolutosi nello UNIX System V con le sue varie release),  derivarono diverse   varianti  (BSD,   Minix, Linux, FreeBSD, OpenBSD, NetBSD, e altri ancora), alcune delle  quali distribuite gratuitamente e con  i sorgenti.

 

A Cura di

Angelo Carpenzano ( © )

 

Evoluzione  dei sistemi  operativi (III)

Lezione 7

Parte 5 di 5

 

Una nota particolare merita Linux, apparso  per  la prima  volta  nel 1991,  che, nato su iniziativa  di un giovane studente di nome  Linus Torvalds,   allievo   di   A.   S. Tanenbaum (l'autore di Minix),  ha ben presto ricevuto l'appoggio  di numerosi  sviluppatori  sparsi  in tutto  il mondo, che hanno  potuto contribuire   al   suo    sviluppo soprattutto grazie ad Internet.

L'affermazione  di  questo  SO   è storia  recente  ed è  tuttora  in crescita.

Per  concludere questa  carrellata storica,    non    possiamo    non menzionare           l'incredibile diffusione  dei sistemi  operativi basati   sul  DOS   di   Microsoft (MS-DOS,  Windows  3.x  e  Windows 9x),  che,  seppure  con  i   loro difetti    e    demeriti,    hanno certamente   il  merito  di   aver introdotto  i  PC  nelle  case  di tutto il mondo.

Per  il  futuro  siamo  ancora  in attesa   e,  come  vedremo   nella seconda   parte  del   corso,   si prospetta  ricco  di  interessanti novità!

 

A Cura di

Angelo Carpenzano ( © )

 

Funzioni  di un SO:  gestione  dei processi I

Lezione 8

Parte 1 di 5

 

Data la complessità di un SO, esso può   avere  componenti   alquanto diverse tra loro e un sistema  può differire   da   un   altro    per moltissimi aspetti.

Tuttavia    all'interno   di    un qualsiasi   SO  è   quasi   sempre possibile trovare dei sottosistemi che  interagiscono  tra  loro  per realizzare le funzioni necessarie

alla gestione dell'intero  sistema di elaborazione:

1. Gestione dei processi

2.    Gestione    della    memoria principale

3.    Gestione    della    memoria secondaria

4. Gestione del file system

5. Gestione dei dispositivi di I/O

6. Protezione delle risorse

7. Interprete dei comandi

 

A Cura di

Angelo Carpenzano ( © )

 

Funzioni  di un SO:  gestione  dei processi I

Lezione 8

Parte 2 di 5

 

Un  concetto  chiave  in  tutti  i sistemi  operativi è il  processo, ovvero  l'istanza di un  programma in  esecuzione, che  è  costituito da:

1.  il  codice  eseguibile  (detto anche testo);

2. i dati su cui il codice lavora;

3. una lista (più o meno lunga) di strutture dati e informazioni  che occupano risorse di sistema.

E' indispensabile comprendere  che programma e processo sono due cose distinte.

Un programma è un'entità  passiva, un   codice   binario   che    può risiedere   in   un   sistema   di memorizzazione  (come  il   disco) anche se il computer è spento e la

cui  durata può essere (almeno  in teoria) infinita.

Di contro, un processo è un'entità attiva,   che  scaturisce  da   un programma   quando  questo   viene mandato  in  esecuzione e  la  cui durata è variabile e dipende

dall'ambiente di esecuzione.

Inoltre  per esistere un  processo ha  bisogno  che il  computer  sia almeno acceso :-).

 

A Cura di

Angelo Carpenzano ( © )

 

Funzioni  di un SO:  gestione  dei processi I

Lezione 8

Parte 3 di 5

 

Per  chiarire meglio  il  concetto facciamo un esempio.

Quando  in  un  sistema  Microsoft WindowsÒ eseguiamo  l'applicazione "Notepad"  ("Blocco  note"   nella versione  italiana),  il   sistema crea  un  processo a  partire  dal programma notepad.exe che si trova nella    directory   di    sistema (tipicamente C:\WINDOWS).

Il processo non esiste finché  non ne  invochiamo  esplicitamente  la creazione, mentre il programma era già nel computer quando il sistema è stato avviato.

Se, inoltre, mandiamo più volte in esecuzione il programma (attenti a non  esagerare!), vedremo  aprirsi tante finestre dell'editor  quante sono  state le  nostre  selezioni: ciascuna  copia del Notepad non  è altro che un'istanza dello  stesso programma  notepad.exe, e  per  il sistema   ognuna  di  esse  è   un processo distinto.

Altrettanto  avviene in  qualsiasi altro   SO,  anche   se   esistono varianti  che al momento non è  il caso di considerare.

 

A Cura di Angelo Carpenzano ( © )

 

Funzioni  di un SO:  gestione  dei processi I

Lezione 8

Parte 4 di 5

 

Per potere eseguire un programma è necessario  che esso sia  caricato in memoria principale, insieme  ad una    serie    di    informazioni indispensabili, come ad es. valori di  variabili e il puntatore  alla prima istruzione da eseguire (noto come   program   counter,   spesso indicato  con  la sigla  pc),  che complessivamente prendono il  nome di contesto del processo.

Durante  l'esecuzione il pc  viene continuamente    aggiornato    per puntare alla locazione di  memoria che   contiene   l'istruzione   da eseguire al passo successivo.

Se  un  SO  permette  l'esecuzione contemporanea  di  più   processi, detti  anche task, allora si  dice che   il  SO  è   multitasking   o multiprogrammato.

Tutti   i  sistemi  attuali   sono multitasking,  classici esempi  di sistemi  monoprogrammati  sono  le versioni di MS-DOS precedenti alla 5.0.

 

A Cura di

Angelo Carpenzano ( © )

 

Funzioni  di un SO:  gestione  dei processi I

Lezione 8

Parte 5 di 5

 

In sistemi con un solo  processore (per  intenderci,  la   stragrande maggioranza   dei   PC)   non    è possibile che più processi vengano eseguiti        contemporaneamente dall'unica  CPU, ma  esistono  dei meccanismi  del SO che  consentono di   avere  l'illusione  che   ciò avvenga,  attraverso  un  continuo passaggio    da    un     processo all'altro;  si  parla  perciò   di pseudo-parallelismo,           per distinguerlo   dal    parallelismo reale che avviene nei sistemi  con più CPU.

Perché   il   multitasking   possa funzionare è necessario che il SO, prima di passare da un processo ad un  altro, salvi il  contesto  del processo    che   sta    eseguendo attualmente,  in modo  che  quando esso verrà rimesso in  esecuzione, potrà proseguire dal punto in  cui era stato sospeso senza accorgersi di nulla.

Quando  un processore passa da  un processo  ad un altro si dice  che esegue  un  cambio  di   contesto, ovvero un context switch.

Nella       prossima       puntata continueremo    a    parlare    di processi.

 

A Cura di Angelo Carpenzano ( © )

 

Funzioni  di un SO:  gestione  dei processi II

Lezione 9

Parte 1 di 4

 

Quanto detto nella scorsa  puntata ci  fa comprendere che un SO  vive di processi.

In   realtà  il  SO  è   anch'esso costituito    da   processi    che cooperano    adeguatamente     per garantire       un        corretto funzionamento del sistema (almeno, questo  è quello che  si  dovrebbe cercare di fare).

Riprendendo   il   discorso    sul multitasking, diciamo innanzitutto che il modulo del SO che si occupa di gestire il context switch viene detto scheduler.

Lo  scheduling, cioè  l'operazione dello   scheduler,   può    essere realizzato   in   modi    diversi, secondo   le   modalità   che   il progettista del sistema sceglie di adottare.

Un  obiettivo importante che  deve essere   perseguito,   quando   si sceglie     un    algoritmo     di scheduling, è sfruttare al massimo il tempo di esecuzione della CPU,

evitando,  nel  contempo,  che  un processo   ne  monopolizzi   l'uso impedendo  agli altri processi  di progredire.

 

A Cura di Angelo Carpenzano ( (c)

 

Funzioni  di un SO:  gestione  dei processi II

Lezione 9

Parte 2 di 4

 

Riguardo  a quest'ultimo  aspetto, un   SO  è  detto  preemptive   (o prelazionato) se lo scheduler  può arbitrariamente    sottrarre    il processore   ad   un   task    per assegnarlo  ad  un altro  (ad  es. perché    quest'ultimo   ha    una priorità maggiore); altrimenti  si parla        di         scheduling non-preemptive.

Una tecnica di schedulazione molto usata  è  nota col nome  di  round robin.

Secondo  lo schema round robin  ad ogni  processo viene assegnato  un time  slice,  ovvero  una  piccola frazione di tempo (dell'ordine dei millisecondi),  durante  la  quale gli  viene aggiudicata  totalmente la CPU.

Allo  scadere  del time  slice  il clock, ossia l'orologio di sistema che   regola  la   temporizzazione delle  operazioni della  macchina, invia al processore un'interrupt

(un'interruzione),  per   indicare che   il   processo   attuale   ha occupato   l'intero   time   slice assegnatogli  e  che  è  possibile eseguire un nuovo processo.

In base alle politiche attuate dal SO,  la  CPU  esegue  un   context switch  o continua a lavorare  con il processo corrente.

Per   sfruttare  al   massimo   le potenzialità  del sistema,  il  SO sospende un processo in esecuzione quando  esso  deve  attendere  che venga  completata una  determinata operazione.

 

A Cura di Angelo Carpenzano ( (c)

 

Funzioni  di un SO:  gestione  dei processi II

Lezione 9

Parte 3 di 4

 

Ad es. se un processo deve leggere un  file  dal  disco,  passerà  un certo  tempo  prima  che  i   dati attesi   dal   processo    saranno disponibili, a causa dell'elevato

tempo   di   accesso   del   disco (rispetto alla scala dei tempi  di una CPU).

Sospendendo  il processo  fino  al completamento  del   trasferimento dei   dati,  la  CPU  può   essere assegnata  ad un  processo  pronto per essere eseguito, evitando così     che essa rimanga inutilizzata.

Dunque, un processo durante la sua esecuzione può trovarsi in diversi stati,  che  possiamo   riassumere sommariamente in tre:

1.   in  esecuzione   (quando   il processo      sta      utilizzando effettivamente    la    CPU     in quell'istante);

2. pronto (quando può essere messo in      esecuzione,      ma      è temporaneamente    sospeso     per permettere ad un altro processo di eseguire);

3. bloccato (quando non può essere messo  in  esecuzione  finché  non accade  un evento esterno, ad  es. il completamento di  un'operazione di I/O).

Generalmente, durante la sua vita, un processo transita continuamente da uno stato all'altro secondo  le regole adottate dal SO.

 

Funzioni  di un SO:  gestione  dei processi II

Lezione 9

Parte 4 di 4

 

Una  transizione  interessante   è quella  dallo  stato  di  bloccato allo   stato   di   pronto,    che presuppone che il SO sia in  grado di rendersi conto del verificarsi

di un dato evento.

Le    soluzioni   adottate    sono generalmente due:

1. polling

2. interrupt

Con   il   polling  il   SO   deve periodicamente    interrogare    i dispositivi di I/O per  verificare il   loro  stato  di   esecuzione, spendendo   tempo   di   CPU   per controllare

tutti    i    dispositivi    della macchina.

Con  la tecnica  degli  interrupt, invece,  sono  le  periferiche  ad avvertire il SO quando si verifica un evento che ne cambia lo  stato: questa soluzione è la

più efficiente ed è quindi la  più usata.

Il   meccanismo  degli   interrupt richiede un hardware opportuno per il   controllo  dei   segnali   di interruzione e i sistemi operativi che lo utilizzano (detti

per questo interrupt driven,  cioè guidati  dagli eventi)  mantengono delle strutture software  adeguate per   riconoscere   il   tipo   di interrupt ed intraprendere

le relative azioni di gestione.

Nella prossima puntata vedremo  il sottosistema  di  gestione   della memoria principale.

 

A Cura di Angelo Carpenzano (c)

 

 

Corso di Sistemi Operativi

 

Funzioni di un SO: gestione della memoria principale (I)

Lezione 10

Parte 1 di 5

 

Al momento dell’esecuzione ogni programma deve risiedere, almeno in parte, nella memoria centrale.

In un sistema monoprogrammato, questa condizione può essere facilmente soddisfatta imponendo un limite alla dimensione massima che un processo può avere;

soluzione, questa, certamente non elegante e poco efficiente.

La situazione si aggrava nei sistemi multiprogrammati, in cui un numero imprecisato di processi aventi dimensioni variabili possono contemporaneamente contendersi

il processore per l’esecuzione.

La contesa fra i vari processi riguarda naturalmente anche la memoria e il SO deve fornire dei meccanismi per tenere conto delle parti di memoria utilizzate

e di quelle libere, per allocare memoria ai processi quando ne hanno bisogno e deallocarla quando hanno finito, e infine per gestire gli scambi fra la

memoria principale e il disco, quando la memoria non è sufficiente a contenere tutti i processi.

 

A Cura di

Angelo Carpenzano ( © )

 

 

Funzioni di un SO: gestione della memoria principale (I)

Lezione 10

Parte 2 di 5

 

Infatti, con il timesharing, ad un sistema sono normalmente collegati tanti utenti e la memoria non è in grado di contenere tutti i loro processi, rendendo

così necessario scaricarne alcuni su disco.

Per far girare i processi che ad un dato istante risiedono nel disco, è necessario che essi vengano caricati in memoria: l’operazione relativa allo spostamento

di processi dalla memoria al disco e viceversa prende il nome di swapping (scambio) e il modulo del SO che se ne occupa si chiama swapper.

Alcuni sistemi operativi (ad es. Linux) richiedono una partizione dell’hard disk dedicata esclusivamente a questo scopo, mentre altri sistemi (ad es. Windows)

creano ed utilizzano un file particolare (in Windows questo file si chiama Win386.swp e si trova nella directory C:\WINDOWS\).

 

A Cura di

Angelo Carpenzano ( © )

Corso di Sistemi Operativi

 

Funzioni di un SO: gestione della memoria principale (I)

Lezione 10

Parte 3 di 5

 

Per permettere a più processi di risiedere contemporaneamente in memoria, questa viene divisa in partizioni o regioni, ossia porzioni di celle di memoria

contigue, che possono essere di dimensioni fisse o variabili, secondo le scelte fatte da chi sviluppa il sistema.

La maggior parte dei sistemi attuali utilizza partizioni variabili, perché presentano una maggiore flessibilità, resa necessaria dal fatto che i processi

hanno dimensioni molto diverse tra loro e non tutti richiedono la stessa quantità di memoria per poter eseguire.

Inoltre gran parte dei processi cambia dinamicamente la propria dimensione durante l’esecuzione, richiedendo di volta in volta una quantità di memoria variabile

e, spesso, non predicibile.

Occorre notare che, a seguito dello swapping, un processo non occupa sempre le stesse le regioni di memoria, anzi, la cosa più probabile è che ogni volta

che il processo viene rimesso in memoria dal dispositivo di swap (swap device), il SO gli assegnerà regioni differenti, in relazione alla situazione di

occupazione della memoria al momento in cui viene richiesto il caricamento di quel processo.

A cura di

Angelo Carpensano

 

Corso di Sistemi Operativi

 

Funzioni di un SO: gestione della memoria principale (I)

Lezione 10

Parte 4 di 5

 

Riguardo allo spazio di swap, l’allocazione può avere caratteristiche differenti da sistema a sistema: alcuni non allocano spazio sullo swap device fino

a che il processo non viene scaricato e ad ogni scaricamento questo può essere piazzato in una zona diversa del disco; altri sistemi al momento della creazione

del processo gli riservano spazio per lo swap sul disco, cosicché esso occuperà sempre lo spazio che gli è stato assegnato.

In quest’ultimo caso, quando il processo termina lo spazio viene liberato.

 

Lo swapping puro prevede che il caricamento e lo scaricamento di un processo avvenga per intero.

Esiste però una soluzione alternativa che tiene conto di una caratteristica comune a tutti i processi: ad un dato istante ogni processo esegue utilizzando

solo un sottoinsieme del suo spazio di indirizzamento.

 

A Cura di

Angelo Carpenzano ( © )

 

Corso di Sistemi Operativi

 

Funzioni di un SO: gestione della memoria principale (I)

Lezione 10

Parte 5 di 5

 

Lo spazio di indirizzamento è l’insieme degli indirizzi di memoria generati da un programma.

Ad un dato istante, un programma in esecuzione utilizza solo gli indirizzi relativi alle istruzioni che esegue in quel momento, per cui si potrebbe pensare

di tenere in memoria solo il sottoinsieme di indirizzi necessario, evitando di occupare la memoria con informazioni non necessarie.

Su questa importante proprietà si basa il metodo della memoria virtuale, di cui discuteremo nella prossima lezione.

 

 

A Cura di

Angelo Carpenzano ( © )

 

Corso di Sistemi Operativi

 

Funzioni di un SO: gestione della memoria principale (II)

Lezione 11

Parte 1 di 5

 

 

Nella scorsa puntata abbiamo accennato al metodo della memoria virtuale: l’idea di base della memoria virtuale è che la dimensione combinata di testo, dati

e stack dei processi può eccedere la quantità di memoria disponibile per essi.

Abbiamo anche notato che, ad un determinato istante, i processi non riferiscono tutto il loro spazio di indirizzamento, ma solo una sua parte: per indicare

questa proprietà si utilizza il concetto di località.

Poiché un processo indirizza celle di memoria contigue in una piccola porzione dello spazio di indirizzamento totale si parla di località spaziale (un caso

che possiamo immaginare è quello in cui un processo sta scorrendo in sequenza gli elementi di un array).

Poiché una stessa cella di memoria può essere riferita frequentemente per un certo intervallo di tempo, si parla di località temporale (ad es. una cella

di memoria viene prima letta e poi scritta).

 

A Cura di

Angelo Carpenzano (©)

 

Corso di Sistemi Operativi

 

Funzioni di un SO: gestione della memoria principale (II)

Lezione 11

Parte 2 di 5

 

 

Il SO può allora mantenere in memoria le parti che sono in uso in un certo momento, mentre le altre parti vengono mantenute nello swap device.

Tuttavia occorre notare che il processo cambia località quando passa da una fase dell’esecuzione all’altra, cosicché è necessario cambiare le sue parti

in memoria quando deve accedere a nuovi indirizzi.

La memoria virtuale si sposa molto bene con la multiprogrammazione: mentre un programma aspetta che una sua porzione venga caricata in memoria, è di fatto

in attesa di un’operazione di I/O e non può girare, cosicché il processore può essere assegnato ad un altro processo.

 

 

A Cura di

Angelo Carpenzano (©)

 

Corso di Sistemi Operativi

 

Funzioni di un SO: gestione della memoria principale (II)

Lezione 11

Parte 3 di 5

 

 

Naturalmente in un sistema di questo tipo, gli indirizzi generati dai programmi non possono riferirsi direttamente alla memoria, perché durante l’esecuzione

di un processo la memoria viene dinamicamente allocata e deallocata, per permettere di caricare e scaricare le porzioni degli spazi di indirizzamento usate

dai processi in memoria.

Per questo motivo gli indirizzi generati dai programmi vengono detti indirizzi virtuali e formano lo spazio di indirizzamento virtuale.

Gli indirizzi virtuali, anziché essere inviati direttamente alla memoria - come succede nei sistemi che non hanno la memoria virtuale -, vengono inviati

ad un’unità hardware, detta MMU (Memory Management Unit – unità di gestione della memoria), che trasforma gli indirizzi virtuali in indirizzi della memoria

fisica.

Possiamo pensare alla MMU come ad una funzione che riceve un parametro d’ingresso (l’indirizzo virtuale) e dà in uscita un valore (l’indirizzo fisico).

 

 

A Cura di

Angelo Carpenzano (©)

 

Corso di Sistemi Operativi

 

Funzioni di un SO: gestione della memoria principale (II)

Lezione 11

Parte 4 di 5

 

 

Lo spazio di indirizzamento virtuale viene suddiviso in unità chiamate pagine e le corrispondenti unità nella memoria fisica vengono dette pagine fisiche.

Pagine e pagine fisiche hanno la stessa dimensione e i trasferimenti da e verso il disco vengono effettuati sempre in unità di una pagina.

Quando la MMU riceve un indirizzo virtuale, essa calcola il numero della pagina alla quale appartiene: se essa è presente in memoria, la MMU estrae il corrispondente

numero della pagina fisica e l’indirizzo fisico corrispondente all’indirizzo virtuale; se la pagina non è in memoria viene invocato un page fault (fallimento

di accesso alla pagina), con il quale il controllo viene passato al SO che si occupa di recuperare al pagina dal disco.

Questo metodo di gestire la memoria pone una complessa problematica che deve essere accuratamente esaminata e risolta da chi progetta un SO.

 

 

A Cura di

Angelo Carpenzano (©)

 

Corso di Sistemi Operativi

 

Funzioni di un SO: gestione della memoria principale (II)

Lezione 11

Parte 5 di 5

 

Innanzitutto la scelta della dimensione delle pagine è un fattore molto importante, perché da essa derivano le dimensioni delle strutture dati adibite alla

gestione della memoria.

Inoltre la traduzione di un indirizzo virtuale in un indirizzo fisico è un’operazione che ricorre ad ogni accesso in memoria, quindi, proprio per l’elevata

frequenza con la quale deve essere eseguita questa operazione, è necessario che la traduzione avvenga velocemente.

Quando si verifica un page fault il SO deve scegliere una pagina da rimuovere dalla memoria principale per far posto a quella che deve essere caricata;

occorre perciò scegliere un efficiente algoritmo che consenta di minimizzare i page fault futuri causati dalla rimozione di una pagina.

Questi sono solo alcuni dei problemi che un progettista di SO incontra nel progetto del modulo di gestione della memoria, anche se spesso è aiutato da un

hardware creato per supportare efficientemente una scelta piuttosto che un’altra.

 

 

A Cura di

Angelo Carpenzano (©)

 

Corso di Sistemi Operativi

 

Gestione del file system

Lezione 12

Parte 1 di 5

 

Uno degli aspetti che più interessano l’utente di un SO è la possibilità di memorizzare permanentemente (anche per decenni) le proprie informazioni e che

sia possibile reperirle facilmente in un secondo momento.

A tal riguardo, i requisiti essenziali che vengono richiesti ad un SO sono tre:

1. possibilità di memorizzare grandi quantità di informazioni;

2. conservazione i dati anche dopo la terminazione del processo che li ha creati;

3. possibilità per più processi di accedere concorrentemente a tali informazioni.

Per raggiungere questi obiettivi la soluzione comune adottata da tutti i SO è quella di registrare i dati su dischi e altri supporti esterni, in unità dette

file (termine inglese che vuol dire archivio).

Il sottosistema del SO che si occupa della gestione dei file è detto File Management System (FMS).

I file di un sistema, inclusi quelli che servono al suo stesso funzionamento, sono raccolti in una struttura detta file system, che ha il compito di presentare

agli utenti un’interfaccia semplice e immediata per accedere ai dati.

 

A Cura di

Angelo Carpenzano (©)

 

 

Corso di Sistemi Operativi

 

Gestione del file system

Lezione 12

Parte 2 di 5

 

Le caratteristiche e l’organizzazione di un file system variano da un sistema ad un altro, ma presentano, complessivamente, dei punti in comune:

- I file sono un meccanismo di astrazione, cioè offrono un modo per memorizzare e recuperare dati su un disco, senza che l’utente debba preoccuparsi del

modo in cui tale servizio viene realizzato.

- Un processo che crea un nuovo file gli assegna un nome, permettendo ad altri processi di utilizzare quel nome per accedere alle informazioni che esso

contiene.

- Ad ogni file è associato un gruppo di attributi, come il nome del file, la data e l’ora di creazione, la data e l’ora dell’ultimo accesso, la data e l’ora

dell’ultima modifica, la dimensione, il proprietario, un flag di sola lettura (per indicare se è possibile leggere/scrivere il file o se è consentita la

sola lettura), un flag di sistema (per indicare se è un file utente normale o un file di sistema), un flag “nascosto” (per indicare se è un file da non

visualizzare nel listato del file system), campi di protezione e tanti altri.

 

 

A Cura di

Angelo Carpenzano (©)

 

 

Corso di Sistemi Operativi

 

Gestione del file system

Lezione 12

Parte 3 di 5

 

- Il file system viene generalmente organizzato in una struttura ad albero, per mezzo di opportuni contenitori chiamati directory, che possono raccogliere

al loro interno file e altre directory.

- Vengono fornite dal SO una serie di operazioni per creare, cancellare, leggere, scrivere e rinominare file e directory, nonché operazioni per leggerne

e/o scriverne gli attributi.

 

Sebbene questi ed altri meccanismi siano forniti da tutti i sistemi operativi, vi sono delle differenze significative.

Alcuni sistemi, come MS-DOS, nominano i file mediante un meccanismo di estensione, cioè dividono il nome del file in due parti separate da un punto, dando

un significato particolare alla parte del nome che segue il punto.

 

A Cura di

Angelo Carpenzano (©)

 

 

Corso di Sistemi Operativi

 

Gestione del file system

Lezione 12

Parte 4 di 5

 

Ad es. un file chiamato prog.c rappresenta, per sistemi che adottano questa convenzione, un programma sorgente scritto in linguaggio C.

Altri sistemi, come UNIX, lasciano all’utente piena libertà sul nome da assegnare, permettendo che il nome di un file abbia più estensioni; ad es. prog.c.tgz

può essere utilizzato per nominare un file sorgente C compresso.

Inoltre il numero ed il tipo di attributi che un file può avere dipendono fortemente dal SO.

Ad es. i sistemi Windows 9x e Me, che adottano un file system basato su MS-DOS, noto come FAT, non associano dei campi di protezione ai file, che così possono

essere acceduti da chiunque.

Invece i sistemi Windows NT e 2000 (che adottano il file system denominato NTFS) e quelli basati su UNIX, come Linux, FreeBSD, Solaris e altri, associano

ad ogni file dei bit di protezione, ad es. distinguendo tra l’utente proprietario, il gruppo di utenti del proprietario e tutti gli altri utenti del sistema

(questi concetti verrano chiariti nelle lezioni successive).

 

A Cura di

Angelo Carpenzano (©)

 

 

Corso di Sistemi Operativi

 

Gestione del file system

Lezione 12

Parte 5 di 5

 

 

Altra importante differenza è l’implementazione delle directory.

Tipicamente una directory contiene un certo numero di elementi, uno per ogni file e directory in essa contenuti.

Prima che un utente possa accedere ad un file, il SO deve esaminarne gli attributi per decidere se rendere possibile o meno l’accesso e per aggiornarne

alcuni, come ad es. la data e l’ora dell’ultimo accesso.

 

Il progettista di un SO può scegliere di memorizzare gli attributi del file nell’elemento corrispondente della directory oppure in altre strutture indirizzate

da quell’elemento (v. figura).

 

Nella prossima puntata vedremo come un SO gestisce la memoria secondaria.

 

A Cura di

Angelo Carpenzano (©)

 

 

Corso di Sistemi Operativi

 

Funzioni di un SO: gestione della memoria secondaria e dell’I/O

Lezione 13

Parte 1 di 5

 

Nelle scorse puntate abbiamo visto che, per rendere possibile la multiprogrammazione e il timesharing, si ricorre ad una gestione della memoria principale

che utilizza intensamente la memoria secondaria, con continui spostamenti di dati e programmi da e verso lo swap device.

Data l’elevata frequenza con cui viene richiesto questo trasferimento di informazioni, per gestire efficacemente un ambiente di questo tipo, un SO deve

offrire prestazioni elevate, riducendo al minimo il sovraccarico (overhead) dovuto a queste operazioni.

Per ottimizzare questi meccanismi, il SO deve fornire le seguenti funzionalità:

- tener conto dello spazio occupato sul disco e di quello inutilizzato;

- allocare spazio ai processi che lo richiedono e deallocarlo quando può essere liberato;

- schedulare le operazioni del disco rispetto a più richieste provenienti da processi utente e di sistema.

 

A Cura di

Angelo Carpenzano (©)

 

 

Corso di Sistemi Operativi

 

Funzioni di un SO: gestione della memoria secondaria e dell’I/O

Lezione 13

Parte 2 di 5

 

 

Un problema interessante che caratterizza fortemente un sistema è l’implementazione del file system, cioè il modo in cui vengono memorizzati file e directory,

e in particolare come vengono associati i blocchi di disco a ciascun file.

Il più semplice schema di allocazione prevede che ogni file sia costituito da blocchi contigui di dati sul disco.

In questo modo è più semplice tenere traccia della collocazione dei blocchi relativi ad un file (basta memorizzare l’indirizzo del primo blocco e la dimensione

dei dati) e l’accesso alle informazioni è più efficiente, perché è possibile leggere l’intero file con una sola operazione.

Tuttavia non è realizzabile, perché difficilmente si conosce a priori la grandezza massima di ogni file; inoltre porta ad una frammentazione del disco,

dovuta allo spreco di spazio che potrebbe essere utilizzato altrimenti.

 

A Cura di

Angelo Carpenzano (©)

 

 

Corso di Sistemi Operativi

 

Funzioni di un SO: gestione della memoria secondaria e dell’I/O

Lezione 13

Parte 3 di 5

 

Quest’ultimo problema potrebbe risolversi con la compattazione, o deframmentazione, che risulta spesso proibitivamente lunga e costosa (in termini di risorse

di sistema).

Le soluzioni più diffuse ricorrono ad un’allocazione a lista concatenata, in cui i blocchi associati ad un file sono sparpagliati nel disco.

Ogni blocco può contenere un puntatore al blocco successivo, oppure si può ricorrere ad una tabella, chiamata FAT (file allocation table) che contiene,

in ordine, i puntatori ai blocchi di disco costituenti il file e che deve essere costantemente mantenuta in memoria.

Utilizzare una lista concatenata di blocchi permette di non perdere spazio a causa della frammentazione del disco, ma, rispetto all’allocazione contigua,

rallenta l’accesso ai file.

Un ulteriore metodo per tenere traccia dei blocchi appartenenti ad un file consiste nell’associare a ogni file una piccola tabella, detta i-node, che elenca

gli attributi e gli indirizzi dei blocchi del file.

 

A Cura di

Angelo Carpenzano (©)

 

 

Corso di Sistemi Operativi

 

Funzioni di un SO: gestione della memoria secondaria e dell’I/O

Lezione 13

Parte 4 di 5

 

Questo schema, utilizzato in UNIX e nei suoi “derivati”, è molto flessibile e consente di avere una frammentazione del disco praticamente nulla.

 

Accenniamo adesso ad un’altra utile funzione dei SO, la gestione dell’I/O, il cui scopo è quello di nascondere sia all’utente che al sistema, le caratteristiche

dei dispositivi di input/output.

Nel sottositema di I/O possiamo trovare essenzialmente tre elementi:

- gestione della memoria, per ottimizzare gli scambi di informazioni tra la memoria centrale e i dispositivi;

- una collezione di driver associati ai vari dispositivi del sistema, contenenti tutte le caratteristiche che dipendono dall’hardware;

- presentazione di un’interfaccia generica, che permette ai programmatori di utilizzare in maniera uniforme i driver dei dispositivi.

 

A Cura di

Angelo Carpenzano (©)

 

 

Corso di Sistemi Operativi

 

Funzioni di un SO: gestione della memoria secondaria e dell’I/O

Lezione 13

Parte 5 di 5

 

Una caratteristica molto importante dei sistemi UNIX, che vale la pena di citare, è il buffer cache, una particolare soluzione adottata per ottimizzare

l’accesso al disco, che utilizza la memoria principale come una “cache” per aumentare le prestazioni di I/O.

Infatti, ogni blocco di disco che deve essere letto e/o scritto viene prima caricato in questa struttura, che viene utilizzata direttamente dai processi

in modo da non dover ricorrere al disco ogni qualvolta occorre accedere a quel blocco.

Poiché la memoria principale è molto più veloce dei dischi, il buffer cache produce un sostanziale miglioramento delle prestazioni, riducendo le operazioni

di I/O solo al momento in cui sono necessarie.

 

A Cura di

Angelo Carpenzano (©)