2009-05-31 11 views
5

ho bisogno di risolvere un problema di blocco per questo scenario:Qual è il miglior meccanismo di blocco del kernel Linux per uno specifico scenario

  1. Un sistema CPU multi.
  2. Tutte le CPU utilizzano una risorsa (software) comune.
  3. Leggi solo l'accesso alla risorsa è molto comune. (Elaborazione dei pacchetti di rete in entrata)
  4. L'accesso in scrittura è molto meno frequente. (Solo alcune modifiche alla configurazione).

Attualmente utilizzo il meccanismo read_lock_bh, write_lock_bh (spinlock). Il problema è che maggiore è il numero di CPU, maggiore è il numero di blocchi in un contesto di scrittura.

Ho letto il capitolo sulla concorrenza in this book, , ma non è stato possibile capire se il lettore o lo scrittore avranno priorità quando si utilizzano i blocchi di spin.

Quindi le domande sono:

  1. Vuol il meccanismo spinlock Linux dare priorità al lettore/scrittore di/nessuno di loro?
  2. Esiste un meccanismo migliore che posso utilizzare al fine di evitare quei blocchi molli in mio scenario, o forse un modo per me di dare priorità allo scrittore ogni volta che si cerca di ottenere il blocco, mentre usando la mia soluzione attuale?

Grazie, Nir

+0

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

+0

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. –

+0

@Nir Felice di vederti finalmente accettato una risposta dopo 4 anni :-) –

risposta

5

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.

0

Se il lavoro che fate mentre si tiene il blocco è piccolo si può provare un mutex normale, non il lettore-scrittore. È più efficiente

+0

In genere non ha il senso di avere una macchina multi CPU. Ciò lo renderà utile come una singola CPU. – Nir

3

Non è questo il caso di utilizzo che RCU è progettato per gestire? Vedi http://lwn.net/Articles/262464/ per una buona annotazione sul suo utilizzo.

+0

Ho letto di RCU nel libro che ho citato. Il problema è che, come ho capito, è progettato solo per uno scrittore. Posso avere di più. Inoltre, penso che dovrei cambiare la mia architettura per farla funzionare. Grazie comunque. (Aggiorna tutto e quindi sostituisci solo un puntatore.) – Nir

Problemi correlati