2010-08-25 18 views
7

Por curiosidad, ¿cuál es la forma preferida de lograr la sincronización entre procesos en Linux? La familia de llamadas al sistema sem*(2) parece tener una interfaz muy anticuada y anticuada, mientras que hay tres formas de bloquear archivos: fcntl(), flock() y lockf().File Locking vs. Semaphores

¿Cuáles son las diferencias internas (si las hay) y cómo justificaría el uso de cada una?

Respuesta

8

Ninguno. Las versiones actuales de pthread_* (por ejemplo, phtread_mutex_t) permiten colocar las variables en segmentos compartidos que se crean a través de shm_open. Solo tiene que colocar algún parámetro adicional a las llamadas init.

No usar semáforos (sem_t) si no tiene que hacerlo, que son de muy bajo nivel y se veía interrumpida por IO etc.

No abuse del archivo de bloqueo para el control entre procesos. No está hecho para eso. En particular, no tiene la posibilidad de vaciar los metadatos de los archivos, como bloqueos, por lo que nunca se sabe cuándo un bloqueo/desbloqueo será visible en un segundo proceso.

+0

Recuerdo que pthread_mutex_t en una memoria compartida a veces causa problemas, si no recuerdo mal en el kernel 2.4.x. ¿Sabes algo sobre eso? – DarkDust

+0

@DarkDust: versiones de kernel anteriores a 2.6.algo (pero hace muchos años) tenía una implementación pthread diferente, que de hecho no era adecuada para el control entre procesos. Esto es historia. De todos modos, la llamada 'init' correspondiente le indicará a la vuelta si el atributo' pshared' no es compatible con la implementación. –

+0

¿Sacrificas la portabilidad con esta técnica? – bstpierre

2

Las diferentes implementaciones de bloqueo/semáforos cobraron vida en diferentes sistemas. En System V Unix tenía semget/semop, POSIX definió una implementación diferente con sem_init, sem_wait y sem_post. Y flock se originó en 4.2BSD, por lo que pude averiguar.

Dado que todos obtuvieron un cierto significado, Linux los admite a todos ahora para facilitar la transferencia. Además, flock es un mutex (ya sea bloqueado o desbloqueado), pero las funciones sem* (tanto SysV como POSIX) son semáforos: permiten que una aplicación otorgue acceso a varios procesos concurrentes, p. podría permitir el acceso a un recurso a 4 procesos simultáneos con semáforos. Puede implementar un mutex con semáforos pero no al revés. Recuerdo que en la excelente "Advanced UNIX Programming" de Marc J. Rochkind demostró cómo transmitir datos entre procesos a través de semáforos (muy ineficiente, lo hizo solo para demostrar que se puede hacer). Pero no pude encontrar nada confiable sobre la eficiencia.

Supongo que es más como "Usa lo que quieras".

+0

¿por qué no se puede implementar un semáforo utilizando mutexes? –

+1

@Anurag Uniyal: Porque un mutex tiene solo dos estados: bloqueado o desbloqueado. Un semáforo es un contador y, por lo tanto, tiene más de dos estados. – DarkDust

+0

Esto no parece correcto. No veo ninguna razón por la cual no se pueda hacer un semáforo usando un mutex. –

4

Estás sufriendo una gran cantidad de opciones de una rica historia, como señaló DarkDust. Por lo que vale la pena, mi árbol de decisiones es algo como esto:

Use mutexes cuando solo se puede acceder a un proceso/subproceso a la vez.

Use semáforos cuando dos o más procesos/subprocesos (aunque finitos) pueden usar un recurso.

Usa semáforos POSIX a menos que realmente necesites algo que los semáforos SYSV tengan, p. DESHACER, PID de la última operación, etc.

Utilice el bloqueo de archivos o si lo anterior no se ajusta a sus requisitos de alguna manera.

2

Una diferencia potencialmente significativa podría ser la equidad de la distribución de recursos. No conozco los detalles de la implementación de la familia semget/semop, pero sospecho que normalmente se implementa como un semáforo "tradicional" en lo que respecta a la programación. En general, creo que los hilos liberados se manejan en una base FIFO (el primero que espera que el semáforo se libere primero).No creo que esto ocurra con el bloqueo de archivos, ya que sospecho (de nuevo, solo estoy adivinando) que el manejo no se realiza a nivel del kernel.

Tenía el código existente sentado para probar los semáforos para propósitos de IPC, por lo que comparé las dos situaciones (una usando semop y otra usando lockf). Hice la prueba de un pobre y simplemente corrí a las instancias de la aplicación. El semáforo compartido se usó para sincronizar el inicio. Al ejecutar la prueba de semop, ambos procesos terminaron 3 millones de bucles casi sincronizados. El loopf lockf, por otro lado, no era tan justo. Un proceso normalmente termina mientras que el otro solo ha completado la mitad de los bucles.

El ciclo para la prueba de semop se veía como el siguiente. Las funciones semwait y semsignal son solo envoltorios para las llamadas semop.

ct = myclock(); 
    for (i = 0; i < loops; i++) 
     { 
     ret = semwait("test", semid, 0); 
     if (ret < 0) { perror("semwait"); break; } 

     if ((i & 0x7f) == 0x7f) 
     printf("\r%d%%", (int)(i * 100.0/loops)); 

     ret = semsignal(semid, 0); 
     if (ret < 0) { perror("semsignal"); break; } 
     } 
    printf("\nsemop time: %d ms\n", myclock() - ct); 

El tiempo de ejecución total para ambos métodos fue casi la misma, aunque la versión lockf realidad era más rápido en general a veces debido a la injusticia de la programación. Una vez que el primer proceso haya finalizado, el otro proceso tendrá acceso no disputado durante aproximadamente 1,5 millones de iteraciones y se ejecutará extremadamente rápido.

Cuando se ejecuta sin prueba (proceso único que obtiene y libera los bloqueos), la versión semop fue más rápida. Tomó aproximadamente 2 segundos para 1 millón de iteraciones, mientras que la versión de lockf tomó aproximadamente 3 segundos.

Este ensayo se realizó de la siguiente versión:

[]$ uname -r 
2.6.11-1.1369_FC4smp 
+0

Los semáforos del sistema AFAIK son completamente dependientes del programador del sistema operativo y no tienen ninguna inteligencia propia. Aunque se puede establecer una política general de programación de hilos, la secuencia de liberación de hilos va a ser indeterminada en cualquier sentido práctico. – Duck

+0

@Duck, eso es ciertamente cierto; sería incorrecto esperar que los hilos sean lanzados en cierto orden. Pero su punto de que los semáforos dependen del sistema operativo es el punto crítico. Debido a que el sistema operativo toma la decisión, puede aplicar las reglas de "imparcialidad" que desee (ya sea una aproximación de FIFO o incluso un lanzamiento aleatorio de la moneda).Cuando se lanza un bloqueo de archivos, no creo que ocurra el mismo tipo de toma de decisiones en el núcleo. –