AJM*_*eld 11 shell-script concurrency loop-device
我正在编写一些 shell 脚本来处理一些磁盘映像,我需要使用循环设备来访问一些磁盘映像。但是,我不确定如何在不将我的程序暴露于竞争条件的情况下正确分配循环设备。
我知道我可以losetup -f
用来获取下一个未分配的循环设备,然后像这样分配该循环设备:
ld=$(losetup -f)
sudo losetup $ld myfile.img
dostuffwith $ld
Run Code Online (Sandbox Code Playgroud)
但是,在我想同时运行多个程序实例的情况下,这几乎是竞争条件的教科书示例,这让我非常困扰。如果我有这个程序的多个实例正在运行,或者其他程序也试图获得一个循环设备,那么每个进程可能无法在下一个调用之前分配循环设备losetup -f
,在这种情况下,两个进程都会认为同一个循环设备可用,但只有一个人可以得到它。
我可以为此使用外部同步,但我想(如果可能)避免额外的复杂性。此外,使用循环设备的其他程序可能不会尊重我可能提出的任何同步。
我怎样才能避免这种潜在的竞争条件?理想情况下,我希望能够以原子方式发现和绑定循环设备,例如使用如下命令:
ld=$(sudo losetup -f myfile.img)
dostuffwith $ld
Run Code Online (Sandbox Code Playgroud)
但是,当我这样做时,$ld
不会被分配到循环设备路径,并sudo
移出,因为在sudo ld=$(losetup -f myfile.img)
给出权限错误。
Gil*_*il' 14
这是并发中的一个经典问题:在分配资源时,您需要原子地确定该资源是空闲的并保留它,否则另一个进程可能会在您检查它空闲的时间和您保留它的时间之间保留该资源。
请使用losetup
的自动分配模式 ( -f
),并传递--show
选项以使其打印循环设备路径。
ld=$(sudo losetup --show -f /tmp/1m)
Run Code Online (Sandbox Code Playgroud)
自 2.13 版以来,该选项已出现在 util-linux 中(最初添加为-s
,但--show
已在所有已发布版本中得到支持,并且最近的版本已删除-s
选项名称)。不幸的是 BusyBox 版本没有它。
Linux 内核 3.1 版引入了一种通过新/dev/loop-control
设备直接在内核中执行循环设备分配操作的方法。此方法仅从 util-linux 2.21 开始支持。对于内核 <3.1 或 util-linux <2.21,losetup
程序枚举循环设备条目以保留一个。但是我在代码中看不到竞争条件;它应该是安全的,但它可能有一个小窗口,在此期间它会错误地报告所有设备都已分配,即使情况并非如此。
我想到了。虽然我不确定许可的问题是什么,但我可以先拍摄,然后像这样询问:
sudo losetup -f myfile.img
ld=$(losetup -j myfile.img | grep -o "/dev/loop[0-9]*")
dostuffwith $ld
Run Code Online (Sandbox Code Playgroud)