디스크 이미지를 처리하기 위해 일부 쉘 스크립트를 작성 중이며 루프 장치를 사용하여 일부 디스크 이미지에 액세스해야합니다. 그러나 프로그램을 경쟁 조건에 노출시키지 않고 루프 장치를 올바르게 할당하는 방법을 잘 모르겠습니다.
losetup -f
할당되지 않은 다음 루프 장치를 가져 와서 다음과 같이 해당 루프 장치를 할당하는 데 사용할 수 있다는 것을 알고 있습니다 .
ld=$(losetup -f)
sudo losetup $ld myfile.img
dostuffwith $ld
그러나 동시에 프로그램의 여러 인스턴스를 실행하려는 경우 경쟁 조건의 거의 모든 교과서 예제이며 상당히 귀찮게합니다. 이 프로그램의 여러 인스턴스가 실행 중이거나 루프 장치를 얻으려고 시도하는 다른 프로그램이있는 경우 각 프로세스는 다음 프로세스가 호출되기 전에 루프 장치를 할당하지 못할 수 있습니다 losetup -f
.이 경우 두 프로세스 모두 동일한 루프라고 생각합니다. 장치는 사용할 수 있지만 하나만 얻을 수 있습니다.
이를 위해 외부 동기화를 사용할 수 있지만 가능한 경우 추가 복잡성을 피하고 싶습니다. 또한 루프 장치를 사용하는 다른 프로그램은 내가 만든 동기화를 존중하지 않을 것입니다.
이 잠재적 경쟁 조건을 피하려면 어떻게해야합니까? 이상적으로는 루프 장치를 원자 적으로 발견하고 바인딩 할 수 있기를 원합니다 (예 :
ld=$(sudo losetup -f myfile.img)
dostuffwith $ld
그러나 그렇게 하면 권한 오류가 발생하는 것처럼 $ld
루프 장치 경로에 할당되지 않고 sudo
밖으로 이동하지 않습니다 sudo ld=$(losetup -f myfile.img)
.
답변
이는 동시성의 일반적인 문제입니다. 자원을 할당 할 때 자원이 비어 있는지 원자 적으로 결정하여 예약해야합니다. 그렇지 않으면 다른 프로세스가 자원이 비어 있는지 확인한 시간과 예약 한 시간 사이에 자원을 예약 할 수 있습니다.
사용하십니까 losetup
의 자동 할당 모드 ( -f
) 및 통과 --show
는 루프 장치 경로를 인쇄 할 옵션을 선택합니다.
ld=$(sudo losetup --show -f /tmp/1m)
이 옵션은 버전 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
답변
당신은 사용할 수 있습니다 flock
:
tryagain=1
while [[ $tryagain -ne 0 ]]; do
ld=`losetup -f`
flock -n $ld -c "losetup $ld myfile.img"
tryagain=$?
done
여기서 아이디어 flock
는 루프 장치 파일 을 시도한다는 것입니다 . 동일한 스크립트의 다른 인스턴스가 먼저이를 가져 오면 호출 losetup $ld myfile.img
하여 flock
0을 반환합니다. 레이스를 잃은 스크립트의 losetup
경우 호출되지 않고 flock
1을 반환하여 루프가 반복됩니다.
자세한 내용은를 참조하십시오 man flock
.
답변
루프백 장치로서 이미지와 관련된 모든 작업이 파일 시스템으로 마운트되어 내용에 대해 작업하는 경우 mount
명령이이를 자동으로 처리 할 수 있습니다.
mount -o loop myfile.img /tmp/mountpoint