  The Unix and Internet Fundamentals HOWTO
  Eric S. Raymond
  v1.4, 25 settembre 1999

  Questo documento descrive il funzionamento di base dei computer di
  classe PC, i sistemi operativi di tipo Unix e Internet senza far uso
  di un linguaggio troppo tecnico.  Traduzione a cura di Mirko Nasato,
  mnasato@iol.it.
  ______________________________________________________________________

  Indice Generale


  1. Introduzione
     1.1 Scopo di questo documento

  2. Novit
     2.1 Risorse correlate
     2.2 Nuove versioni di questo documento
     2.3 Commenti, suggerimenti e correzioni

  3. Anatomia di base del computer
  4. Cosa succede quando si accende un computer?
  5. Che cosa accade con il log in?
  6. Cosa succede quando si eseguono i programmi dalla shell?
  7. Come funzionano i dispositivi di input e gli interrupt?
  8. Come fa il computer a fare diverse cose contemporaneamente?
  9. Come fa il computer a evitare che i processi si intralcino tra loro?
  10. Come fa il computer a immagazzinare le cose in memoria?
     10.1 Numeri
     10.2 Caratteri

  11. Come fa il computer a immagazzinare le cose su disco?
     11.1 Struttura di basso livello del disco e del file system
     11.2 Nomi dei file e delle directory
     11.3 Mount point
     11.4 Come viene cercato un file
     11.5 Proprietari dei file, autorizzazioni e sicurezza
     11.6 Come le cose possono andare male

  12. Come funzionano i linguaggi per computer?
     12.1 Linguaggi compilati
     12.2 Linguaggi interpretati
     12.3 Linguaggi a codice P

  13. Come funziona Internet?
     13.1 Nomi e locazioni
     13.2 Pacchetti e router
     13.3 TCP e IP
     13.4 HTTP, un protocollo applicativo


  ______________________________________________________________________

  11..  IInnttrroodduuzziioonnee



  11..11..  SSccooppoo ddii qquueessttoo ddooccuummeennttoo

  Questo documento vuole essere un aiuto per gli utenti di Linux e di
  Internet che stanno imparando dalla pratica. Anche se il ``learning by
  doing''  un ottimo metodo per acquisire competenze specifiche, a
  volte lascia determinate lacune nella conoscenza delle basi che
  possono rendere difficile il pensiero creativo o la risoluzione
  efficace dei problemi, a causa della mancanza di un chiaro modello
  mentale relativo a cosa sta succedendo nella realt.

  Cercher di descrivere con un linguaggio chiaro e semplice come
  funziona il tutto. La presentazione sar calibrata per persone che
  usano Unix o Linux su hardware di classe PC. Di solito far comunque
  riferimento semplicemente a `Unix', dato che la maggior parte delle
  descrizioni vale anche per altre piattaforme e varianti Unix.

  Assumer che stiate usando un PC Intel. I dettagli differiscono
  leggermente se lavorate su un Alpha o un PowerPC o qualche altro
  computer Unix, ma i concetti di base sono gli stessi.

  Non ripeter le cose, quindi dovrete stare attenti, ma ci significa
  anche che imparerete da ogni parola che leggete.  una buona idea
  limitarsi a dare una scorsa la prima volta che leggete; dovreste poi
  tornare indietro e rileggere alcune volte finch avrete digerito
  quello che avete imparato.

  Questo  un documento in evoluzione. Intendo continuare ad aggiungere
  sezioni in risposta agli stimoli dei lettori, pertanto periodicamente
  dovreste tornare a rivederlo.


  22..  NNoovviitt

  Novit nella versione 1.2: Sezione `Come fa il computer a
  immagazzinare le cose in memoria?'.  Novit nella versione 1.3:
  Sezione `Che cosa accade con il log in?' e `Proprietari dei file,
  autorizzazioni e sicurezza'.


  22..11..  RRiissoorrssee ccoorrrreellaattee

  Se state leggendo questo documento al fine di imparare come diventare
  un hacker, dovreste anche leggere la How To Become A Hacker FAQ
  <http://www.tuxedo.org/~esr/faqs/hacker-howto.html>.  Contiene dei
  link ad altre risorse utili.


  22..22..  NNuuoovvee vveerrssiioonnii ddii qquueessttoo ddooccuummeennttoo

  Nuove versioni dello Unix and Internet Fundamentals HOWTO verranno
  periodicamente postate su comp.os.linux.help, comp.os.linux.announce e
  news.answers <news:answers>.  Saranno anche depositate su vari siti
  WWW e FTP dedicati a Linux, inclusa la LDP home page.

  Potete vedere l'ultima versione sul World Wide Web all'URL
  <http://metalab.unc.edu/LDP/HOWTO/Fundamentals-HOWTO.html>.


  22..33..  CCoommmmeennttii,, ssuuggggeerriimmeennttii ee ccoorrrreezziioonnii

  Se avete domande o commenti su questo documento sentitevi liberi di
  contattare Eric S. Raymond all'indirizzo esr@thyrsus.com.  Qualsiasi
  suggerimento o critica sar il benvenuto. Apprezzo particolarmente
  link a spiegazioni pi dettagliate dei singoli concetti. Se trovate un
  errore per favore fatemelo sapere, in modo che lo possa correggere
  nella prossima versione. Grazie.


  33..  AAnnaattoommiiaa ddii bbaassee ddeell ccoommppuutteerr

  Dentro al vostro computer c' un chip processore che compie
  l'elaborazione vera e propria. C' una memoria interna (quella che la
  gente DOS/Windows chiama ``RAM'' e la gente Unix spesso chiama
  ``core''). Il processore e la memoria risiedono sulla _s_c_h_e_d_a _m_a_d_r_e,
  che  il cuore del vostro computer.

  Il vostro computer ha uno schermo e una tastiera. Ha dischi fissi e
  dischi floppy. Lo schermo e i dischi hanno _s_c_h_e_d_e _c_o_n_t_r_o_l_l_e_r che si
  attaccano sulla scheda madre e aiutano il computer a gestire questi
  dispositivi.  (La tastiera  troppo semplice per aver bisogno di una
  scheda separata; il controller  costruito all'interno della tastiera
  stessa.)

  Scenderemo pi avanti in alcuni dei dettagli relativi al funzionamento
  di questi dispositivi. Per ora, ecco alcune cose di base da tenere a
  mente su come funzionano assieme:

  Tutte le parti interne del vostro computer sono collegate da un _b_u_s.
  Fisicamente, il bus  quello dove si attaccano le schede controller
  (la scheda video, il controller del disco, una scheda audio se ce
  l'avete). Il bus  l'autostrada dei dati tra il processore, lo
  schermo, il disco e tutto il resto.

  Il processore, che fa funzionare tutto il resto, in realt non  in
  grado di vedere direttamente nessuno degli altri pezzi: deve
  comunicare con loro attraverso il bus. L'unico sottosistema al quale
  ha accesso veramente rapido, immediato,  la memoria (core). Perch i
  programmi siano eseguiti, dunque, devono essere _i_n _m_e_m_o_r_i_a.

  Quando il vostro computer legge un programma o dei dati dal disco in
  effetti succede che il processore usa il bus per spedire una richiesta
  di lettura disco al controller del disco. Dopo un po' di tempo il
  controller del disco usa il bus per segnalare al computer che ha letto
  i dati e li ha messi in una certa locazione di memoria. Il processore
  pu allora usare il bus per guardare in quella memoria.

  Anche la tastiera e lo schermo comunicano con il processore attraverso
  il bus, ma in modi pi semplici. Ne discuteremo pi avanti. Per ora,
  ne sapete abbastanza per capire cosa succede quando accendete il
  vostro computer.


  44..  CCoossaa ssuucccceeddee qquuaannddoo ssii aacccceennddee uunn ccoommppuutteerr??

  Un computer senza un programma in esecuzione  soltanto un ammasso
  inerte di componenti elettronici. La prima cosa che un computer deve
  fare quando viene acceso  far partire un programma speciale chiamato
  _s_i_s_t_e_m_a _o_p_e_r_a_t_i_v_o. Il compito del sistema operativo  aiutare gli
  altri programmi del computer a funzionare, gestendo gli intricati
  dettagli relativi al controllo dell'hardware del computer.

  Il processo di avvio del sistema operativo si chiama _b_o_o_t (in origine
  era _b_o_o_t_s_t_r_a_p e alludeva alla difficolt di tirarsi su da solo, ``by
  your bootstraps'').  Il vostro computer sa come avviarsi perch le
  istruzioni per il boot sono incorporate in uno dei suoi chip, il BIOS
  (Basic Input/Output System).

  Il chip BIOS gli dice di cercare uno speciale programma chiamato _b_o_o_t
  _l_o_a_d_e_r (quello di Linux si chiama LILO) che si trova in un posto
  predefinito del disco fisso con numero pi basso (il _d_i_s_c_o _d_i _a_v_v_i_o).
  Il compito del boot loader  far partire il sistema operativo vero e
  proprio.

  Per compiere quest'ultima operazione il loader cerca un _k_e_r_n_e_l, lo
  carica in memoria e lo fa partire. Quando avviate Linux e vedete
  ``LILO'' sullo schermo, seguito da una riga di puntini, vuol dire che
  sta caricando il kernel. (Ogni puntino significa che ha caricato un
  altro _b_l_o_c_c_o _d_e_l _d_i_s_c_o di codice kernel).


  (Vi potreste chiedere come mai il BIOS non carica il kernel
  direttamente: perch questo processo a due stadi con il boot loader?
  Beh, il BIOS non  molto intelligente. In effetti  proprio stupido, e
  Linux non lo usa pi dopo la fase di avvio. Fu scritto in origine per
  i PC primitivi a 8 bit con dischi poco capienti e proprio non riesce
  ad accedere a una parte abbastanza grande del disco per caricare
  direttamente il kernel. La fase del boot loader consente anche di far
  partire diversi sistemi operativi da posti diversi del vostro disco,
  nella improbabile circostanza che Unix non vi soddisfi a sufficienza.)

  Dopo essere partito, il kernel si guarda in giro, trova il resto
  dell'hardware e si prepara a far girare i programmi. Fa tutto questo
  guardando non nelle ordinarie locazioni di memoria ma piuttosto alle
  _p_o_r_t_e _I_/_O, speciali indirizzi bus che probabilmente hanno schede
  controller di dispositivi che sono in ascolto in attesa di comandi. Il
  kernel non cerca a caso; ha molta conoscenza innata su cosa 
  probabile trovare dove, e su come i controller rispondono se sono
  presenti. Questo processo si chiama _a_u_t_o_r_i_l_e_v_a_m_e_n_t_o.

  La maggior parte dei messaggi che vedete durante la fase di avvio sono
  del kernel che fa l'autorilevamento del vostro hardware attraverso le
  porte I/O, riconosce cosa ha a sua disposizione e si adatta al vostro
  computer. Il kernel di Linux  estremamente bravo in questo, meglio
  della maggior parte degli altri Unix e _m_o_l_t_o meglio del DOS o di
  Windows. Infatti, molti linuxiani della prima ora pensano che
  l'intelligenza del rilevamento all'avvio di Linux (che lo rende
  relativamente facile da installare) sia stata una delle principali
  ragioni che lo hanno fatto sfondare dal mucchio di esperimenti di Unix
  liberi, attraendo una massa critica di utenti.

  Ma avere il kernel del tutto caricato e funzionante non  la fine del
  processo di boot; ne  solo il primo stadio (a volte chiamato _r_u_n
  _l_e_v_e_l _1, livello di esecuzione 1). A questo punto il kernel passa il
  controllo a un processo speciale chiamato `init' che esegue diverse
  attivit comuni.

  Il primo compito del processo init  assicurarsi che i vostri dischi
  siano a posto. I file system dei dischi sono fragili: se vengono
  danneggiati da un malfunzionamento hardware o da un'improvvisa
  mancanza di elettricit, ci sono buoni motivi per compiere alcune
  operazioni di riaggiustamento prima che il vostro Unix sia tutto a
  posto. Parleremo pi approfonditamente di questo pi avanti, a
  proposito di ``come i file system si possono danneggiare''.

  Il passo successivo del kernel  far partire diversi _d_e_m_o_n_i. Un demone
  (o daemon)  un programma quale uno spooler di stampa, un programma
  che attende di ricevere posta in arrivo oppure un server WWW che
  rimane latente in sottofondo, aspettando qualcosa da fare. Questi
  programmi speciali devono spesso coordinare diverse richieste che
  rischiano di entrare in conflitto.  Sono demoni perch spesso  pi
  facile scrivere un programma che gira costantemente e viene a
  conoscenza di tutte le richieste piuttosto che cercare di assicurarsi
  che un gruppo di copie (che girano tutte contemporaneamente, con
  ciascuna che processa una richiesta) non si ostacolino a vicenda.  La
  particolare serie di demoni che il vostro sistema fa partire pu
  variare, ma quasi certamente include uno spooler di stampa (un demone
  che fa da `portinaio' per la vostra stampante).

  Una volta che tutti i demoni sono avviati ci troviamo al _r_u_n _l_e_v_e_l _2.
  Il prossimo passo  prepararsi per gli utenti. Init avvia una copia di
  un programma chiamato getty per controllare la vostra console (e forse
  altre copie per controllare le porte seriali dial-in). Questo
  programma  quello che emette il prompt login alla vostra console.
  Siamo ora al _r_u_n _l_e_v_e_l _3, pronti per fare il log in e lanciare i
  programmi.

  55..  CChhee ccoossaa aaccccaaddee ccoonn iill lloogg iinn??

  Quando fate il log in (date un nome e la password) vi identificate a
  getty e al computer. Parte allora un altro programma chiamato
  (ovviamente) login, che controlla se siete autorizzati a usare quella
  macchina. Se non lo siete, il tentativo di log in viene rifiutato. Se
  lo siete, login compie qualche operazione di servizio e poi fa partire
  un interprete di comandi, la _s_h_e_l_l. (S, getty e login potrebbero
  essere un solo programma. Sono separati per motivi storici che qui non
  vale la pena approfondire.)

  Ecco pi in dettaglio che cosa accade prima che compaia la shell; sar
  necessario comprenderlo pi avanti quando parleremo di autorizzazioni
  dei file. Si viene identificati con un nome di login e password.
  Questo nome di login viene cercato in un file chiamato /etc/password,
  costituito da una sequenza di righe ciascuna delle quali descrive un
  account utente.

  Uno di questi campi  una versione cifrata della password
  dell'account. Quello che inserite come password viene cifrato
  esattamente allo stesso modo e il programma login controlla se
  corrispondono. La sicurezza di questo metodo dipende dal fatto che,
  mentre  facile passare da una password in chiaro a una cifrata,
  l'inverso  molto difficile. Per cui, se qualcuno riesce a vedere la
  versione cifrata della vostra password non pu comunque usare il
  vostro account. (Significa anche che se dimenticate la vostra
  password, non c' modo di recuperarla, ma solamente di cambiarla in
  un'altra di vostra scelta.)

  Una volta effettuato il log in con successo, otterrete tutti i
  privilegi associati al singolo account che state utilizzando. Potreste
  anche essere riconosciuti come appartenenti a un _g_r_o_u_p. Un gruppo  un
  insieme di utenti impostato dall'amministratore e a cui  associato un
  nome. I gruppi possono avere privilegi indipendentemente dai privilegi
  dei loro membri. Un utente pu appartenere a pi gruppi. (Per maggiori
  dettagli sul funzionamento dei privilegi in Unix si veda la sezione su
  ``''.)

  (Si noti che, sebbene si fa normalmente riferimento agli utenti e ai
  gruppi per nome, essi sono in realt memorizzati internamente come ID
  numerici. Il file password associa il vostro nome di account a un ID
  utente; il file /etc/group associa i nomi di gruppo agli ID numerici
  dei gruppi. I comandi che hanno a che fare con account e gruppi
  effettuano automaticamente la conversione.)

  La vostra registrazione di account contiene anche la vostra _h_o_m_e
  _d_i_r_e_c_t_o_r_y, il posto nel file system Unix che contiene i vostri file
  personali. Infine, la registrazione dell'account imposta anche la
  _s_h_e_l_l, l'interprete di comandi che login avvier per accettare i
  vostri comandi.


  66..  CCoossaa ssuucccceeddee qquuaannddoo ssii eesseegguuoonnoo ii pprrooggrraammmmii ddaallllaa sshheellll??

  La shell normale vi presenta il prompt '$' che vedete dopo il login (a
  meno che non lo abbiate personalizzato). Non parleremo della sintassi
  della shell e delle cose semplici che potete vedere da soli sullo
  schermo; daremo piuttosto uno sguardo dietro le quinte a quello che
  succede dal punto di vista del computer.

  Dopo la fase di avvio, e prima che sia eseguito un programma, potete
  pensare al vostro computer come a un contenitore di un repertorio di
  processi che stanno tutti aspettando qualcosa da fare. Stanno tutti
  aspettando degli _e_v_e_n_t_i. Un evento pu essere voi che premete un tasto
  o muovete il mouse. Oppure, se il vostro computer  collegato a una
  rete, un evento pu essere un pacchetto di dati che arriva lungo
  quella rete.

  Il kernel  uno di questi processi.  uno speciale, perch controlla
  quando gli altri _p_r_o_c_e_s_s_i _u_t_e_n_t_e possono girare ed  normalmente
  l'unico processo con accesso diretto all'hardware del computer.
  Infatti, i processi utente devono fare richiesta al kernel quando
  vogliono ottenere un input dalla tastiera, scrivere sullo schermo,
  leggere o scrivere su disco o fare qualsiasi altra cosa che non sia
  macinare bit in memoria. Queste richieste sono note come _c_h_i_a_m_a_t_e _d_i
  _s_i_s_t_e_m_a.

  Normalmente tutto l'I/O passa attraverso il kernel, cos quest'ultimo
  pu organizzare le operazioni e impedire che i processi si ostacolino
  a vicenda. Alcuni processi utente speciali hanno il permesso di
  aggirare il kernel, di solito per ottenere accesso diretto alle porte
  I/O. I server X (i programmi che gestiscono le richieste degli altri
  programmi di generare grafica sullo schermo, sulla maggior parte dei
  computer Unix) sono gli esempi pi comuni al riguardo. Ma non siamo
  ancora arrivati a un server X; state guardando il prompt della shell
  su una console a caratteri.

  La shell  solo un processo utente, e neppure uno tanto speciale.
  Attende che voi digitiate qualcosa, ascoltando (attraverso il kernel)
  sulle porte I/O della tastiera. Come il kernel vede che avete digitato
  qualcosa lo visualizza sullo schermo e poi lo passa alla shell. Quando
  il kernel vede un `Invio' passa la vostra linea di testo alla shell.
  La shell tenta di interpretare questo testo come se si trattasse di
  comandi.

  Diciamo che digitate `ls' e Invio per invocare il programma Unix che
  elenca le directory. La shell applica le sue regole incorporate per
  indovinare che volete lanciare il comando eseguibile nel file
  `/bin/ls'. Fa una chiamata di sistema chiedendo al kernel di far
  partire /bin/ls come un nuovo processo _f_i_g_l_i_o e di dargli accesso allo
  schermo e alla tastiera attraverso il kernel. Poi la shell va a
  dormire, aspettando che ls finisca.

  Quando /bin/ls ha finito dice al kernel che ha terminato emettendo una
  chiamata di sistema _e_x_i_t. Il kernel allora sveglia la shell e le dice
  che pu riprendere a girare. La shell emette un altro prompt e attende
  un'altra linea di input.

  Tuttavia (supponiamo che stiate elencando una directory molto lunga)
  potrebbero succedere altre cose mentre `ls'  in esecuzione.  Potreste
  passare su un'altra console virtuale, fare il log in di l e iniziare
  una partita a Quake, per esempio. Oppure immaginate di essere
  collegati a Internet. Il vostro computer potrebbe spedire o ricevere
  posta mentre /bin/ls  in esecuzione.


  77..  CCoommee ffuunnzziioonnaannoo ii ddiissppoossiittiivvii ddii iinnppuutt ee ggllii iinntteerrrruupptt??

  La tastiera  un dispositivo di input molto semplice: semplice perch
  genera piccole quantit di dati molto lentamente (per gli standard di
  un computer). Quando premete o rilasciate un tasto, il valore di
  questo evento viene segnalato attraverso il cavo della tastiera per
  far scattare un _i_n_t_e_r_r_u_p_t _h_a_r_d_w_a_r_e.

   compito del sistema operativo stare attento a questi interrupt. Per
  ogni possibile tipo di interrupt c' un _g_e_s_t_o_r_e _d_e_l_l_'_i_n_t_e_r_r_u_p_t, una
  parte del sistema operativo che immagazzina i dati a esso associati
  (come il valore del vostro premere/rilasciare il tasto) finch pu
  essere processato.

  Quello che effettivamente fa il gestore dell'interrupt della vostra
  tastiera  mettere il valore del tasto in un'area di sistema vicino al
  fondo della memoria. L rimane a disposizione per ispezione quando il
  sistema operativo passa il controllo al programma che ritiene stia
  attualmente leggendo dalla tastiera.

  Dispositivi di input pi complessi come i dischi o le schede di rete
  funzionano in modo simile. Sopra abbiamo fatto il caso di un
  controller del disco che usa il bus per segnalare che una richiesta
  disco  stata ultimata. In realt succede che il disco fa scattare un
  interrupt. Il gestore dell'interrupt del disco copia poi in memoria i
  dati ottenuti, a uso successivo da parte del programma che aveva fatto
  la richiesta.

  A ogni tipo di interrupt  associato un _l_i_v_e_l_l_o _d_i _p_r_i_o_r_i_t_. Gli
  interrupt con priorit pi bassa (come gli eventi della tastiera)
  devono dare la precedenza agli interrupt con priorit pi alta (come i
  tick dell'orologio o gli eventi del disco). Unix  progettato per dare
  alta priorit al tipo di eventi che hanno bisogno di essere processati
  rapidamente, in modo da mantenere fluida la risposta del computer.

  Tra i messaggi d'avvio del vostro SO potete vedere dei riferimenti a
  numeri di _I_R_Q. Forse sapete, senza capirne esattamente il perch, che
  uno dei modi pi comuni di configurare male l'hardware  avere due
  dispositivi diversi che cercano di usare lo stesso IRQ.

  Ecco la spiegazione. IRQ  l'abbreviazione di ``Interrupt Request''
  (richiesta di interrupt). Il sistema operativo ha bisogno di sapere al
  momento dell'avvio quali interrupt numerati verranno usati da ciascun
  dispositivo hardware, in modo da poter associare a ciascuno il gestore
  appropriato. Se due dispositivi diversi cercano di usare lo stesso IRQ
  a volte gli interrupt verranno notificati al gestore sbagliato. Questo
  di solito provocher quantomeno il blocco del dispositivo, ma pu a
  volte confondere il SO a tal punto da farlo diventare instabile oppure
  mandarlo in crash.


  88..  CCoommee ffaa iill ccoommppuutteerr aa ffaarree ddiivveerrssee ccoossee ccoonntteemmppoorraanneeaammeennttee??

  Non lo fa, in realt. I computer possono svolgere soltanto un task (o
  _p_r_o_c_e_s_s_o) alla volta. Ma un computer pu cambiare task molto
  rapidamente e indurre i lenti esseri umani a pensare che sta facendo
  diverse cose contemporaneamente. Questo viene chiamato _t_i_m_e_s_h_a_r_i_n_g
  (condivisione di tempo).

  Uno dei compiti del kernel  gestire il timesharing. Ha una parte
  chiamata _s_c_h_e_d_u_l_e_r (pianificatore) che contiene informazioni relative
  a tutti gli altri processi (a parte il kernel) del vostro repertorio.
  Ogni sessantesimo di secondo nel kernel fa scattare un timer e viene
  generato un clock di interrupt. Lo scheduler ferma qualunque processo
  sia attualmente in esecuzione, lo sospende sul posto e passa il
  controllo a un altro processo.

  Un sessantesimo di secondo pu non sembrare una grande quantit di
  tempo. Ma per i microprocessori odierni  sufficiente per eseguire
  decine di migliaia di istruzioni macchina, che si possono tradurre in
  una gran mole di lavoro. Quindi anche se ci sono molti processi
  ciascuno di essi pu fare molte cose nella porzione di tempo a sua
  disposizione.

  In pratica non sempre un programma ottiene la sua intera porzione di
  tempo. Se scatta un interrupt da un dispositivo I/O il kernel ferma
  effettivamente il task corrente, esegue il gestore dell'interrupt e
  poi ritorna al task corrente. Una tempesta di interrupt ad alta
  priorit pu scombinare il normale funzionamento dei processi; questo
  fenomeno viene chiamato _t_h_r_a_s_h_i_n_g e per fortuna  molto difficile da
  indurre negli Unix moderni.

  Infatti la velocit dei programmi solo molto di rado  limitata dalla
  quantit di tempo macchina a loro disposizione (ci sono alcune
  eccezioni a questa regola, quali il suono o la generazione di grafica
  3D). Molto pi spesso dei ritardi si generano quando il programma deve
  attendere dei dati da un disco o da una connessione di rete.

  Un sistema operativo che pu di norma gestire pi processi
  simultaneamente  detto ``multitasking''. La famiglia di sistemi
  operativi Unix  stata progettata fin dall'inizio per il multitasking
  e lo fa molto bene, in modo molto pi efficace rispetto a Windows o al
  Mac OS ai quali il multitasking  stato appiccicato a posteriori in
  seguito a un ripensamento e lo fanno in modo piuttosto povero. Il
  multitasking efficiente e affidabile costituisce buona parte di ci
  che rende Linux superiore per le applicazioni di rete, le
  comunicazioni e i servizi Web.


  99..  CCoommee ffaa iill ccoommppuutteerr aa eevviittaarree cchhee ii pprroocceessssii ssii iinnttrraallcciinnoo ttrraa
  lloorroo??

  Lo scheduler del kernel si prende cura di dividere il tempo tra i
  processi. Il vostro sistema operativo deve dividere tra i processi
  anche lo spazio, per evitare che non sconfinino oltre la porzione di
  memoria loro assegnata. Le operazioni compiute dal sistema operativo
  per risolvere questo problema si chiamano _g_e_s_t_i_o_n_e _d_e_l_l_a _m_e_m_o_r_i_a.

  Ogni processo del vostro repertorio ha la propria area di memoria
  core, come luogo dal quale eseguire il proprio codice e dove
  immagazzinare le variabili e i risultati. Potete pensare a questo
  insieme come formato da un _s_e_g_m_e_n_t_o _c_o_d_i_c_e, di sola lettura (che
  contiene le istruzioni del processo), e da un _s_e_g_m_e_n_t_o _d_a_t_i (che
  contiene tutte le variabili immagazzinate dal processo). Il segmento
  dati  sempre unico per ogni processo, mentre nel caso due processi
  usino lo stesso codice Unix automaticamente fa in modo che condividano
  un unico segmento codice, come misura di efficienza.

  L'efficienza  importante, perch la memoria core  costosa. A volte
  non ne avete abbastanza per contenere per intero tutti i programmi che
  il computer sta eseguendo, specialmente se usate un grosso programma
  quale un server X. Per ovviare a questo problema Unix usa una
  strategia chiamata _m_e_m_o_r_i_a _v_i_r_t_u_a_l_e. Non cerca di tenere in core tutti
  i dati e il codice di un processo. Tiene piuttosto caricato solo un
  _w_o_r_k_i_n_g _s_e_t relativamente piccolo; il resto dello stato del processo
  viene lasciato in uno speciale _s_p_a_z_i_o _s_w_a_p sul vostro disco fisso.

  Come i processi sono in esecuzione Unix tenta di anticipare i
  cambiamenti del working set per avere in memoria solo le parti che
  servono davvero. Riuscirci in modo efficace  ingegnoso e complesso,
  pertanto non cercher di descriverlo tutto qui, ma si basa sul fatto
  che il codice e i riferimenti ai dati tendono a comparire a gruppi, ed
   probabile che un nuovo gruppo si colleghi a luoghi vicini a quelli
  di uno precedente. Quindi se Unix tiene caricati i dati e il codice
  usati pi di frequente (o di recente) di solito riuscir a risparmiare
  del tempo.

  Notate che in passato quel ``A volte'' di due paragrafi fa era un
  ``Quasi sempre'', perch la dimensione della memoria era tipicamente
  ridotta rispetto alla dimensione dei programmi in esecuzione, quindi
  il ricorso allo swap era frequente. Oggi la memoria  molto meno
  costosa e persino i computer di fascia bassa ne hanno parecchia. Sui
  moderni computer monoutente con 64MB di memoria e oltre  possibile
  eseguire X e un insieme tipico di programmi senza neppure ricorrere
  allo swap.

  Anche in questa felice situazione la parte del sistema operativo
  chiamata _g_e_s_t_o_r_e _d_e_l_l_a _m_e_m_o_r_i_a mantiene un importante ruolo da
  svolgere. Deve garantire che i programmi possano modificare soltanto
  il proprio segmento dati; deve cio impedire che del codice difettoso
  o malizioso in un programma rovini i dati di altri programmi. A questo
  scopo tiene una tabella dei segmenti dati e codice. La tabella 
  aggiornata non appena un processo richiede pi memoria oppure libera
  memoria (quest'ultimo caso si verifica di solito all'uscita dal
  programma).

  Questa tabella  usata per passare comandi a una parte specializzata
  dell'hardware sottostante chiamata _M_M_U o _u_n_i_t_ _d_i _g_e_s_t_i_o_n_e _d_e_l_l_a
  _m_e_m_o_r_i_a. I processori moderni hanno MMU incorporate. La MMU ha la
  peculiare capacit di porre dei delimitatori attorno alle aree di
  memoria, in modo che un riferimento che sconfina venga rifiutato e
  faccia scattare uno speciale interrupt.

  Se avete mai visto un messaggio del tipo ``Segmentation fault'',
  ``core dumped'' o qualcosa del genere, questo  esattamente quello che
   successo: un tentativo da parte del programma in esecuzione di
  accedere alla memoria al di fuori dal proprio segmento ha fatto
  scattare un interrupt fatale. Questo rivela un bug nel codice del
  programma; il _c_o_r_e _d_u_m_p (scarico della memoria) che lascia dietro di
  s costituisce una informazione diagnostica volta ad aiutare il
  programmatore nell'individuazione del problema.

  C' un altro aspetto che protegge i processi l'uno dall'altro, oltre
  alla limitazione della memoria a cui possono accedere. Si vuole anche
  poter controllare il loro accesso ai file in modo che un programma
  difettoso o malizioso non possa rovinare parti critiche del sistema. 
  per questo motivo che Unix possiede le ``autorizzazioni sui file'' che
  vedremo in dettaglio pi avanti.


  1100..  CCoommee ffaa iill ccoommppuutteerr aa iimmmmaaggaazzzziinnaarree llee ccoossee iinn mmeemmoorriiaa??

  Probabilmente saprete che ogni cosa in un computer viene memorizzata
  come stringa di bit (binary digit; possiamo immaginarli come molti
  piccoli interruttori). Ora vedremo come questi bit vengano impiegati
  per rappresentare le lettere e i numeri che il computer manipola.

  Prima di poter affrontare questo argomento,  necessario comprendere
  la _d_i_m_e_n_s_i_o_n_e _d_i _p_a_r_o_l_a del computer. Si tratta della dimensione
  preferita dal computer per spostare unit di informazioni;
  tecnicamente  l'ampiezza dei _r_e_g_i_s_t_r_i dei processore, ovvero le aree
  che il processore utilizza per compiere calcoli logici e aritmetici.
  Quando leggiamo che i computer hanno dimensione in bit (per esempio
  ``32-bit'' o ``64-bit'') ecco che cosa si intende.

  La maggior parte dei computer (compresi i PC 386, 486, Pentium e
  Pentium II) ha una dimensione di parola di 32 bit. Le vecchie macchine
  286 lavoravano a 16. Mainframe vecchio stile spesso hanno parole di 36
  bit. Pochi processori (come Alpha di quella che prima era la DEC e ora
   Compaq) hanno parole di 64 bit. La parola di 64 bit diverr pi
  comune nei prossimi cinque anni; Intel sta progettando di sostiuire il
  Pentium II con un chip a 64 bit chiamato `Merced'.

  Il computer vede la memoria core come sequenza di parole numerate da
  zero in avanti, fino a valori molto grandi a seconda della dimensione
  della memoria. Tale valore  limitato dalla dimensione della parola,
  motivo per cui le vecchie macchine come i 286 dovevano svolgere
  complicati contorsionismi per indirizzare grandi quantit di memoria.
  Non li descriver qui; procurano ancora degli incubi ai vecchi
  programmatori.



  1100..11..  NNuummeerrii

  I numeri sono rappresentati come parole o coppie di parole, a seconda
  della dimensione di parola del processore. Su macchine a 32 bit, la
  parola  la dimensione pi comune.

  L'aritmetica degli interi  simile ma non  esattamente identica alla
  matematica in base due. Il bit di ordine pi basso  1, il successivo
  2, poi 4 e cos via in notazione binaria. Ma i numeri dotati di segno
  sono rappresentati in notazione _c_o_m_p_l_e_m_e_n_t_o _a _d_u_e.  Il bit di ordine
  pi alto  un _b_i_t _d_i _s_e_g_n_o che rende negativa la quantit
  rappresentata, mentre ogni numero negativo pu essere ottenuto dal
  valore positivo corrispondente invertendo tutti i bit.  per questo
  motivo che gli interi su una macchina a 32 bit devono essere compresi
  nell'intervallo tra -2^31 + 1 e 2^31 - 1 (dove ^  l'operatore di
  elevamento a potenza, 2^3 = 8). Il 32-esimo bit  usato per il segno.

  Alcuni linguaggi di programmazione danno accesso a una _a_r_i_t_m_e_t_i_c_a
  _s_e_n_z_a _s_e_g_n_o ovvero una artimetica in base 2 con solo i numeri positivi
  e lo zero.

  La maggior parte dei processori e alcuni linguaggi possono manipolare
  numeri in _v_i_r_g_o_l_a _m_o_b_i_l_e (funzionalit incorporata nel chip di tutti i
  processori recenti). I numeri in virgola mobile forniscono un
  intervallo pi ampio degli interi e consentono di esprimere le
  frazioni. I modi in cui questo avviene sono diversi e un po' troppo
  complicati per essere affrontati in dettaglio in questa sede.
  Tuttavia, l'idea generale  molto simile alla cosiddetta `notazione
  scientifica', dove si pu scrivere (per esempio) 1.234 * 10^23; la
  codifica del numero viene divisa in una _m_a_n_t_i_s_s_a (1.234) e in un
  _e_s_p_o_n_e_n_t_e (23) che indica le potenze di dieci.


  1100..22..  CCaarraatttteerrii

  I caratteri sono normalmente rappresentati come stringhe di sette bit,
  in una codifica chiamata ASCII (American Standard Code for Information
  Interchange). Sulle macchine moderne, ciascuno dei 128 caratteri ASCII
   dato dai sette bit pi bassi di un _o_t_t_e_t_t_o a 8 bit; gli ottetti sono
  riuniti in parole di memoria in modo che (per esempio) una stringa di
  sei caratteri occupi solamente due parole di memoria. Per vedere una
  mappa dei caratteri ASCII, scrivere `man 7 ascii' al prompt di Unix.

  Il paragrafo precedente, per, non  completamente corretto, per due
  ragioni. Quella minore  che il termine `ottetto'  formalmente
  corretto ma raramente utilizzato; la maggior parte delle persone si
  riferisce a un ottetto come a un _b_y_t_e e ritiene che i byte siano
  lunghi otto bit. Per essere corretti, il termine `byte'  pi
  generale; per esempio, ci sono state macchine a 36 bit con byte di 9
  bit (anche se probabilmente non capiter pi in futuro).

  La ragione principale , invece, che non tutto il mondo usa i codici
  ASCII. Infatti, molti paesi non possono usarli: mentre i codici ASCII
  funzionano bene per l'inglese americano, non contengono molte
  accentate e caratteri speciali necessari per le altre lingue. Persino
  l'inglese britannico ha il problema della mancanza di un segno per la
  sterlina.

  Ci sono stati diversi tentativi di risolvere questo problema. Tutti
  fanno uso dell'ottavo bit non usato dai codici ASCII, che in questo
  modo risultano la met inferiore di un set di 256 caratteri. Quello
  pi largamente utilizzato  il set di caratteri `Latin-1' (o pi
  formalmente ISO 8859-1). Si tratta del set di caratteri predefinito
  per Linux, HTML e X. Microsoft Windows usa una versione mutante di
  Latin-1 che aggiunge alcuni caratteri come le virgolette destre e
  sinistre, in posizioni lasciate libere da Latin-1 per ragioni storiche
  (per una resoconto severo dei problemi che ha provocato, vedere la
  pagina demoroniser <http://www.fourmilab.ch/webtools/demoroniser/>.

  Latin-1 gestisce le principali lingue europee, tra cui inglese,
  francese, tedesco, spagnolo, italiano, olandese, norvegese, svedese,
  danese. Tuttavia non  ancora sufficiente, per cui esistono altre
  serie di set di caratteri da Latin-2 a -9 per rappresentare il greco,
  l'arabo, l'ebraico e il serbo-croato. Per maggiori dettagli vedere la
  pagina ISO alphabet soup
  <http://www.utia.cas.cz/user_data/vs/documents/ISO-8859-X-
  charsets.html>.

  La soluzione definitiva  uno standard enorme chiamato Unicode (e il
  suo gemello identico ISO/IEC 10646-1:1993). Unicode  identico a
  Latin-1 nella 256 posizioni pi basse. Nello spazio successivo dei 16
  bit comprende greco, cirillico, armeno, ebraico, arabo, devanagarico,
  bengalese, gurmukhi, gujarati, oriya, tamil, telugu, kannada, malese,
  tailandese, lao, georgiano, tibetano, giapponese kana, il set completo
  del coreano hangul moderno e un set unificato di ideogrammi
  cinesi/giapponesi/coreani (CJK). Per maggiori dettagli vedere la
  Unicode Home Page <http://www.unicode.org/>.


  1111..  CCoommee ffaa iill ccoommppuutteerr aa iimmmmaaggaazzzziinnaarree llee ccoossee ssuu ddiissccoo??

  Quando leggete un disco fisso su Unix vedete un albero di nomi di file
  e directory. Normalmente non avrete bisogno di andare oltre, ma pu
  essere utile avere maggiori dettagli se vi capita un crash del disco e
  dovete cercare di salvare dei file. Sfortunatamente non c' un buon
  modo per descrivere l'organizzazione del disco dal livello dei file in
  gi, quindi dovr partire dall'hardware e risalire.


  1111..11..  SSttrruuttttuurraa ddii bbaassssoo lliivveelllloo ddeell ddiissccoo ee ddeell ffiillee ssyysstteemm

  La superficie del vostro disco, dove vengono immagazzinati i dati, si
  divide in una sorta di bersaglio per il tiro a freccette: in tracce
  circolari che sono poi `affettate' in settori. Dal momento che le
  tracce vicino al bordo esterno hanno area maggiore di quelle vicino al
  centro, le tracce esterne hanno pi settori rispetto a quelle interne.
  Ogni settore (o _b_l_o_c_c_o _d_e_l _d_i_s_c_o) ha la stessa dimensione, che sui
  moderni Unix  generalmente pari a 1K binario (1024 parole da 8 bit).
  Ogni blocco  individuato da un indirizzo univoco, il _n_u_m_e_r_o _d_i _b_l_o_c_c_o
  _d_e_l _d_i_s_c_o.

  Unix divide il disco in _p_a_r_t_i_z_i_o_n_i _d_e_l _d_i_s_c_o. Ogni partizione 
  formata da una serie continua di blocchi che vengono usati
  separatamente da quelli delle altre partizioni, come file system
  oppure come spazio swap. La partizione con numero pi basso viene
  spesso trattata in modo speciale, come _p_a_r_t_i_z_i_o_n_e _d_i _a_v_v_i_o dove si pu
  mettere un kernel da far partire.

  Ogni partizione  alternativamente uno _s_p_a_z_i_o _s_w_a_p, usato per
  implementare ``memoria virtuale'', oppure un _f_i_l_e _s_y_s_t_e_m, usato per
  contenere i file. Le partizioni swap sono trattate proprio come una
  sequenza lineare di blocchi. I file system, invece, hanno bisogno di
  un modo per associare i nomi dei file alle sequenze di blocchi disco.
  Dal momento che la dimensione dei file aumenta, diminuisce, si
  modifica nel tempo, i blocchi dati di un file non saranno una sequenza
  lineare ma potranno essere disseminati su tutta la sua partizione
  (dipende da dove il sistema operativo riesce a trovare un blocco
  libero quando gliene serve uno).



  1111..22..  NNoommii ddeeii ffiillee ee ddeellllee ddiirreeccttoorryy

  All'interno di ciascun file system la corrispondenza tra i nomi e i
  blocchi viene assicurata da una struttura chiamata _i_-_n_o_d_e. C' un
  gruppo di questi elementi vicino al ``fondo'' (i blocchi a numerazione
  pi bassa) di ciascun file system (quelli pi bassi in assoluto sono
  usati a fini di manutenzione e di etichettatura, non ne parleremo
  qui). Ogni i-node individua un file. I blocchi dati dei file si
  trovano sotto gli i-node.

  Ciascun i-node contiene una lista dei numeri di blocco disco relativi
  al file che individua. (Questa  una mezza verit, corretta solo per i
  file piccoli, ma il resto dei dettagli non  importante qui.)  Notate
  che l'i-node _n_o_n contiene il nome del file.

  I nomi dei file si trovano nelle _s_t_r_u_t_t_u_r_e _d_e_l_l_e _d_i_r_e_c_t_o_r_y. Una
  struttura della directory associa i nomi ai numeri i-node. Ecco
  perch, su Unix, un file pu avere pi nomi reali (o _h_a_r_d _l_i_n_k); sono
  soltanto diverse voci di directory che puntano allo stesso i-node.


  1111..33..  MMoouunntt ppooiinntt

  Nel caso pi semplice, tutto il vostro file system Unix si trova su di
  una sola partizione disco. Anche se questa situazione si ritrova in
  qualche piccolo sistema Unix personale,  inusuale. Pi generalmente
  esso  suddiviso tra pi partizioni disco, magari su diversi dischi
  fisici. Cos, per esempio, il vostro sistema pu avere una piccola
  partizione dove alloggia il kernel, una un po' pi grande dove si
  trovano i programmi di utilit del SO e una molto pi grande dove ci
  sono le directory personali degli utenti.

  La sola partizione alla quale avrete accesso subito dopo l'avvio del
  sistema  la _p_a_r_t_i_z_i_o_n_e _r_o_o_t, che  (quasi sempre) quella dalla quale
  avete fatto il boot. Essa contiene la root directory del file system,
  il nodo superiore dal quale dipende tutto il resto.

  Le altre partizioni del sistema devono collegarsi a questa root
  affinch tutto il vostro file system multipartizione sia accessibile.
  Circa a met del processo di avvio, il vostro Unix render accessibili
  queste partizioni non root. Dovr _m_o_n_t_a_r_e ciascuna di esse su una
  directory della partizione root.

  Per esempio, se avete una directory chiamata `/usr', si tratta
  probabilmente di un mount point per una partizione che contiene molti
  programmi che fanno parte della distribuzione standard del vostro Unix
  ma che non sono necessari durante l'avvio iniziale.


  1111..44..  CCoommee vviieennee cceerrccaattoo uunn ffiillee

  Ora possiamo guardare al file system dall'alto al basso. Ecco cosa
  succede quando aprite un file (quale, ad esempio,
  /home/esr/WWW/ldp/fundamentals.sgml):

  Il kernel parte dalla radice del vostro file system Unix (dalla
  partizione root). Cerca una directory chiamata `home'. Di solito
  `home'  un mount point per una grande partizione utente da qualche
  altra parte, cos va di l. Nella struttura della directory di livello
  pi alto di quella partizione utente cerca poi una voce chiamata `esr'
  e ne estrae un numero di i-node. Va a quell'i-node, vede che si tratta
  di una struttura di directory e cerca `WWW'. Estraendo _q_u_e_l_l'i-node,
  va alla corrispondente sottodirectory e cerca `ldp'. Questo lo porta a
  un altro i-node di directory ancora. Aprendolo, trova il numero i-node
  di `fundamentals.sgml'. Questo i-node non  una directory, ma contiene
  invece l'elenco dei blocchi disco associati al file.
  1111..55..  PPrroopprriieettaarrii ddeeii ffiillee,, aauuttoorriizzzzaazziioonnii ee ssiiccuurreezzzzaa

  Per impedire ai programmi di intervenire accidentalmente o
  maliziosamente su dati su cui non dovrebbero, Unix usa le
  _a_u_t_o_r_i_z_z_a_z_i_o_n_i. Queste vennero originariamente pensate per supportare
  il timesharing, proteggendo gli uni dagli altri utenti diversi sulla
  stessa macchina, quando ancora Unix veniva usato su costosi
  minicomputer condivisi.

  Per comprendere le autorizzazioni sui file, occorre richiamare la
  descrizione di utenti e gruppi nella sezione ``Che cosa accade con il
  log in?''. Ciascun file ha un utente proprietario e un gruppo
  proprietario. Inizialmente sono quelli del creatore del file; possono
  poi essere modificati con i programmi chown(1) e chgrp(1).

  Le autorizzazioni fondamentali che possono essere associate a un file
  sono `read' (autorizzazione a leggere i dati contenuti), `write'
  (autorizzazione a modificarli) e `execute' (autorizzazione a eseguirli
  come programma). Ciascun file ha tre set di autorizzazioni; uno per
  l'utente proprietario, uno per tutti gli utenti nel gruppo
  proprietario e uno per tutti gli altri. I `privilegi' che si ottengono
  al momento del log in sono la possibilit di leggere, modificare ed
  eseguire quei file i cui bit di autorizzazione coincidono la propria
  ID utente o quella di un gruppo a cui si appartiene.

  Per vedere come queste possono interagire e come le visualizza Unix,
  osserviamo alcuni elenchi di file su un sistema Unix ipotetico. Ecco
  un esempio:



       snark:~$ ls -l notes
       -rw-r--r--   1 esr      users         2993 Jun 17 11:00 notes



  Si tratta di un file di dati ordinario. Il listato ci dice che il
  proprietario  l'utente `esr', creato con il gruppo proprietario
  `users'. Probabilmente la macchina su cui si trova mette per
  definizione tutti gli utenti ordinari in questo gruppo; altri gruppi
  che si vedranno comunemente su macchine con timesharing sono `staff',
  `admin', o `wheel' (per ovvie ragioni, i gruppi non sono molto
  importanti su workstation a singolo utente o PC). Il vostro Unix
  potrebbe usare un gruppo di default differente, magari derivato dal
  vostro nome utente.

  La stringa `-rw-r--r--' rappresenta i bit di autorizzazione per il
  file. Il primo trattino  la posizione del bit directory; se il file
  fosse stato una directory il bit sarebbe stato `d'. Dopo di questo, le
  prime tre posizioni successive sono le autorizzazioni utente, le
  seconde tre le autorizzazioni del gruppo e le terze tre le
  autorizzazioni per gli altri (spesso chiamate autorizzazioni `world').
  Su questo file l'utente proprietario `esr' pu leggere e modificare il
  file, gli altri appartenenti al gruppo `users' possono leggerlo e cos
  tutti gli altri utenti. Si tratta di un set di autorizzazioni
  piuttosto tipiche per un file di dati ordinario.

  Ora osserviamo un file con autorizzazioni molto diverse. Tale file 
  GCC, il compilatore C GNU.



       snark:~$ ls -l /usr/bin/gcc
       -rwxr-xr-x   3 root     bin         64796 Mar 21 16:41 /usr/bin/gcc

  Questo file appartiene a un utente chiamato `root' e ad un gruppo
  chiamato `bin'; pu essere modificato solo da root, ma letto ed
  eseguito da tutti. Si tratta di un proprietario e un set di
  autorizzazioni tipiche per un comando di sistema pre-installato. Il
  gruppo `bin' esiste su alcuni Unix per raggruppare i comandi di
  sistema (il nome  una reliquia storica, abbreviazione di `binary').
  Il vostro Unix potrebbe usare invece un gruppo `root' (non esattamente
  la stessa cosa dell'utente `root'!).

  L'utente `root'  il nome convenzionale per l'ID utente con numero 0,
  un account speciale privilegiato che pu scavalcare tutti i privilegi.
  L'accesso root  utile ma pericoloso; un errore di battitura quando si
   collegati come root potrebbe rovinare file critici del sistema, cosa
  che non pu avvenire con un account utente ordinario.

  Poich l'account root  cos potente, il suo accesso dovrebbe essere
  sorvegliato attentamente. La password di root  il componente pi
  critico nelle informazioni di sicurezza del sistema, e sar quello che
  cercheranno di ottenere tutti i cracker e gli intrusi che verranno
  dopo di voi.

  (Per quanto riguarda le password: non scrivetele su carta -- e non
  scegliete password che possano essere indovinate facilmente, come il
  nome della/o vostra/o ragazza/o.  una pratica sorprendentemente
  comune che aiuta continuamente i cracker...)

  Osserviamo ora un terzo caso:



       snark:~$ ls -ld ~
       drwxr-xr-x  89 esr      users          9216 Jun 27 11:29 /home2/esr
       snark:~$



  Questo file  una directory (osserviamo la `d' in prima posizione).
  Vediamo che pu essere modificata solo da esr, ma letta ed eseguita da
  tutti gli altri. Le autorizzazioni vengono interpretate in modo
  speciale sulle directory; esse controllano l'accesso ai file contenuti
  all'interno della directory.

  Autorizzazione in lettura su una directory  semplice; significa
  semplicemente che potete esplorare la directory e aprire i file e le
  directory che contiene. L'autorizzazione in scrittura (modifica) da la
  possibilit di creare e cancellare file nella directory.
  Autorizzazione di esecuzione consente di effettuare _r_i_c_e_r_c_h_e nella
  directory -- ovvero elencare il suo contenuto e vedere i nomi dei file
  e delle directory che contiene. A volte troverete directory che sono
  leggibili da tutti ma non eseguibili; questo significa che un utente
  qualunque pu accedere a file e directory al suo interno, ma solamente
  se ne conosce il nome esatto.

  Infine, osserviamo le autorizzazioni del programma login stesso.



       snark:~$ ls -l /bin/login
       -rwsr-xr-x   1 root     bin         20164 Apr 17 12:57 /bin/login



  Possiede le autorizzazioni che ci aspetteremmo per un comando di
  sistema -- tranne la `s' dove dovrebbe esserci il bit per
  l'autorizzazione in esecuzione del proprietario. Si tratta della
  manifestazione visibile di un tipo speciale di autorizzazione chiamata
  `set-user-id' o _b_i_t _s_e_t_u_i_d.

  Il bit setuid  normalmente legato a programmi che hanno la necessit
  di dare agli utenti ordinari i privilegi di root, ma in modo
  controllato. Quando  impostato su un programma eseguibile, si
  acquistano i privilegi del proprietario di quel file finch si esegue
  quel programma, sia che essi coincidano con i nostri oppure no.

  Come l'account root stesso, i programmi setuid sono utili ma
  pericolosi. Chiunque sia in grado di sovvertire o modificare un
  programma setuid che ha root come proprietario, pu utilizzarlo per
  accedere alla shell con privilegi di root. Per questa ragione sulla
  maggior parte dei sistemi Unix, aprendo un file in scrittura
  automaticamente il suo bit setuid viene disattivato. Molti attacchi
  alla sicurezza su Unix tentano di scoprire bug nei programmi setuid,
  con lo scopo di sovvertirli. Amministratori di sistema attenti alla
  sicurezza sono quindi molto prudenti con questi programmi e riluttanti
  alla installazione di nuovi.

  Ci sono un paio di importati dettagli che abbiamo sorvolato durante la
  discussione precedente sulle autorizzazioni; in particolare, come
  vengono assegnati l'utente e il gruppo proprietario quando viene
  creato un file per la prima volta. Il gruppo  importante poich gli
  utenti possono essere membri di pi gruppi, ma uno di essi
  (specificato nella voce dell'utente in /etc/passwd)  il _g_r_u_p_p_o _d_i
  _d_e_f_a_u_l_t dell'utente e normalmente possieder i file creati
  dall'utente.

  Per quanto riguarda i bit iniziali di autorizzazione, la faccenda 
  leggermente pi complicata. Un programma che crea un file normalmente
  specificher le autorizzazioni con cui dovr partire. Queste, per,
  verranno modificate da una variabile nell'ambiente dell'utente
  chiamata _u_m_a_s_k. Umask speciica quali bit di autorizzazione _d_i_s_a_t_t_i_v_a_r_e
  quando crea un file; il valore pi comune, e il default sulla maggior
  parte dei sistemi,  -------w- o 002, che disattiva il bit di modifica
  per tutti gli utenti. Vedere la documentazione per il comando umask
  nella pagina di manuale della shell per maggiori dettagli.


  1111..66..  CCoommee llee ccoossee ppoossssoonnoo aannddaarree mmaallee

  Prima accennavamo al fatto che i file system possono essere delicati.
  Ora sappiamo che per raggiungere un file dobbiamo fare il gioco della
  campana attraverso quella che pu essere una catena arbitrariamente
  lunga di riferimenti i-node e directory. Supponiamo ora che sul vostro
  disco fisso si formi un punto danneggiato.

  Se siete fortunati ci vi far perdere solo qualche file di dati. Se
  invece siete sfortunati, si potrebbe danneggiare una struttura di
  directory o un numero i-node e un intero sottoalbero del vostro
  sistema potrebbe rimanere pendente nel limbo. Oppure, peggio ancora,
  si potrebbe originare una struttura rovinata che punta in pi modi
  allo stesso blocco disco o i-node. Un danneggiamento di questo tipo si
  pu propagare a partire da una normale operazione sui file, facendo
  perdere tutti i dati collegati al punto danneggiato di origine.

  Fortunatamente questo tipo di eventualit  divenuto abbastanza
  infrequente perch l'hardware dei dischi  pi affidabile. Tuttavia,
  questo comporta che il vostro Unix voglia controllare periodicamente
  l'integrit del file system per assicurarsi che non ci sia nulla fuori
  posto. Gli Unix moderni compiono un rapido controllo dell'integrit di
  ciascuna partizione nella fase di avvio, giusto prima di montarle.
  Ogni tot riavvii fanno un controllo molto pi approfondito che impiega
  qualche minuto in pi.
  Se tutto questo pu far sembrare che Unix sia terribilmente complesso
  e incline a malfunzionamenti, pu essere rassicurante sapere che
  questi controlli nella fase d'avvio tipicamente intercettano e
  correggono i problemi normali _p_r_i_m_a che diventino veramente
  disastrosi. Altri sistemi operativi non hanno questi strumenti, cosa
  che velocizza un po' l'avvio ma pu mettervi molto di pi nei pasticci
  quando cercate di fare un salvataggio a mano (e sempre assumendo che
  abbiate una copia delle Norton Utilities o simili, tanto per
  cominciare...).


  1122..  CCoommee ffuunnzziioonnaannoo ii lliinngguuaaggggii ppeerr ccoommppuutteerr??

  Abbiamo gi visto ``come vengono eseguiti i programmi''. Ogni
  programma in definitiva deve eseguire un flusso di byte che sono
  istruzioni nel _l_i_n_g_u_a_g_g_i_o _m_a_c_c_h_i_n_a del vostro computer. Ma gli esseri
  umani non se la cavano molto bene con il linguaggio macchina;
  riuscirci  divenuta un'arte rara, una magia nera persino tra gli
  hacker.

  Quasi tutto il codice Unix, ad eccezione di una piccola porzione
  relativa all'interfaccia diretta con l'hardware nel kernel, viene oggi
  scritto in un _l_i_n_g_u_a_g_g_i_o _d_i _a_l_t_o _l_i_v_e_l_l_o. (`Alto livello' in questa
  espressione  un residuo storico volto a distinguerlo dai _l_i_n_g_u_a_g_g_i
  _a_s_s_e_m_b_l_e_r di `basso livello', che sono fondamentalmente sottili
  involucri attorno al codice macchina.)

  Ci sono diversi tipi di linguaggi di alto livello. Per affrontare
  l'argomento troverete utile tenere a mente che il _c_o_d_i_c_e _s_o_r_g_e_n_t_e di
  un programma (la versione creata dall'uomo, editabile) deve passare
  attraverso un qualche tipo di traduzione in codice macchina che il
  computer pu effettivamente eseguire.


  1122..11..  LLiinngguuaaggggii ccoommppiillaattii

  Il tipo pi convenzionale di linguaggio  il _l_i_n_g_u_a_g_g_i_o _c_o_m_p_i_l_a_t_o. I
  linguaggi compilati vengono tradotti in file eseguibili di codice
  macchina binario da uno speciale programma chiamato (ovviamente)
  _c_o_m_p_i_l_a_t_o_r_e. Una volta che il codice binario  stato generato potete
  eseguirlo direttamente senza pi guardare al codice sorgente. (La
  maggior parte del software  fornita come binari compilati a partire
  da codice che non vedete.)

  I linguaggi compilati tendono a dare prestazioni eccellenti e hanno il
  pi completo accesso al SO, ma tendono anche a essere difficili da
  programmare.

  C, il linguaggio in cui Unix stesso  scritto,  di gran lunga il pi
  importante tra questi (con la sua variante C++). FORTRAN  un altro
  linguaggio ancora usato tra gli ingegneri e gli scienziati ma di anni
  pi vecchio e molto pi primitivo. Nel mondo Unix nessun altro
  linguaggio compilato  nell'uso dominante. Al di fuori di esso, il
  COBOL  molto usato per il software finanziario e commerciale.

  C'erano molti altri linguaggi compilati, ma la maggior parte di essi
  si sono estinti oppure sono strumenti strettamente di ricerca. Se
  siete nuovi sviluppatori Unix e usate un linguaggio compilato 
  estremamente probabile che questo sia il C o il C++.


  1122..22..  LLiinngguuaaggggii iinntteerrpprreettaattii

  Un _l_i_n_g_u_a_g_g_i_o _i_n_t_e_r_p_r_e_t_a_t_o dipende da un programma interprete che
  legge il codice sorgente e lo traduce al volo in calcoli e chiamate di
  sistema. Il sorgente deve essere reinterpretato (e l'interprete deve
  essere presente) ogni volta che il codice viene eseguito.

  I linguaggi interpretati tendono a essere pi lenti dei linguaggi
  compilati e spesso hanno accesso limitato al sistema operativo e
  all'hardware sottostanti. D'altra parte, essi tendono a essere pi
  facili da programmare e pi propensi a perdonare gli errori di
  codifica rispetto ai linguaggi compilati.

  Molti programmi di utilit di Unix, inclusa la shell, bc(1), sed(1) e
  awk(1), sono in effetti piccoli linguaggi interpretati. I BASIC sono
  di solito interpretati. Cos pure il Tcl. Storicamente, il pi
  importante linguaggio interpretato  stato il LISP (un grande
  miglioramento rispetto ai suoi predecessori). Oggi il Perl  molto
  usato ed in costante crescita di popolarit.


  1122..33..  LLiinngguuaaggggii aa ccooddiiccee PP

  Dal 1990  andato assumendo importanza crescente un tipo di linguaggi
  ibridi che usa sia la compilazione che l'interpretazione. I linguaggi
  a codice P sono come i linguaggi compilati nel senso che il sorgente
  viene tradotto in una forma binaria compatta che  ci che viene
  realmente eseguito, ma che non  esattamente codice macchina. Si
  tratta invece di _p_s_e_u_d_o_c_o_d_i_c_e (o _c_o_d_i_c_e _P) che  solitamente molto pi
  semplice ma pi potente di un vero linguaggio macchina. Quando
  eseguite il programma, interpretate il codice P.

  Il codice P pu girare velocemente quasi quanto un binario compilato
  (gli interpreti di codice P possono essere abbastanza semplici,
  leggeri e rapidi). Ma i linguaggi a codice P riescono a mantenere la
  flessibilit e la potenza di un buon interprete.

  Importanti linguaggi a codice P includono Python e Java.


  1133..  CCoommee ffuunnzziioonnaa IInntteerrnneett??

  Per aiutarvi a capire come funziona Internet daremo un'occhiata alle
  cose che succedono quando fate una tipica operazione di Internet:
  indirizzate un browser alla prima pagina di questo documento, sul sito
  Web del Linux Documentation Project. L'indirizzo di questo documento 


  http://metalab.unc.edu/LDP/HOWTO/Fundamentals.html



  che significa che si trova nel file LDP/HOWTO/Fundamentals.html sotto
  la web directory dell'host metalab.unc.edu.


  1133..11..  NNoommii ee llooccaazziioonnii

  La prima cosa che il vostro browser deve fare  stabilire una
  connessione remota al computer dove si trova il documento. A tal fine
  deve prima trovare la locazione remota dell'_h_o_s_t metalab.unc.edu
  (`host'  la forma breve di `computer host' o `host remoto';
  metalab.unc.edu  un tipico _h_o_s_t_n_a_m_e). La locazione corrispondente 
  in realt un numero chiamato _i_n_d_i_r_i_z_z_o _I_P (spiegheremo pi avanti la
  parte `IP' di questa espressione).

  A questo scopo il vostro browser interroga un programma chiamato _n_a_m_e
  _s_e_r_v_e_r. Il name server pu trovarsi sul vostro computer, ma  pi
  probabile che giri su un computer del fornitore col quale il vostro
  computer dialoga. Quando vi collegate a un ISP una parte della
  procedura consiste quasi sicuramente nel dire al vostro software per
  Internet qual  l'indirizzo IP di un name server sulla rete dell'ISP.

  I name server sui vari computer si parlano tra loro, scambiandosi e
  tenendo aggiornate tutte le informazioni necessarie per risolvere i
  nomi degli host (per metterli in corrispondenza con gli indirizzi IP).
  Il vostro name server pu interrogare tre o quattro diversi siti sulla
  rete nel processo di risoluzione di metalab.unc.edu, ma di solito
  questo si verifica molto rapidamente (tipo in meno di un secondo).

  Il name server dir al vostro browser che l'indirizzo IP di Metalab 
  152.2.22.81; a questo punto il vostro computer sar in grado di
  scambiare direttamente bit con metalab.


  1133..22..  PPaacccchheettttii ee rroouutteerr


  Quello che il browser vuole  mandare al server Web su Metalab un
  comando come questo:


  GET /LDP/HOWTO/Fundamentals.html HTTP/1.0



  Ecco cosa succede. Dal comando si costruisce un _p_a_c_c_h_e_t_t_o, cio un
  blocco di bit come un telegramma che  `impacchettato' con tre cose
  importanti: l'_i_n_d_i_r_i_z_z_o _d_i _p_r_o_v_e_n_i_e_n_z_a (l'indirizzo IP del vostro
  computer), l'_i_n_d_i_r_i_z_z_o _d_i _d_e_s_t_i_n_a_z_i_o_n_e (152.2.22.81), e un _n_u_m_e_r_o _d_i
  _s_e_r_v_i_z_i_o o _n_u_m_e_r_o _d_i _p_o_r_t_a (in questo caso 80) che indica che si
  tratta di una richiesta World Wide Web.

  Il vostro computer spedisce allora il pacchetto lungo il cavo (la
  connessione modem al vostro ISP o rete locale) finch arriva a un
  computer specializzato chiamato _r_o_u_t_e_r. Il router ha nella sua memoria
  una mappa di Internet, non sempre una completa, ma una che descrive
  completamente il vostro vicinato di rete e sa come raggiungere i
  router per altri circondari di Internet.

  Il vostro pacchetto potrebbe passare attraverso svariati router lungo
  la strada per la sua destinazione. I router sono intelligenti.
  Guardano quanto tempo impiegano gli altri router per avvertire che
  hanno ricevuto un pacchetto. Usano questa informazione per dirigere il
  traffico verso i collegamenti veloci. La usano per accorgersi se un
  altro router (o un cavo) sono fuori servizio o irraggiungibili e
  quindi, se possibile, ovviare al problema trovando un'altra strada.

  C' una leggenda metropolitana secondo la quale Internet  stata
  progettata per sopravvivere alla guerra nucleare. Questo non  vero,
  ma la struttura di Internet  estremamente adatta a ottenere
  prestazioni affidabili anche con l'hardware precario che caratterizza
  questo mondo incerto. Questo deriva direttamente dal fatto che la sua
  intelligenza  distribuita tra migliaia di router piuttosto che
  riunita in poche enormi centrali (come la rete telefonica). Questo
  significa che i malfunzionamenti tendono a essere ben localizzati e la
  rete pu aggirarli.

  Una volta che il vostro pacchetto  giunto al computer di destinazione
  quest'ultimo usa il numero di servizio per inviare il pacchetto al
  server Web. Il server Web pu capire a chi rispondere guardando
  l'indirizzo IP di provenienza del pacchetto con il comando. Quando il
  server Web restituisce questo documento lo suddivide in un certo
  numero di pacchetti. La dimensione dei pacchetti varia a seconda del
  mezzo di trasmissione sulla rete e del tipo di servizio.


  1133..33..  TTCCPP ee IIPP

  Per capire come vengono gestite le trasmissioni a pacchetti multipli,
  dovete sapere che Internet in realt usa due protocolli, uno
  sovrapposto all'altro.

  Il livello pi basso, l'_I_P (Internet Protocol), sa come recapitare
  singoli pacchetti da un indirizzo di provenienza a un indirizzo di
  destinazione ( per questo che si chiamano indirizzi IP). Tuttavia
  l'IP non  affidabile: se un pacchetto si perde o cade i computer di
  origine e di destinazione possono non venirne mai a conoscenza. Nel
  gergo delle reti, l'IP  un protocollo _s_e_n_z_a _c_o_n_n_e_s_s_i_o_n_e; il mittente
  si limita a far partire un pacchetto per il destinatario e non si
  aspetta un avviso di ricevuta.

  L'IP  veloce ed economico, comunque. A volte veloce, economico e
  inaffidabile va bene. Quando giocate in rete a Doom o Quake, ogni
  pallottola  rappresentata da un pacchetto IP. Se alcune vengono
  perse, pazienza.

  Il livello superiore, _T_C_P (Transmission Control Protocol), vi d
  affidabilit. Questi due computer negoziano una connessione TCP (cosa
  che fanno usando l'IP); il ricevente sa che deve spedire al mittente
  un avviso di ricevuta dei pacchetti che legge. Se il mittente non vede
  un avviso di ricevuta per un pacchetto entro un certo periodo di tempo
  (timeout) allora rispedisce quel pacchetto. Inoltre, il mittente
  attribuisce a ogni pacchetto TCP un numero di sequenza, che il
  ricevente pu usare per riassemblare i pacchetti nel caso che
  risultino in disordine. (Cosa che si verifica se un collegamento della
  rete viene attivato o cade durante una connessione.)

  I pacchetti TCP/IP contengono anche un checksum per consentire
  l'individuazione di dati rovinati da collegamenti difettosi. Cos, dal
  punto di vista di chiunque usi il TCP/IP e i name server, sembra
  affidabile passare flussi di byte in coppie hostname/numero di
  servizio. Chi scrive i protocolli di rete non deve quasi mai pensare
  agli aspetti di basso livello relativi alla pacchettizzazione, al
  riassemblaggio dei pacchetti, al controllo degli errori, al checksum e
  alla ritrasmissione.


  1133..44..  HHTTTTPP,, uunn pprroottooccoolllloo aapppplliiccaattiivvoo

  Torniamo ora al nostro esempio. I browser e i server Web dialogano
  usando un _p_r_o_t_o_c_o_l_l_o _a_p_p_l_i_c_a_t_i_v_o che si appoggia al TCP/IP, usandolo
  semplicemente come un modo per passare stringhe di byte avanti e
  indietro. Questo protocollo  chiamato _H_T_T_P (Hyper-Text Trasfer
  Protocol, protocollo per il trasferimento di ipertesti) e abbiamo gi
  visto un suo comando: il GET mostrato sopra.

  Quando il comando GET arriva al server Web metalab.unc.edu con numero
  di servizio 80 verr notificato al _d_e_m_o_n_e _s_e_r_v_e_r che  in attesa sulla
  porta 80. La maggior parte dei servizi Internet sono implementati da
  demoni server che si limitano ad ascoltare sulle porte, attendono ed
  eseguono i comandi in arrivo.

  Se il disegno di Internet ha una regola generale, questa  che tutte
  le parti dovrebbero essere il pi possibile semplici e accessibili per
  gli esseri umani. L'HTTP, e i suoi simili (come il Simple Mail
  Transfer Protocol, _S_M_T_P, che viene usato per trasferire la posta
  elettronica tra gli host) tende a usare comandi in semplice testo
  stampabile che terminano con un codice di carriage return/line feed.

  Questo  marginalmente inefficiente: in qualche circostanza potreste
  ottenere una velocit maggiore usando un protocollo binario di stretta
  codifica. Ma l'esperienza ha dimostrato che i vantaggi di avere
  comandi facili da descrivere e comprendere per gli esseri umani supera
  qualsiasi guadagno marginale di efficienza che si possa ottenere al
  prezzo di rendere le cose oscure e complicate.

  Di conseguenza, quello che il demone server vi rispedisce via TCP/IP 
  anch'esso testo. L'inizio della risposta assomiglier in qualche modo
  a questa (alcuni header sono stati omessi):


  HTTP/1.1 200 OK
  Date: Sat, 10 Oct 1998 18:43:35 GMT
  Server: Apache/1.2.6 Red Hat
  Last-Modified: Thu, 27 Aug 1998 17:55:15 GMT
  Content-Length: 2982
  Content-Type: text/html



  Questi header saranno seguiti da una linea vuota e dal testo della
  pagina Web (dopodich la connessione viene lasciata cadere). Il vostro
  browser si limita a visualizzare quella pagina. Gli header servono a
  spiegargli come (in particolare, l'header Content-Type gli dice che i
  dati restituiti sono veramente HTML).



