Ecco una citazione diretta da Essential Linux Device Drivers che potrebbe essere quello che stai cercando. Sembra che la parte a che fare con telecomando alla fine può essere quello che ti interessa.
Serrature Reader-Writer
Un altro meccanismo di regolazione della concorrenza specializzata è una variante di lettura-scrittura di spinlocks. Se l'utilizzo di una sezione critica è tale che i thread separati vengono letti o scritti in una struttura di dati condivisa, ma non lo fanno entrambi, questi blocchi sono una scelta naturale. Sono consentiti più thread di lettura all'interno di un'area critica simultaneamente. spinlocks Reader sono definiti come segue:
rwlock_t myrwlock = RW_LOCK_UNLOCKED;
read_lock(&myrwlock); /* Acquire reader lock */
/* ... Critical Region ... */
read_unlock(&myrwlock); /* Release lock */
Tuttavia, se un thread scrittore entra in una sezione critica, altri thread lettore o scrittore non sono ammessi all'interno. Per utilizzare spinlocks scrittore, si potrebbe scrivere questo:
rwlock_t myrwlock = RW_LOCK_UNLOCKED;
write_lock(&myrwlock); /* Acquire writer lock */
/* ... Critical Region ... */
write_unlock(&myrwlock); /* Release lock */
sguardo al codice di routing IPX presente in net/ipx/ipx_route.c
per un esempio reale di uno spinlock di lettura-scrittura. Un blocco lettore-scrittore chiamato ipx_routes_lock
protegge la tabella di routing IPX dall'accesso simultaneo.Thread che ha bisogno di cercare la tabella di routing per inoltrare i blocchi del lettore di richiesta dei pacchetti. I thread che devono aggiungere o eliminare le voci dalla tabella di routing acquisiscono i blocchi del writer. Ciò migliora le prestazioni perché di solito ci sono molte più ricerche di tabelle di routing rispetto agli aggiornamenti delle tabelle di routing.
Come spinlocks regolari, serrature lettore-scrittore hanno anche corrispondente IRQ varianti, cioè, read_lock_irqsave()
, read_lock_irqrestore()
, write_lock_irqsave()
e write_lock_irqrestore()
. La semantica di queste funzioni è simile a quella dei normali spinlock.
I blocchi sequenza o seqlocks, introdotti nel kernel 2.6, sono blocchi di lettore-scrittore in cui gli scrittori sono preferiti rispetto ai lettori . Ciò è utile se le operazioni di scrittura su una variabile superano di gran lunga gli accessi in lettura. Un esempio è la variabile jiffies_64
discussa in precedenza in questo capitolo. I thread di Writer non attendono i lettori che potrebbero trovarsi all'interno di una sezione critica. A causa di questo, le discussioni lettore può scoprire che il loro ingresso all'interno di una sezione critica non è riuscito e potrebbe essere necessario ripetere:
u64 get_jiffies_64(void) /* Defined in kernel/time.c */
{
unsigned long seq;
u64 ret;
do {
seq = read_seqbegin(&xtime_lock);
ret = jiffies_64;
} while (read_seqretry(&xtime_lock, seq));
return ret;
}
Writers proteggere regioni critiche utilizzando write_seqlock()
e write_sequnlock()
.
I kernel 2.6 ha introdotto un altro meccanismo chiamato Read-Copy Update (RCU), che produce migliorati prestazioni quando i lettori sono molto più numerosi scrittori. L'idea di base è che i thread del lettore possano essere eseguiti senza il blocco . I thread di writer sono più complessi. Eseguono operazioni di aggiornamento su una copia della struttura dati e sostituiscono il puntatore che i lettori vedono. La copia originale viene mantenuta fino a quando il successivo interruttore di contesto su tutte le CPU su assicura il completamento di tutte le operazioni di lettura in corso. Si noti che l'uso di RCU è più complicato rispetto all'uso delle primitive discusse finora e dovrebbe essere utilizzato solo se si è certi che sia lo strumento giusto per il lavoro. Dati RCU strutture e funzioni di interfaccia sono definite in include/linux/rcupdate.h
. C'è un'ampia documentazione in Documentation/RCU/*
.
Per un esempio di utilizzo RCU, vedere fs/dcache.c
. Su Linux, ogni file è associato alle informazioni della rubrica (memorizzate in una struttura denominata dentry), alle informazioni sui metadati (memorizzate in un inode) e ai dati effettivi (memorizzati nei blocchi di dati). Ogni volta che si opera su un file, vengono analizzati i componenti nel percorso del file e si ottengono le dentellature corrispondenti . Le dentisie vengono tenute nella cache in una struttura dati chiamata dcache, per accelerare le operazioni future. In qualsiasi momento, il numero di ricerche di dcache è molto più che gli aggiornamenti di dcache, quindi i riferimenti a dcache vengono protetti utilizzando primitive RCU.
Non conosco la risposta a questa domanda, ma il libro "Capire il kernel di Linux" ha molte buone informazioni su questo tipo di cose. È un libro davvero fantastico, chiunque lavori sul kernel dovrebbe leggerlo. – Zifre
Non si sa molto sugli interni della concurrency kernel, ma si potrebbe eseguire il roll-out con il conteggio di lettori/scrittori e bloccare su writer-wait. –
@Nir Felice di vederti finalmente accettato una risposta dopo 4 anni :-) –