Estoy escribiendo algunos scripts de shell para manejar algunas cosas de imagen de disco, y necesito usar dispositivos de bucle para acceder a algunas imágenes de disco. Sin embargo, no estoy seguro de cómo asignar correctamente un dispositivo de bucle sin exponer mi programa a una condición de carrera.
Sé que puedo usar losetup -f
para obtener el siguiente dispositivo de bucle sin asignar, y luego asignar ese dispositivo de bucle de esta manera:
ld=$(losetup -f)
sudo losetup $ld myfile.img
dostuffwith $ld
Sin embargo, en el caso en que quiero ejecutar varias instancias del programa al mismo tiempo, este es casi un ejemplo de libro de texto de una condición de carrera, y eso me molesta bastante. Si tuviera varias instancias de este programa ejecutándose, u otros programas que también intentan obtener un dispositivo de bucle, entonces cada proceso podría no ser capaz de asignar el dispositivo de bucle antes de que la próxima llamada losetup -f
, en cuyo caso ambos procesos pensarían que el mismo bucle el dispositivo está disponible, pero solo uno puede obtenerlo.
Podría usar sincronización externa para esto, pero me gustaría (si es posible) evitar una complejidad adicional. Además, otros programas que usan dispositivos de bucle probablemente no respetarían la sincronización que se me ocurra.
¿Cómo puedo evitar esta posible condición de carrera? Idealmente, me gustaría poder descubrir y enlazar el dispositivo de bucle atómicamente, por ejemplo con un comando como:
ld=$(sudo losetup -f myfile.img)
dostuffwith $ld
Sin embargo, cuando hago eso, $ld
no se asigna a la ruta del dispositivo de bucle, y moverlo sudo
hacia afuera, como en sudo ld=$(losetup -f myfile.img)
da errores de permiso.
fuente
</dev/tty
de?losetup --find --show
carreras.for i in {1..100}; do losetup -f -s $i & done
no me dio 100 dispositivos de bucle. Los dispositivos de bucle son poco comunes para que no importe normalmente; si lo hace, su única opción es hacer sus propios bloqueos y / o verificar que el dispositivo de bucle correcto se haya creado como una ocurrencia tardía.losetup
puede fallar (por ejemplo, porque se ha quedado sin entradas de bucle), pero si informa un nombre de dispositivo, ese es el dispositivo que asignó con éxito. ¿Las versiones anteriores tenían un error que causaba que escribiera un nombre de dispositivo aunque la asignación había fallado? Veo en el código fuente que la interfaz para la asignación en el núcleo solo existe desde el núcleo 3.1, ¿es quizás un error con la interfaz anterior que requiere ellosetup
utilidad realice la búsqueda?/dev/loop14
y tal y el dispositivo puede faltar por completo al final. Tal vez la solución es cortesía/dev/loop-control
, solía mirar/proc/partitions
...losetup
usa/dev/loop-control
si está presente, y no parece que pueda tener una condición de carrera: la asignación ocurre en el kernel e imprimir la ruta del dispositivo es lo último que hace la utilidad.Me lo imaginé. Si bien no estoy seguro de cómo es el problema con el permiso, puedo disparar primero y preguntar más tarde de esta manera:
fuente
Podrías usar
flock
:La idea aquí es que intentes y
flock
el archivo del dispositivo de bucle; si otra instancia del mismo script lo adquiere primero, llamarálosetup $ld myfile.img
yflock
devolverá 0. Para el script que pierde la carrera,losetup
no se llamará yflock
devolverá 1, haciendo que el ciclo se repita.Para más ver
man flock
.fuente
Si todo lo que desea hacer con la imagen como dispositivo de bucle invertido es montarla como un sistema de archivos y trabajar con los contenidos, el
mount
comando puede encargarse de esto automáticamente.fuente