문제

일반적으로 여러 프로세스에서 UNIX의 파일에 추가 할 때 당연한 점은 무엇입니까? 데이터를 잃을 수 있습니까 (한 프로세스는 상대방의 변경을 덮어 씁니다)? 데이터가 엉망이 될 수 있습니까? (예를 들어, 각 프로세스는 로그 파일에 대한 부록 당 한 줄을 추가하고 있습니다. 두 줄이 엉망이 될 수 있습니까?) 부록이 위의 의미에서 원자가 아닌 경우 상호 배제를 보장하는 가장 좋은 방법은 무엇입니까?

도움이 되었습니까?

해결책

'pipe_buf'의 크기 아래에있는 쓰기는 원자가되어야합니다. 그것은 512 바이트가되어야하지만 쉽게 더 클 수 있습니다 (Linux는 4096으로 설정 한 것 같습니다).

이것은 당신이 모든 POSIX 호환 구성 요소를 말하고 있다고 가정합니다. 예를 들어 NFS에서는 사실이 아닙니다.

그러나 'o_append'모드로 열린 로그 파일에 쓰고 'pipe_buf'바이트 아래에 라인을 유지하고있는 로그 파일을 유지한다고 가정하면, 손상 문제없이 여러 작가를 로그 파일로 가질 수 있어야합니다. 중간이 아닌 쓰기 전후에 인터럽트가 도착합니다. 파일 무결성이 재부팅에서 살아 남기 위해 전화해야합니다. fsync(2) 모든 글을 쓰면 성능이 끔찍합니다.

설명: 주석을 읽고 오즈 솔로몬의 대답. 확실하지 않습니다 O_APPEND 그것을 가지고 있어야합니다 PIPE_BUF 크기 원자력. Linux가 구현 한 방식 일 가능성이 전적으로 가능합니다. write(), 또는 기본 파일 시스템의 블록 크기 때문일 수 있습니다.

다른 팁

편집하다: 2017 년 8 월 최신 Windows 결과로 업데이트되었습니다.

제안 된 저자로서 테스트 코드에 대한 링크와 결과에 대한 답변을 드리겠습니다. boost.afio 비동기 파일 시스템과 파일 I/O C ++ 라이브러리를 구현합니다.

첫째, Windows의 O_append 또는 동등한 File_Append_data는 최대 파일 범위 (파일 "길이")의 증분이 원자 동시 작가 아래. 이는 POSIX 및 Linux, FreeBSD, OS X 및 Windows에 의해 보장됩니다. Samba는 또한이를 올바르게 구현합니다. V5 이전의 NFS는 원자 적으로 추가 할 수있는 와이어 형식 기능이 없기 때문에 NFS가 아닙니다. 따라서 부록 전용으로 파일을 열면 동시 쓰기는 주요 OS에서 서로에 대해 찢어지지 않을 것입니다. NFS가 관여하지 않는 한.

그러나 동시 읽습니다 원자가에 5월 OS, 파일 시스템 및 파일을 열었던 플래그에 따라 찢어진 쓰기를 참조하십시오. 최대 파일 범위의 증가는 원자가되지만 읽기와 관련하여 쓰기의 가시성은 원자가 될 수 있습니다. 다음은 플래그, OS 및 파일링 시스템의 빠른 요약입니다.


없음 o_direct/file_flag_no_buffering :

NTFS가 포함 된 Microsoft Windows 10 : Atomicity = 1 바이트는 10.0.14393에서 10.0.10240까지 1MB를 포함하여 최소 1MB, 아마도 무한 (*).

ext4와 함께 Linux 4.2.6 : Atomicity 업데이트 = 1 바이트

ZFS가있는 freebsd 10.2 : Atomicity를 업데이트 = 최소 1MB, 아마도 무한 (*)

o_direct/file_flag_no_buffering :

NTFS가 포함 된 Microsoft Windows 10 : Atomicity를 업데이트 = 최대 10.0.10240까지 최대 4096 바이트를 포함하여 페이지가 정렬 된 경우에만 512 바이트를 포함합니다. file_flag_write_through 꺼 이 원자력은 아마도 10.0.14393 이후 적어도 1MB, 아마도 무한 (*) 이후 PCIE DMA의 특징 일 것입니다.

ext4가있는 Linux 4.2.6 : Atomicity = 최소 1MB, 아마도 무한 (*). Ext4를 가진 초기 리눅스는 확실히 4096 바이트를 초과하지 않았으며 XFS는 확실히 사용자 지정 잠금을했지만 최근 Linux가 마침내이 문제를 해결 한 것처럼 보입니다.

ZFS가있는 freebsd 10.2 : Atomicity를 업데이트 = 최소 1MB, 아마도 무한 (*)


원시 경험적 테스트 결과를 볼 수 있습니다 https://github.com/ned14/afio/tree/master/programs/fs-probe. 참고 우리는 512 바이트 배수에서만 찢어진 오프셋을 테스트하므로 512 바이트 부문의 부분 업데이트가 읽기 모형 쓰레기주기 중에 찢어 질지 말할 수 없습니다.

따라서 OP의 질문에 답하기 위해 O_Append는 서로를 방해하지 않지만 O_Append에 동시에 읽는 것은 아마도 O_Direct가 켜져 있지 않으면 ext4를 사용하여 Linux에 찢어진 글을 볼 수 있습니다.


(*) "아마도 무한"은 POSIX 사양에서 이러한 조항에서 비롯됩니다.

다음 기능은 일반 파일 또는 기호 링크에서 작동 할 때 POSIX.1-2008에 명시된 효과에서 서로에 대한 원자력이어야합니다 ... [많은 기능] ... read () ... write (write) ) ... 두 스레드가 각각이 함수 중 하나를 호출하는 경우 각 호출은 다른 호출의 지정된 효과를 모두 보거나 그 중 어느 것도 볼 수 없습니다. 원천

그리고

다른 독서 및 쓰기와 관련하여 글을 직렬화 할 수 있습니다. 파일 데이터의 read ()가 데이터의 write () 후에 발생하는 것으로 입증 될 수있는 경우, 다른 프로세스에 의해 호출이 이루어 지더라도 해당 write ()를 반영해야합니다. 원천

그러나 반대로 :

이 POSIX.1-2008은 여러 프로세스의 파일에 동시 쓰기의 동작을 지정하지 않습니다. 응용 프로그램은 어떤 형태의 동시성 제어를 사용해야합니다. 원천

이 답변에서 이들의 의미에 대해 더 많이 읽을 수 있습니다.

최대 원자 부속 크기를 경험적으로 테스트하기 위해 스크립트를 작성했습니다. Bash로 작성된 스크립트는 모두 동일한 파일에 작업자 별 서명을 작성하는 여러 작업자 프로세스를 생성합니다. 그런 다음 파일을 읽고 겹치거나 손상된 서명을 찾고 있습니다. 이것에서 스크립트 소스를 볼 수 있습니다. 블로그 게시물.

실제 최대 원자 부속 크기는 OS뿐만 아니라 파일 시스템에 따라 다릅니다.

Linux+Ext3에서 크기는 4096이고 Windows+NTF에서 크기는 1024입니다. 더 많은 크기는 아래 주석을 참조하십시오.

표준의 말은 다음과 같습니다. http://www.opengroup.org/onlinepubs/009695399/functions/pwrite.html.

만약 O_APPEND 파일 상태 플래그의 플래그가 설정되고 파일 오프셋은 각 쓰기 전에 파일 끝으로 설정되어야하며 파일 오프셋 변경과 쓰기 작업 사이에 중간 파일 수정 작업이 발생하지 않아야합니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top