루프 장치를 원자 적으로 할당하는 방법은 무엇입니까?


11

디스크 이미지를 처리하기 위해 일부 쉘 스크립트를 작성 중이며 루프 장치를 사용하여 일부 디스크 이미지에 액세스해야합니다. 그러나 프로그램을 경쟁 조건에 노출시키지 않고 루프 장치를 올바르게 할당하는 방법을 잘 모르겠습니다.

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).

답변:


13

이는 동시성의 일반적인 문제입니다. 자원을 할당 할 때 자원이 비어 있는지 원자 적으로 결정하여 예약해야합니다. 그렇지 않으면 다른 프로세스가 자원이 비어 있는지 확인한 시간과 예약 한 시간 사이에 자원을 예약 할 수 있습니다.

사용하십니까 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프로그램은 루프 장치 항목을 열거하여 하나를 예약합니다. 코드에서 경쟁 조건을 볼 수는 없습니다. 안전해야하지만 작은 경우에는 모든 장치가 할당되지 않았다고 잘못보고하는 작은 창이있을 수 있습니다.


무엇입니까 </dev/tty?
Stéphane Chazelas

1
내가 마지막으로 시도했을 때조차도 losetup --find --show경주. for i in {1..100}; do losetup -f -s $i & done100 루프 장치를주지 않았습니다. 루프 장치는 일반적으로 중요하지 않을 정도로 흔하지 않습니다. 그것이 유일한 옵션이라면, 자신의 잠금 장치를 만들고 /하거나 올바른 루프 장치가 나중에 만들어 졌는지 확인하는 것입니다.
frostschutz

@frostschutz losetup가 실패 할 수 있지만 (예 : 루프 항목이 부족하여) 장치 이름을보고하면 장치가 성공적으로 할당 된 장치입니다. 이전 버전에는 할당에 실패했지만 장치 이름을 쓰게하는 버그가 있습니까? 소스 코드에서 커널 내부 할당을위한 인터페이스는 커널 3.1 이후로만 존재한다는 것을 알 수 있습니다. losetup유틸리티를 검색 해야하는 이전 인터페이스의 버그 일까요?
Gilles 'SO- 악마 그만'

오, 실제로 최신 버전에서 수정 된 것으로 보입니다. util-linux-2.26.2가 작동하는 것으로 보이며 util-linux-2.24.1이 반복적으로 인쇄 /dev/loop14되므로 장치가 완전히 누락 될 수 있습니다. 아마 수정의 의례 /dev/loop-control가에서 단지보기에 사용 /proc/partitions...
frostschutz

@frostschutz util-linux 2.21부터는 존재 losetup하는 /dev/loop-control경우 사용 하고 경쟁 조건이있는 것처럼 보이지 않습니다. 할당은 커널에서 발생하며 장치 경로를 인쇄하는 것이 유틸리티가 수행하는 마지막 작업입니다.
Gilles 'SO- 악마 그만해'

6

나는 그것을 알아. 권한 문제의 문제가 확실하지 않지만 대신 먼저 촬영하여 다음과 같이 요청할 수 있습니다.

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

2

당신은 사용할 수 있습니다 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하여 flock0을 반환합니다. 레이스를 잃은 스크립트의 losetup경우 호출되지 않고 flock1을 반환하여 루프가 반복됩니다.

자세한 내용은를 참조하십시오 man flock.


0

루프백 장치로서 이미지와 관련된 모든 작업이 파일 시스템으로 마운트되어 내용에 대해 작업하는 경우 mount명령이이를 자동으로 처리 할 수 ​​있습니다.

mount -o loop myfile.img /tmp/mountpoint

사실, 필자의 경우 특히 마운트 하지 않기를 원합니다 . 파일 시스템이 아닌 블록 장치로 사용하고 있습니다.
AJMansfield

@AJMansfield 마운트하지 않고 파일로 할 수없는 블록 장치로 무엇을 할 수 있습니까?
Random832

전체 디스크 btrfs 설정에서 스왑 공간으로 포맷 할 수 없습니다. btrfs는 스왑 파일에 필요한 작업을 지원하지 않으므로 전체 디스크 btrfs 설정으로 실제 스왑 파티션을 가질 수 없으므로 스왑 공간에 파일을 사용하려고했습니다.
AJMansfield 21시 46 분
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.