2013-07-02 13 views
10

Cosa succederebbe se chiami read (o write, o entrambi) in due thread diversi, sullo stesso descrittore di file (diciamo che siamo interessati a un file locale, ed è un descrittore di file socket), senza utilizzare esplicitamente un meccanismo di sincronizzazione?C read and thread safety (linux)

Leggere e scrivere sono syscall, quindi, su una CPU single core, è probabilmente sfortunato che due letture vengano eseguite "allo stesso tempo". Ma con più core ...

Cosa farà il kernel linux?

E siamo un po 'più generali: il comportamento è sempre lo stesso per gli altri kernel (come i BSD)?

Modifica: in base allo close documentation, dovremmo essere sicuri che il descrittore di file non sia utilizzato da un syscall in un altro thread. Di conseguenza, sarebbe necessaria una sincronizzazione esplicita prima di chiudere un descrittore di file (e quindi, anche in lettura/scrittura se il thread che potrebbe chiamarlo è ancora in esecuzione).

+2

Non è possibile utilizzare un meccanismo di sincronizzazione; il kernel lo fa già per te. –

+0

Intendo, usando esplicitamente. Quindi il kernel fa tutto il lavoro da solo, e leggere/scrivere/chiamare entrambi su di essi non richiede alcuna sincronizzazione esplicita? –

+0

Per quanto ne so, si. In realtà non sono un esperto di kernel Linux, ma non riesco a immaginarlo diversamente. Forse arriverà qualcuno con una conoscenza più specifica. –

risposta

11

Qualsiasi accesso al descrittore di file di livello di sistema (syscall) è thread-safe in tutti i sistemi operativi UNIX mainstream. Anche se a seconda dell'età non sono necessariamente sicuri.

Se si chiama read, write, accept o simile su un descrittore di file da due task diversi, il meccanismo di blocco interno del kernel risolverà la contesa.

Per le letture, ogni byte può essere letto una sola volta e le scritture andranno in ordine indefinito.

La libreria stdio funziona fread, fwrite e co. hanno anche il blocco interno di default sulle strutture di controllo, anche se usando i flag è possibile disabilitarlo.

+1

Ciao. Puoi pubblicare una documentazione ufficiale che contrassegni queste funzioni come thread-safe. – felknight

+1

Sarei davvero felice se si possano aggiungere collegamenti ad alcuni documenti ufficiali sia per lettura/scrittura/accettazione che per estensione/scrittura :) –

+0

Sono abbastanza sicuro che glibc non sarà thread-safe su fread, fwrite a meno che non si colleghi a libpthread . Ma ovviamente se stai usando thread allora dovrebbe già essere vero. –

0

Il risultato dipenderà dal modo in cui i thread sono pianificati per l'esecuzione in quel particolare istante di tempo.

Un modo per evitare potenzialmente un comportamento non definito con il multithreading è presupporre che si stiano facendo operazioni di memoria. Per esempio. aggiornare un elenco collegato o modificare una variabile, ecc.

Se si utilizza il mutex/semaphores/lock o qualche altro meccanismo di sincronizzazione, dovrebbe funzionare come previsto.

2

Il commento su chiudi è perché non ha molto senso chiudere un descrittore di file in qualsiasi situazione in cui qualche altro thread potrebbe tentare di usarlo. Quindi, mentre è "sicuro" per quanto riguarda il kernel, può portare a casi d'angolo strani, difficili da diagnosticare.

Se un thread chiude un descrittore di file mentre un secondo thread tenta di leggere da esso, il secondo thread potrebbe ricevere un errore EBADF imprevisto. Peggio ancora, se un terzo thread apre simultaneamente un nuovo file, questo potrebbe riallocare lo stesso fd e il secondo thread potrebbe accidentalmente leggere dal nuovo file anziché quello che si aspettava ...

1

Avere cura di chi segue le tue orme

È perfettamente normale proteggere il descrittore di file con un semaforo mutex. Rimuove qualsiasi dipendenza dal comportamento del kernel, quindi i limiti dei messaggi sono ora certi.Quindi non devi citare l'ultimo paragrafo nella parte inferiore di una manpage di 15.489 righe che spiega perché il mutex non è necessario (ho esagerato, ma hai capito)

Inoltre rende chiaro a chiunque la lettura il tuo codice che il descrittore di file viene utilizzato da più di un thread.

Fringe Benefit

C'è un fringe benefit di utilizzare un mutex in quel modo. Supponiamo che tu abbia messaggi diversi provenienti da diversi thread e alcuni di questi messaggi siano più importanti di altri. Tutto quello che devi fare è impostare le priorità del thread per riflettere l'importanza dei loro messaggi. In questo modo il sistema operativo assicurerà che i tuoi messaggi vengano inviati in ordine di importanza per il minimo sforzo da parte tua.