기존 파일을 완전히 작성하여 한 번만 새 버전으로 대체되도록 기존 파일을 다시 작성하십시오.


18

필자는 일부 Unices에서 기존 파일을 여는 방법과 커널이 이전 버전 (읽기 위해 액세스하는 다른 프로세스의 경우)을 사용하도록 요청하는 플래그와 함께 "새 파일을 읽을 때까지" "버전이 완전히 작성되었습니다 (fd 닫힘).이 시점에서 파일이 새 버전으로 나타납니다.

다시 말해서, 다른 프로세스는 이전 버전이나 새 버전을 보았으며, 불완전하게 작성된 버전은 결코 없었습니다.

지식이있는 사람이 나를 참조 할 수 있습니까?


계획 9 가 할 수있는 것처럼 들리지만 그렇지 않습니다.
Gilles 'SO- 악의를 멈춰라

2
OpenVMS의 파일 -11 과 같은 소리 : "기존 버전을 덮어 쓰지 않고 파일을 저장할 때마다 이름은 같지만 버전 번호가 증가한 새 파일이 생성됩니다."
Mat

넌 왜 물어 봤니? 그 기능이 필요합니까, 아니면 그냥 호기심 이었습니까?
Nils

1
나는 그 기능을 갖게되어 기쁘고, 그것이 존재하는 곳을 읽는 것을 상기했다. 따라서 필요와 호기심이 혼합되어 있습니다.
eudoxos 2018 년

모든 유닉스 시스템은이를 다른 방식으로 허용합니다. 같은 디렉토리에 새 파일을 만들고 변경된 내용으로 채우고 원자 이름을 바꿉니다. 이것은 작은 변경이지만 작동하는 데 훨씬 비쌉니다.
Netch

답변:


14

당신이 묘사하는 것은 파일을 덮어 쓰는 기본 이름 바꾸기와 정확히 같습니다.

한 파일을 다른 파일의 이름으로 바꾸거나 이동하면 이전 파일이 연결 해제됩니다. 파일이 여전히 존재하지만 더 이상 파일 시스템 트리에 없다는 것을 의미합니다. 따라서 오래된 응용 프로그램은 파일을 열어 두는 한 계속 파일에 액세스 할 수 있습니다. 모든 응용 프로그램이 이전 파일을 닫으면 디스크에서 실제로 할당 해제됩니다.

rename시스템 호출은 원자 동작이다. 이렇게하려면 다른 이름으로 새 파일을 만든 다음 호출 rename하여 임시 파일의 이름을 바꾸려는 파일로 바꾸십시오. 작업이 원 자성이므로 파일이 누락 된 기간은 전혀 없습니다. 오래된 파일에서 새 파일로 즉시 이동합니다.
임시 파일과 교체되는 파일은 동일한 마운트 지점에 있어야합니다.


프로그램이 기능을 염두에두고 특별히 작성된 경우에만 사용할 수 있습니다. 그러나이 경우에는 일반 프로그램조차도이 원자 적 의미론을 자동으로 부여받는 것이 OS 기능이었습니다.
eudoxos

1
@eudoxos 귀하의 의견은 의미가 없습니다. rename스왑 작업 을 수행하려면 프로그램을 특별히 작성해야한다고 말하고 있습니다 . 당신이 말하는 것과 같은 'OS 기능'이 존재하더라도, 그것을 활용하기 위해 프로그램을 작성해야 할 것입니다. 차이점이 뭐야?
Patrick

opensyscall에 (지원되지 않는) 플래그를 전달 하거나 직접 설명하는 것을 수행해야하는 경우 차이가 있습니다.
eudoxos

충돌이 발생하는 경우 이전 버전 또는 완전히 작성된 새 버전을 유지하려면 fsync 또는 이와 유사한 기능을 사용하여 디스크에 새 파일을 추가로 동기화해야합니다.
textshell

@textshell 동기화하지 않으면 여전히 원 자성을 얻습니다 .... 내구성이 아닙니다 ... 맞습니까? 이 경우 goo.gl/qfQQfy 의 인수를 이해하지 못합니다 . 내 경우에는 시스템이 극단적으로로드되고 파일 시스템 플러시를 피하고 파일이 충돌에서 살아남는 것을 신경 쓰지 않습니다.
wcochran

6

같이 Patrick이 쓰는 일반적인 방법은 새 버전을 별도의 파일에 쓰고 새 버전의 이름을 이전 파일 이름으로 바꾸면 원자 적으로 덮어 씁니다. 이 두 번째 작업을 덮어 쓰기 별명 이라고 합니다.

이제, 일부 참고 문헌 :


man 3p rename그것이 rename실제로 원자 적이라고 말하면 , 그것은 모든 Linux 파일 시스템을위한 것이라고 생각합니다. 그리고 내가 연결 한 첫 번째 기사를 읽을 때 Btrfs 이름 바꾸기 작업은 원자 적이라고 생각합니다.
hagello

1

이것은 나에게 Allocate On Flush를 상기시킨다 . 파일 시스템이 데이터를 디스크에 직접 쓰는 대신이 기능을 사용하면 디스크의 여유 공간 카운터에서 쓸 데이터의 크기를 빼고 동기화 시스템 호출이 수행되거나 커널이 결정할 때까지 데이터를 메모리에 보유합니다 더티 버퍼를 플러시합니다.

이 경우 파일이 한 프로세스에서 수정되고 다른 프로세스에서 열리면 후자의 프로세스는 파일의 수정되지 않은 ( 또는 원하는 경우 "오래된" ) 버전을 "인식" 합니다.

물론 위의 내용은 이론적이며 다양한 요인에 달려 있으며, 커널이 언제 더티 페이지를 플러시하는지 정확히 알지 못하기 때문에 예측할 수없는 부분이 있습니다. 예를 들어 Linux의 경우 ( Linux 커널 이해의 15.3 섹션에서도 읽을 수 있음 ) 다음과 같은 조건에서 더티 페이지가 디스크에 기록됩니다.

  • 페이지 캐시가 가득 차서 더 많은 페이지가 필요하거나 더티 페이지 수가 너무 많아집니다.

  • 페이지가 더러워진 후 너무 많은 시간이 경과했습니다.

  • 프로세스는 블록 장치 또는 특정 파일의 보류중인 모든 변경 사항을 플러시하도록 요청합니다. sync (), fsync () 또는 fdatasync () 시스템 호출을 호출하여이를 수행합니다.

이 기능은 HFS +, XFS, Reiser4, ZFS, Btrfs 및 ext4 파일 시스템에서 구현되는 것으로 알려져 있습니다.


2
당신이 설명하는 것은 (참조 POSIX (파일) 시스템에서 (당신이 나타내는 것을하지 않고, 따라서 등) 사용자 공간에서 눈에 보이지 않는 수 있어야 파일 시스템 기술이다 쓰기 "파일 데이터의 읽기 ()을 입증 할 수있는 경우 (어떤 방법으로) : 데이터의 write () 이후에 발생하려면 다른 프로세스에서 호출 한 경우에도 해당 write ()를 반영해야합니다 . ") 다른 프로세스는 POSIX에서 이전 데이터를 볼 수 없습니다 .
Mat

수정 해 주셔서 감사합니다. 이 파일 시스템 기술에 대한 나의 이해가 잘못되었다고 생각합니다.
dkaragasidis

맞습니다. 이것은 다른 것 같습니다. RMS와의 인터뷰에서 그가이 기능을 언급 한 것은 아마도 모호한 일입니다. 어쩌면 학계 밖에서는 살지 않은 오래된 비전 시스템 일 것입니다. 어쨌든 고마워요.
eudoxos
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.