Bir döngü cihazı atomik olarak nasıl tahsis edilir?


11

Bazı disk görüntü şeylerini işlemek için bazı kabuk komut dosyaları yazıyorum ve bazı disk görüntülerine erişmek için döngü aygıtlarını kullanmam gerekiyor. Ancak, benim programımı bir yarış durumuna maruz kalmadan bir döngü cihazı düzgün tahsis nasıl emin değilim.

Bir losetup -fsonraki ayrılmamış döngü aygıtı almak için kullanabileceğinizi biliyorum , ve sonra bu döngü aygıtını şu şekilde tahsis edebilirim:

ld=$(losetup -f)
sudo losetup $ld myfile.img
dostuffwith $ld

Ancak, aynı anda programın birden fazla örneğini çalıştırmak istediğim durumda, bu neredeyse bir yarış durumu ders kitabı örneğidir ve bu beni oldukça rahatsız ediyor. Bu programın birden fazla örneğini çalıştırıyor olsaydım veya bir döngü aygıtı almaya çalışan başka programlar da varsa, her işlem bir sonraki çağrıdan önce döngü aygıtını ayıramayabilir losetup -f, bu durumda her iki işlem de aynı döngüyü düşünürdü kullanılabilir, ancak yalnızca bir tanesi bunu alabilir.

Bunun için harici senkronizasyon kullanabilirsiniz, ancak (mümkünse) ek karmaşıklıktan kaçınmak istiyorum. Ayrıca, döngü aygıtlarını kullanan diğer programlar, karşılaşabileceğim senkronizasyonlara saygı duymaz.

Bu potansiyel yarış koşulundan nasıl kaçınabilirim? İdeal olarak, döngü cihazını atomik olarak, örneğin aşağıdaki gibi bir komutla keşfetmek ve bağlamak istiyorum:

ld=$(sudo losetup -f myfile.img)
dostuffwith $ld

Ancak, bunu yaptığımda $ld, döngü aygıt yoluna atanmaz ve izin verir sudogibi , dışarı taşıma sudo ld=$(losetup -f myfile.img).

Yanıtlar:


13

Bu eşzamanlılıktaki klasik bir sorundur: bir kaynağı tahsis ederken, kaynağın ücretsiz olduğunu ve rezervini atomik olarak belirlemeniz gerekir, aksi takdirde başka bir işlem, ücretsiz olup olmadığını kontrol ettiğiniz zaman ile ayırdığınız zaman arasında kaynağı ayırabilir.

Kullanım Do losetup'ın otomatik ayırma modu ( -f) ve pas --showo döngü cihazı yolunu yazdırmak yapma seçeneğini.

ld=$(sudo losetup --show -f /tmp/1m)

Bu seçenek, 2.13 sürümünden beri util-linux'da bulunmaktadır ( başlangıçta olarak eklenmiştir-s , ancak --showtüm yayınlanmış sürümlerde desteklenmiştir ve son sürümler -sseçenek adını bırakmıştır ). Ne yazık ki BusyBox sürümü buna sahip değil.

Linux çekirdeğinin 3.1 sürümü , döngü aygıtı ayırma işlemini yeni aygıt aracılığıyla doğrudan çekirdeğe gerçekleştirmek için bir yöntem sundu/dev/loop-control . Bu yöntem yalnızca util-linux 2.21'den beri desteklenmektedir. Çekirdek <3.1 veya util-linux <2.21 ile, losetupprogram bir tane ayırmak için döngü cihazı girişlerini numaralandırır. Yine de kodda bir yarış durumu göremiyorum; güvenli olmalıdır, ancak durum böyle olmasa bile tüm cihazların tahsis edildiğini yanlış bildireceği küçük bir pencere olabilir.


Ne </dev/ttyiçin?
Stéphane Chazelas

1
En son denediğimde bile losetup --find --showyarışları. for i in {1..100}; do losetup -f -s $i & donebana 100 loop cihazı vermedi. Döngü aygıtları, normal olarak önemli olmaması için yeterince nadirdir; eğer tek seçeneğiniz kendi kilitlerinizi yapmak ve / veya doğru döngü cihazının sonradan düşünülmüş olarak yaratıldığını kontrol etmektir.
frostschutz

@frostschutz losetupbaşarısız olabilir (örn. döngü girişleriniz bittiği için ), ancak bir cihaz adı bildirirse, başarıyla tahsis edildiği cihaz budur. Önceki sürümlerde, ayırma başarısız olsa bile bir aygıt adı yazmasına neden olan bir hata var mı? Ben kaynak kodu görüyorum ki çekirdek içi tahsisi için arayüz sadece çekirdek 3.1 beri var, belki losetuparama yapmak için yardımcı programı gerektiren eski arayüzü ile bir hata mı?
Gilles 'SO- kötü olmayı bırak'

Oh, gerçekten daha yeni sürümlerde düzeltilmiş gibi görünüyor. util-linux-2.26.2 işe yarıyor gibi görünüyor, util-linux-2.24.1 tekrar tekrar yazdırıyor /dev/loop14ve bu gibi cihazlar sonunda tamamen eksik olabilir. Belki düzeltme nezaket, /dev/loop-controlsadece bakmak için kullanılır /proc/partitions...
frostschutz

@frostschutz util-linux 2.21 olduğundan losetup, /dev/loop-controlvarsa kullanır ve bu bir yarış koşulu olabilir gibi görünmüyor: ayırma çekirdekte olur ve aygıt yolunu yazdırma yardımcı programın yaptığı son şeydir.
Gilles 'SO- kötü olmayı bırak'

6

Bunu anladım. İzin meselesiyle ilgili sorunun nasıl olduğundan emin olmasam da, önce çekim yapıp daha sonra şu şekilde sorabilirim:

sudo losetup -f myfile.img
ld=$(losetup -j myfile.img | grep -o "/dev/loop[0-9]*")
dostuffwith $ld

2

Şunları kullanabilirsiniz flock:

  tryagain=1
  while [[ $tryagain -ne 0 ]]; do
    ld=`losetup -f`
    flock -n $ld -c "losetup $ld myfile.img"
    tryagain=$?
  done

Burada fikir denemek ve flockdöngü aygıt dosyası; Aynı senaryonun başka örneği önce onu edinmesi halinde, bu aramaya alacak losetup $ld myfile.imgve flockyarış kaybeder script 0 döndürür, losetupdenilen edilmeyecek ve flockdöngü tekrar neden 1 dönecektir.

Daha fazla bilgi için man flock.


0

Bir geridöngü aygıtı olarak görüntü ile yapmak istediğiniz her şey onu bir dosya sistemi olarak bağlar ve içeriklerle çalışırsa, mountkomut bunu otomatik olarak halledebilir.

mount -o loop myfile.img /tmp/mountpoint

Aslında benim durumumda, özellikle istediğim değil ben bir blok cihazına değil dosya sistemi olarak kullanıyorum - monteli.
AJMansfield

@AJMansfield Bağlamak dışında, bir dosyayla yapamayacağınız bir blok cihazla ne yapabilirsiniz?
Random832

Tam disk btrfs kurulumunda takas alanı olarak biçimlendiremezsiniz. Dosyayı takas alanı için kullanmayı planlıyordum, çünkü btrfs takas dosyaları için gereken işlemleri desteklemiyor ve tam disk btrfs kurulumuyla gerçek bir takas bölümüm olamaz.
AJMansfield
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.