* [gentoo-docs-it] Posix Thread Explained, Part 1 - traduzione
@ 2007-05-12 7:01 Andrea Veroni
2007-05-12 12:02 ` Davide Cendron
0 siblings, 1 reply; 2+ messages in thread
From: Andrea Veroni @ 2007-05-12 7:01 UTC (permalink / raw
To: gentoo-docs-it
[-- Attachment #1: Type: text/plain, Size: 490 bytes --]
Posto la mia traduzione per la revisione finale, consigli, segnalazione di
eventuali errori di forma e/o contenuto (come e' oramai prassi) prima del
consueto bug report. Essendo un articolo in cui lo scrittore parla in prima
persona ho lasciato la forma colloquiale, perche' renderlo impersonale non
rendeva molto l'idea...Se pero' fa schifo posso sempre cambiarlo :)
Chiedo anche di poter tradurre l-posix2.xml, cosi' continuo con la saga dei
thread posix che sono tanto carucci :D
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: l-posix1.xml --]
[-- Type: text/xml; charset="us-ascii"; name="l-posix1.xml", Size: 23554 bytes --]
<?xml version='1.0' encoding="UTF-8"?>
<!-- $Header: /var/cvsroot/gentoo/xml/htdocs/doc/it/articles/l-posix1.xml,v 1.4 2005/10/09 17:13:23 rane Exp $ -->
<!DOCTYPE guide SYSTEM "/dtd/guide.dtd">
<guide link="/doc/it/articles/l-posix1.xml" lang="it" disclaimer="articles">
<title>POSIX threads explained, parte 1</title>
<author title="Autore">
<mail link="drobbins@gentoo.org">Daniel Robbins</mail>
</author>
<author title="Traduttore">
<mail link="andreaveroni@tiscalinet.it">Andrea Veroni</mail>
</author>
<abstract>
I thread POSIX (Portable Operating System Interface) sono un ottima maniera per
incrementare la reattività e le prestazioni del proprio codice. In questa serie,
Daniel Robbins mostra esattamente come utilizzare i thread nel vostro codice.
Verranno svelati dettagli del retroscena, cosicchè alla fine della serie sarete
veramente pronti per creare il vostro programma multithread.
</abstract>
<!-- La versione originale di questo articolo è stata pubblicata su IBM
developerWorks, ed è di proprietà della Westtech Information Services.
Questo documento è una versione aggiornata dell'articolo originale, e
contiene diversi miglioramenti fatti dal Gentoo Linux Documentation Team -->
<version>1.2</version>
<date>2005-10-09</date>
<chapter>
<title>Uno strumento semplice e veloce per la condivisione della memoria</title>
<section>
<title>I Thread sono divertenti</title>
<body>
<p>
Sapere come usare correttamente i thread dovrebbe far parte del repertorio di
ogni buon programmatore. I thread sono simili ai processi. L'esecuzione dei
thread, similmente a quella dei processi, è ripartita dal kernel in intervalli
di tempo. Nei sistemi uniprocessore il kernel sfrutta il time slice per simulare
l'esecuzione simultanea di piu' thread nella stessa maniera in cui sfrutta il time
slice per i processi. E attualmente, sui sistemi multiprocessore, i thread possono
essere eseguiti contemporaneamente, esattamente come due o piu' processi.
</p>
<p>
E perche' il multithreading è preferibile a più processi indipendenti per la
maggior parte dei compiti cooperativi? Bene, i thread condividono lo stesso spazio
in memoria. Thread indipendenti possono accedere alle stesse variabili.in memoria.
Infatti tutti i thread contenuti nel programma possono leggere e scrivere le stesse
variabili dichiarate globalmente. Se avete mai scritto del codice "non grezzo" che
utilizza la funzione fork(), riconoscerete l'importanza di questo strumento. Perchè?
Mentre fork() permette di dare vita a più processi, crea anche il seguente problema
di comunicazione: come far dialogare fra loro più processi, ognuno dei quali ha un
proprio spazio in memoria. Non esiste una soluzione semplice a questo problema.
Nonostante ci siano molti tipi differenti di comunicazione fra i processi locale
(IPC), tutti presentano gli stessi due inconvenienti:
</p>
<ul>
<li>
Impongono al kernel una specie di overhead in più, abbassando le prestazioni.
</li>
<li>
In quasi tutte le situazioni l'IPC non è un ampliamento "naturale" del codice.
Spesso accresce drasticamente la complessità del programma.
</li>
</ul>
<p>
Ulteriore scocciatura: overhead e complicazioni non sono cose belle. Se vi è mai
capitato di dover apportare grosse modifiche ad uno dei vostri programmi per
fare in modo che supporti IPC, apprezzerete senz'altro il semplice approccio di
condivisione della memoria che i thread mettono a disposizione. I thread POSIX
non necessitano di costose e complicate chiamate a lunga distanza perchè è come
se tutti i nostri thread vivessero nella stessa casa. Con un po' di sincronizzazione,
tutti i vostri thread possono leggere e modificare le strutture dati presenti nel
programma. Non è necessario far transitare i dati attraverso un file descriptor o
comprimerli in una piccola area di memoria condivisa. Per questo motivo solamente
dovreste prendere in considerazione il modello con un processo multithread piuttosto
che il modello multiprocesso con singoli thread.
</p>
</body>
</section>
<section>
<title>I thread sono leggeri</title>
<body>
<p>
Ma c'è altro. I thread risultano inoltre essere estremamente leggeri. Confrontati
alla fork() standard, producono molto meno overhead. Inoltre il kernel non necessita
di creare un'ulteriore copia autonoma dello spazio di memoria relativo al processo,
dei file descriptor, ecc. Ciò comporta un notevole risparmio del tempo di CPU, rendendo
la creazione dei thread da decine a centinaia di volte più veloce che la creazione
di nuovi processi. Proprio grazie a ciò, è possibile utilizzare un intero gruppo di
thread senza doversi preoccupare di un eventuale overhead della CPU o della memoria.
Non si ha un grosso utilizzo della CPU come si ha con una fork(). Questo significa
che potete dare vita ai thread in qualsiasi momento abbia senso all'interno del
programma.
</p>
<p>
Ovviamente, proprio come i processi, i thread trarranno vantaggio dalla presenza di
più CPU. Questa è veramente un'ottima caratteristica se il software è progettato per
essere utilizzato su macchine multiprocessore (se il software è open source,
probabilmente finirà col girare soltanto su alcune di quelle). Le prestazioni di
alcune tipologie di programmi che utilizzano i thread (in modo particolare quelli
che fanno uso intenso della CPU) salirà in modo abbastanza lineare relativamente al
numero dei processori presenti nel sistema. Se state scrivendo un programma che fa un
uso intenso della CPU , certamente cercherete un modo per poter utilizzare i thread nel
vostro codice. Una volta esperti nello scrivere codice contenente thread, sarete capaci,
scrivendo codice, di affrontare le sfide in modi nuovi e creativi, senza una moltitudine
di IPC red tape and miscellaneous mumbo-jumbo. Tutti questi benefici lavorano in sinergia
per rendere la programmazione multithread divertente, veloce e flessibile.
</p>
</body>
</section>
<section>
<title>Ora penso di essere un clone</title>
<body>
<p>
Se avete mai fatto parte del mondo della programmazione Linux almeno per un momento, potreste
conoscere la chiamata di sistema __clone(). __clone() e' simile a fork(), ma consente di
svolgere molti dei compiti che anche i thread possono svolgere. Per esempio, con __clone()
potete selettivamente condividere parte del contesto di esecuzione del processo padre (spazio
in memoria, descrittori dei file, ecc.) con un nuovo processo figlio. E ciò e' un bene. Ma ci
sono anche cose negative a proposito di __clone(). Come riporta la pagina del manuale di __clone:
</p>
<pre caption="Citazione dalla pagina del manuale di __clone()">
"La chiamata __clone è propria di Linux e non dovrebbe essere utilizzata in programmi il
cui obiettivo è la portabilità. Programmando applicazioni che sfruttano i thread (thread
di controllo multipli nello stesso spazio di memoria), è preferibile utilizzare una
libreria che implementi il thread API POSIX 1003.1c, come la libreria thread di Linux.
Vedi pthread_create(3)."
</pre>
<p>
Così, anche se __clone() offre gran parte dei vantaggi che offrono i thread, non è
portabile. Ciò non significa che non dovreste usarla nel vostro codice. Ma dovreste
valutare ciò quando pensate di utilizzare __clone() nel vostro software. Fortunatamente,
come riporta la pagina del manuale di __clone(), c'è un'alternativa migliore: i thread
POSIX. Quando avete intenzione di scrivere codice portabile e multithread, codice che
funzioni sotto Solaris, FreeBSD, Linux, e altri, i thread POSIX sono la giusta strada da
seguire.
</p>
</body>
</section>
<section>
<title>Iniziando con i thread</title>
<body>
<p>
Ecco un semplice programma che sfrutta i thread POSIX:
</p>
<pre caption="Programma di esempio che sfrutta i thread POSIX">
#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>
void *thread_function(void *arg) {
int i;
for ( i=0; i<20; i++ ) {
printf("Thread says hi!\n");
sleep(1);
}
return NULL;
}
int main(void) {
pthread_t mythread;
if ( pthread_create( &mythread, NULL, thread_function, NULL) ) {
printf("error creating thread.");
abort();
}
if ( pthread_join ( mythread, NULL ) ) {
printf("error joining thread.");
abort();
}
exit(0);
}
</pre>
<p>
Per compilare questo programma, semplicemente salvare il file come "thread1.c" e digitare:
</p>
<pre caption="Compilare il programma">
$ <i>gcc thread1.c -o thread1 -lpthread</i>
</pre>
<p>
Eseguirlo digitando:
</p>
<pre caption="Eseguire il programma">
$ <i>./thread1</i>
</pre>
</body>
</section>
<section>
<title>Capire thread1.c</title>
<body>
<p>
<path>thread1.c</path> è un semplicissimo programma che utilizza i thread. Anche se
non fa nulla di utile, vi aiuterà a capire come funzionano i thread. Ora diamo
un'occhiata passo passo a ciò che fa questo programma. In main() per prima cosa
dichiariamo una variabile chiamata mythread, che ha un tipo pthread_t. Il tipo
pthread_t, definito in <path>pthread.h</path>, e' spesso chiamato "thread id"
(comunemente abbreviato a "tid"). Pensate a ciò come una specie di gestore di thread.
</p>
<p>
Dopo che mythread è stato dichiarato (ricordare che mythread è soltanto un "tid",
o un controllo al thread che stiamo per creare), chiamiamo la funzione pthread_create
per creare un vero e proprio thread. Non fatevi trarre in inganno dal fatto che
pthread_create() è all'interno di un costrutto "if". Poichè pthread_create() ritorna
zero in caso di successo e un valore diverso da zero in caso di insuccesso, collocare
la chiamata alla funzione all'interno di un if() è soltanto una maniera elegante di
scoprire un insuccesso della chiamata di pthread_create(). E ora diamo un'occhiata
agli argomenti passati a pthread_create. Il primo è un puntatore a mythread,
&mythread. Il secondo argomento, al momento settato NULL, può essere
utilizzato per definire alcuni attributi del nostro thread. Poichè gli attributi
di default del thread per noi funzionano bene, lo settiamo semplicemente a NULL.
</p>
<p>
Il nostro terzo argomento è il nome della funzione che il nuovo thread eseguirà
una volta avviato. In questo caso il nome della funzione è thread_function().
Quando thread_function() ritorna, il nostro nuovo thread terminerà. In questo
esempio la nostra funzione thread non esegue nulla di particolare. Stampa solamente
a video "Thread says hi!" per 20 volte e poi esce. Notate che thread_function() accetta
void * come argomento e ritorna void * come valore di ritorno.
Questo dimostra che è possibile utilizzare un void * per passare una quantita' arbitraria
di dati al nostro nuovo thread, e che il nostro nuovo thread può ritornare una quantita'
arbitraria di dati quando termina. E ora come possiamo passare al nostro thread un
argomento arbitrario? Semplice. Si utilizza il quarto argomento per chiamata a
pthread_create(). In questo esempio è settato a NULL perchè non serve passare nessun
dato alla nostra grezza thread_function().
</p>
<p>
Come potete aver intuito, il programma sarà composto da due thread dopo che
pthread_create() ha ritornato con successo. Aspetta un minuto, due thread? Non abbiamo
creato solamente un singolo thread? Si, certo. Ma anche il nostro programma principale è
considerato un thread. Pensatela in questo modo: se viene scritto un programma senza
assolutamente utilizzare i thread POSIX, il programma sarà composto da un singolo thread
(questo singolo thread è chiamato thread "principale"). Creando un nuovo thread ora
abbiamo un totale di due thread nel nostro programma.
</p>
<p>
Immagino che abbiate almeno due importanti domande da fare a questo punto. La prima
è cosa il thread principale faccia dopo la creazione del nuovo thread. Continua ed
esegue in sequenza la riga successiva del nostro programma (in questo caso la linea
è "if ( pthread_join(...))"). La seconda domanda a cui potreste pensare è cosa succceda
al nuovo thread una volta che esiste. Si ferma e aspetta di essere unificato o "riunito"
con un altro thread come parte del proprio processo di pulizia.
</p>
<p>
OK, ora di nuovo a pthread_join(). Esattamente come pthread_create() divide il
singolo thread in due thread, pthread_join() unifica due thread in un singolo thread.
Il primo argomento passato a pthread_join() è il nostro "tid" mythread. Il secondo
argomento è un puntatore ad un puntatore vuoto. Se il puntatore vuoto non è NULL,
pthread_join() metterà il valore di ritorno di void * del thread nella locazione
specificata. Poichè non ci interessa il valore di ritorno di pthread_function(),
lo settiamo a NULL.
</p>
<p>
Noterete che thread_function() impiega 20 secondi per arrivare al termine. Molto
prima che thread_function() completi l'esecuzione, il thread principale ha già
chiamato pthread_join(). Quando questo succede il thread principale si blocca (va in
sleep) e aspetta il completamento di thread_function(). Una volta che thread_function()
ha competato il suo compito, pthread_join() ritornerà. Ora il programma ha di nuovo
un thread principale. Quando il nostro programma esce, tutti i nuovi thread sono passati
per la funzione pthread_join(). Questo è esattamente il modo in cui vi dovreste comportare
con ogni nuovo thread creato all'interno dei vostri programmi. Se un nuovo thread non è
ricongiunto continuerà a diminuire il numero massimo di thread eseguibili dal vostro
sistema. Questo significa che la dovuta pulizia, se non effettuata a dovere,
probabilmente causerà un fallimento delle nuove chiamate a pthread_create.
</p>
</body>
</section>
<section>
<title>Niente padri, niente figli</title>
<body>
<p>
Se avete utilizzato la chiamata a sistema fork() probabilmente avete familiarità
col concetto di processi padre e figlio. Quando un processo genera un nuovo processo
utilizzando fork(), il nuovo processo viene considerato figlio e il processo originale
viene considerato padre. Questo crea una relazione gerarchica che può essere conveniente,
in modo particolare durante l'attesa del termine di un processo figlio. La funzione
waitpid(), per esempio, comunicherà al processo corrente di aspettare il termine di uno
dei processi figlio. waitpid() è utilizzata per implementare una semplice routine di
pulizia nei processi padre.
</p>
<p>
Le cose si fanno un po' più interessanti con i thread POSIX. Potreste aver notato
che finora ho volutamente evitato di utilizzare i termini "thread padre" e "thread
figlio". Tutto ciò perchè con i thread POSIX queste relazioni gerarchiche non esistono.
Mentre un thread principale può creare un nuovo thread, e questo nuovo thread può
creare un altro nuovo thread, lo standard dei thread POSIX vede tutti i vostri thread
come un singolo insieme di risorse, uguali fra loro. Per questo motivo il concetto di
attesa dell'uscita di un thread figlio non ha senso. Lo standard dei thread POSIX non
registra nessuna informazione della "famiglia". Questa mancanza di una genealogia ha
un'implicazione più grande: se si vuole attendere il termine di un thread, è necessario
specificare quale si sta aspettando passando l'identificatore appropriato a pthread_join().
La libreria dei thread non può immaginarselo al posto vostro.
</p>
<p>
Per molte persone questa non è una gran bella notizia perchè può rendere più complicati
programmi composti da più di due thread. Non fatevi intimorire. Lo standard dei thread POSIX
fornisce tutti gli strumenti utili per gestire in maniera elegante thread multipli.
Allo stato attuale, il fatto che non ci siano relazioni padre/figlio apre strade nuove
e creative di utilizzare i thread nei vostri programmi. Per esempio, se abbiamo un thread
chiamato thread 1, e thread 1 crea a sua volta un thread chiamato thread 2, non è necessario
allo stesso thread 1 chiamare pthread_join() per il thread 2. Qualsiasi altro thread nel
programma può farlo. Ciò permette interessanti possibilità di scrivere codice che sfrutta
pesantemente il multithread. Potete, per esempio, creare una "dead list" globale che
contenga tutti i thread fermi e poi avere uno speciale thread di pulizia che semplicemente
aspetta che un elemento sia aggiunto alla lista. Il thread di pulizia chiama pthread_join()
per unificarsi con se stesso. Ora l'intera pulizia sarà gestita in modo efficente e armonioso
in un unico thread.
</p>
</body>
</section>
<section>
<title>Nuoto sincronizzato</title>
<body>
<p>
E' giunto finalmente il momento di dare un'occhiata a codice che compia qualcosa
di un po' inaspettato. Ecco thread2.c:
</p>
<pre caption="thread2.c">
#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
int myglobal;
void *thread_function(void *arg) {
int i,j;
for ( i=0; i<20; i++ ) {
j=myglobal;
j=j+1;
printf(".");
fflush(stdout);
sleep(1);
myglobal=j;
}
return NULL;
}
int main(void) {
pthread_t mythread;
int i;
if ( pthread_create( &mythread, NULL, thread_function, NULL) ) {
printf("error creating thread.");
abort();
}
for ( i=0; i<20; i++) {
myglobal=myglobal+1;
printf("o");
fflush(stdout);
sleep(1);
}
if ( pthread_join ( mythread, NULL ) ) {
printf("error joining thread.");
abort();
}
printf("\nmyglobal equals %d\n",myglobal);
exit(0);
}
</pre>
</body>
</section>
<section>
<title>Capire thread2.c</title>
<body>
<p>
Questo programma, proprio come il primo, crea un nuovo thread. Sia il thread
principale che il nuovo thread vanno ad incrementare per 20 volte una variabile
globale chiamata myglobal. Ma il programma stesso produce qualche risultato
inaspettato. Compilarlo digitando:
</p>
<pre caption="Compilare il programma">
$ <i>gcc thread2.c -o thread2 -lpthread</i>
</pre>
<p>
ed eseguirlo:
</p>
<pre caption="Esecuzione">
$ <i>./thread2</i>
..o.o.o.o.oo.o.o.o.o.o.o.o.o.o..o.o.o.o.o
myglobal equals 21
</pre>
<p>
Abbastanza inaspettato! Poichè myglobal parte da zero, e sia il thread principale
che il nuovo thread la incrementano di 20, dovremmo vedere myglobal uguale a 40
alla fine del programma. Dato che myglobal è uguale a 21 sappiamo che sta succedendo
qualcosa di strano. Ma cosa?
</p>
<p>
Rinunciato? OK, vi mostrerò cosa succede. Date un'occhiata a thread_function().
Notate come copiamo myglobal in una variabile locale chiamata "j"? E notate
in che modo incrementiamo j, poi pausa per un secondo e soltanto dopo copiamo il
nuovo valore di j in myglobal? Questa è la chiave. Immaginate cosa succederebbe se
il thread principale incrementasse myglobal soltanto <e>dopo</e> che il nuovo thread
ha copiato il valore di myglobal in j. Quando thread_function() scrive di nuovo
il valore di j in myglobal, va a sovrascrivere le modifiche fatte dal thread
principale.
</p>
<p>
Scrivendo programmi che sfruttano i thread, vorrete evitare inutili side effect
simili a quello appena visto, perchè sono una perdita di tempo (eccezion fatta
se state scrivendo un articolo sui thread POSIX, ovviamente :). E ora cosa
si può fare per eliminare questo problema?
</p>
<p>
Dal momento che il problema si verifica perchè myglobal è stata copiata in j e
fermata per un secondo prima di riscriverla, possiamo provare ad evitare l'uso di una
variabile locale incrementando myglobal in modo diretto. Ma mentre questa soluzione
probabilmente funzionerà in questo particolare esempio, non è corretta. E se stiamo
svolgendo un'operazione matematica relativamente complessa su myglobal invece che
semplicemente incrementarla, certamente fallirà. Ma perchè?
</p>
<p>
Per capire il problema, è necessario ricordare che i thread vanno in esecuzione in
maniera simultanea. Anche su una macchina uniprocessore (dove il kernel utilizza il
time slice per simulare un multitasking reale) possiamo, dalla prospettiva di un
programmatore, immaginare entrambi i thread in esecuzione contemporaneamente. thread2.c
presenta problemi perchè il codice all'interno di thread_function() si basa sul fatto
che myglobal non viene modificata per la durata di 1 secondo prima di essere incrementata.
Ci servono alcuni procedimenti per far sì che un thread comunichi all'altro di "bloccarsi"
fintanto che non vengono effettuate delle modifiche a myglobal. Vi mostrerò in modo esatto
come fare nel mio prossimo articolo. Alla prossima.
</p>
</body>
</section>
</chapter>
<chapter>
<title>Risorse</title>
<section>
<body>
<ul>
<li>
Leggi la spiegazione ai thread POSIX di Daniel <uri link="l-posix2.xml">Part 2</uri>
and <uri link="l-posix3.xml">Part 3</uri>.
</li>
<li>
Leggi la documentazione su <uri
link="http://metalab.unc.edu/pub/Linux/docs/faqs/Threads-FAQ/html/">Linux
threads</uri>, by Sean Walton, KB7rfa
</li>
<li>
Un <uri
link="http://www.math.arizona.edu/swig/pthreads/threads.html">tutorial</uri>
sui thread POSIX scritto da Mark Hays presso la University of Arizona
</li>
<li>
In <uri link="http://hwaci.com/sw/pttcl/pttcl.html">An Introduction to
Pthreads-Tcl</uri>, controllate i cambiamenti a Tcl che la rendono idonea
all'utilizzo con i thread POSIX
</li>
<li>
Un altro tutorial, <uri
link="http://dis.cs.umass.edu/~wagner/threads_html/tutorial.html">Getting
Started with POSIX Threads</uri>, scritto da Tom Wagner and Don Towsley
presso il Computer Science Department della University of Massachusetts,
Amherst
</li>
<li>
Date sempre uno sguardo alla amichevole pagina del manuale di Linux di pthread
(<c>man -k pthread</c>)
</li>
<li>
<uri link="http://moss.csc.ncsu.edu/~mueller/pthreads/">FSU PThreads</uri> è una
libreria C che implementa i thread POSIX per SunOS 4.1.x, Solaris 2.x, SCO
UNIX, FreeBSD, Linux, and DOS
</li>
<li>
Riferimento alla home page di <uri
link="http://www.sai.msu.su/sal/C/2/PCTHREADS.html">thread POSIX e DCE per
Linux</uri>
</li>
<li>
Guardate <uri link="http://pauillac.inria.fr/~xleroy/linuxthreads/">La
libreria LinuxThreads</uri>
</li>
<li>
<uri link="http://www.users.itl.net.ua/~prool/proolix.html">Proolix</uri> è un
semplice sistema operativo per i8086 POSIX-compliant in permanente sviluppo
</li>
<li>
Date un'occhiata al libro di David R. Butenhof <uri
link="http://www.amazon.com/exec/obidos/ASIN/0201633922/o/qid=961544788/sr=8-1/ref=aps_sr_b_1_1/002-2882413-1227240">
Programming with POSIX Threads</uri>, in cui egli ricopre, fra le altre
cose, i possibili cambiamenti nel non utilizzare i mutex
</li>
<li>
Cercate il libro di W. Richard Stevens <uri
link="http://search.borders.com/fcgi-bin/db2www/search/search.d2w/Details?&mediaType=Book&prodID=2362607">UNIX
Network Programming: Network APIs: Sockets and XTI, Volume 1</uri>
</li>
</ul>
</body>
</section>
</chapter>
</guide>
^ permalink raw reply [flat|nested] 2+ messages in thread
* Re: [gentoo-docs-it] Posix Thread Explained, Part 1 - traduzione
2007-05-12 7:01 [gentoo-docs-it] Posix Thread Explained, Part 1 - traduzione Andrea Veroni
@ 2007-05-12 12:02 ` Davide Cendron
0 siblings, 0 replies; 2+ messages in thread
From: Davide Cendron @ 2007-05-12 12:02 UTC (permalink / raw
To: gentoo-docs-it
[-- Attachment #1: Type: text/plain, Size: 929 bytes --]
Il Saturday 12 May 2007 09:01:40 Andrea Veroni ha scritto:
> Posto la mia traduzione per la revisione finale, consigli, segnalazione di
> eventuali errori di forma e/o contenuto (come e' oramai prassi) prima del
> consueto bug report. Essendo un articolo in cui lo scrittore parla in prima
> persona ho lasciato la forma colloquiale, perche' renderlo impersonale non
> rendeva molto l'idea...Se pero' fa schifo posso sempre cambiarlo :)
Ok, ci dò un'occhiata appena posso, e poi ti faccio sapere! :)
>
> Chiedo anche di poter tradurre l-posix2.xml, cosi' continuo con la saga dei
> thread posix che sono tanto carucci :D
Ok, così inoltre tutto il blocco di articoli risulterà più "omogeneo" come
traduzione (essendo stato tradotto dalla stessa persona).
articles/l-posix2.xml tuo, grazie!
--
Davide Cendron
Gentoo Documentation Project
Italian Follow Up Translator
http://www.gentoo.org/doc/it/
[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 189 bytes --]
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2007-05-12 12:03 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-05-12 7:01 [gentoo-docs-it] Posix Thread Explained, Part 1 - traduzione Andrea Veroni
2007-05-12 12:02 ` Davide Cendron
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox