2009-05-31 17 views
5

que necesito para resolver un problema de bloqueo para este escenario:¿Cuál es el mejor mecanismo de bloqueo del núcleo de Linux para un escenario específico

  1. Un sistema de múltiples CPU.
  2. Todas las CPU utilizan un recurso común (software).
  3. El acceso de solo lectura al recurso es muy común. (Procesamiento de paquetes de red entrantes)
  4. El acceso de escritura es mucho menos frecuente. (Casi cambios de configuración solamente).

Actualmente uso el, write_lock_bh (spinlocks) mecanismo read_lock_bh. El problema es que cuantas más CPU hay, más obtengo bloqueos suaves en un contexto de escritor.

He leído el capítulo de concurrencia en this book, Pero no pude entender si el lector o el escritor tendrán prioridad al usar bloqueos giratorios.

Así que las preguntas son:

  1. ¿El mecanismo de spinlock Linux dar prioridad al lector/escritor/ninguno de ellos?
  2. ¿Hay algún mecanismo mejor que pueda usar para evitar esos bloqueos suaves en mi escenario, o quizás una forma de dar prioridad al escritor siempre que intente obtener el bloqueo, mientras uso mi solución actual?

Gracias, Nir

+0

No conozco la respuesta a esta pregunta, pero el libro "Understanding the Linux Kernel" tiene mucha información buena sobre este tipo de cosas. Es un gran libro, cualquiera que haga un trabajo de kernel debería leerlo. – Zifre

+0

No sé mucho acerca de las funciones internas de concurrencia del kernel, pero puede hacer las suyas propias con el recuento de lector/escritor y bloqueos en writer-wait. –

+0

@Nir Me alegra ver que finalmente aceptó una respuesta después de 4 años :-) –

Respuesta

5

Aquí hay una cita directa de Essential Linux Device Drivers que podría ser lo que estás buscando. Parece que la parte dedicada a la UCR al final puede ser lo que le interesa.

Cerraduras lector-grabador de

Otro mecanismo de regulación de concurrencia especializada es una variante de un lector-grabador de spinlocks. Si el uso de una sección crítica de es tal que los subprocesos separados leen o escriben en una estructura de datos compartida, pero no hacen , estos bloqueos son naturales. Múltiples hilos de lectura están permitidos dentro de una región crítica simultáneamente. spinlocks Reader se definen como sigue:

rwlock_t myrwlock = RW_LOCK_UNLOCKED; 

read_lock(&myrwlock);    /* Acquire reader lock */ 
/* ... Critical Region ... */ 
read_unlock(&myrwlock);   /* Release lock */ 

Sin embargo, si un hilo escritor entra en una sección crítica, otros hilos lector o escritor no están permitidos dentro. Para utilizar spinlocks escritor, que iba a escribir esto:

rwlock_t myrwlock = RW_LOCK_UNLOCKED; 

write_lock(&myrwlock);   /* Acquire writer lock */ 
/* ... Critical Region ... */ 
write_unlock(&myrwlock); /* Release lock */ 

mirar el código de enrutamiento IPX presente en net/ipx/ipx_route.c para un ejemplo real de un spinlock un lector-grabador. Un bloqueo de lector-escritor llamado ipx_routes_lock protege la tabla de enrutamiento IPX del acceso simultáneo.Los hilos que necesitan buscar la tabla de enrutamiento para reenviar paquetes solicitan bloqueos de lector. Los subprocesos que deben agregar o eliminar entradas de la tabla de enrutamiento adquieren bloqueos de escritor. Esto mejora el rendimiento porque generalmente hay muchas más instancias de búsquedas en la tabla de enrutamiento que las actualizaciones de la tabla de enrutamiento.

Como spinlocks regulares, bloqueos lector-grabador también tienen IRQ correspondientes variantes, a saber: read_lock_irqsave(), read_lock_irqrestore(), write_lock_irqsave(), y write_lock_irqrestore(). La semántica de estas funciones son similares a las de los spinlocks normales.

Los bloqueos de secuencia o seqlocks, introducidos en el kernel 2.6, son bloqueos lector-escritor donde los escritores son favorecidos por sobre los lectores . Esto es útil si las operaciones de escritura en una variable superan con creces los accesos de lectura. Un ejemplo es la variable jiffies_64 explicada anteriormente en este capítulo. Los hilos de Writer no esperan a los lectores que pueden estar dentro de en una sección crítica. Debido a esto, las discusiones lector puede descubrir que su entrada dentro de una sección crítica no ha logrado y puede que tenga que volver a intentar:

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; 
} 

escritores proteger las regiones más importantes usando write_seqlock() y write_sequnlock().

el kernel 2.6 introdujo otro mecanismo llamado Leer-Copy Update (RCU), que los rendimientos mejoraron el rendimiento cuando los lectores son mucho más numerosos escritores. La idea básica es que los hilos lectores pueden ejecutarse sin bloqueando. Los hilos del escritor son más complejos. Realizan operaciones de actualización en una copia de la estructura de datos y reemplazan el puntero que ven los lectores. La copia original se mantiene hasta que el siguiente contexto encienda todas las CPU a para garantizar la finalización de todas las operaciones de lectura en curso. Tenga en cuenta que el uso de RCU es más complicado que utilizar las primitivas discutidas hasta el momento y debe usarse solo si está seguro de que es la herramienta adecuada para el trabajo. Las estructuras y funciones de interfaz RCU se definen en include/linux/rcupdate.h. Hay amplia documentación en Documentation/RCU/*.

Para un ejemplo de uso UCR, un vistazo a fs/dcache.c. En Linux, cada archivo está asociado con la entrada de directorio información (almacenada en una estructura llamada dentry), información de metadatos (almacenada en un inodo) y datos reales (almacenados en bloques de datos). Cada vez que opera en un archivo, los componentes en la ruta del archivo se analizan y se obtienen las anotaciones correspondientes . Las dentries se guardan en caché en una estructura de datos llamada dcache, al agilizar las operaciones futuras. En cualquier momento, el número de consultas de caché es mucho más que las actualizaciones de caché, por lo que las referencias al caché están protegidas utilizando primitivas de RCU.

0

Si el trabajo que haces mientras mantiene el bloqueo es pequeño se puede tratar un mutex normal, no un lector-grabador. Es más eficiente.

+0

En cierto modo se pierde el sentido de tener una máquina de múltiples CPU. Esto lo hará tan útil como una sola máquina de CPU. – Nir

3

¿No es este el tipo de caso de uso que RCU está diseñado para manejar? Ver http://lwn.net/Articles/262464/ para una buena redacción en su uso.

+0

Leí sobre RCU en el libro que mencioné. El problema es que, según tengo entendido, está diseñado solo para un escritor. Puedo tener mas Además, creo que tendría que cambiar mi arquitectura para que funcione. Gracias sin embargo. (Actualice todo y luego simplemente reemplace un puntero). – Nir

Cuestiones relacionadas