A.3. Fsync
Fsync
는 I/O 비용이 많이 드는 시스템 콜로 알려져 있습니다. 하지만 항상 그런것은 아닙니다. 예를 들어 Theodore Ts'o의 글 Don't fear the fsync! [5]과 그에 따르는 토론을 살펴보십시오.
Firefox는 sqlite 라이브러리를 사용자가 새로운 페이지로 이동하는 링크를 클릭할 때마다 호출하곤 합니다. Sqlite은
fsync
를 부르고, 파일 시스템 설정(주로 ext3에 데이터 정렬 모드)에 따라서는, 아무 일이 일어자니 않더라도 응답 시간이 매우 길었습니다. 만약 다른 프로세스가 동시에 큰 파일을 복사하고 있는 중이라면 이 작업에 아주 긴 시간(최대 30초까지)이 걸릴 수도 있습니다.
하지만,
fsync
를 전혀 사용하지 않는 다른 경우에도 ext4 파일 시스템으로 변경하자 문제가 발생했습니다. Ext3은 데이터-정렬 모드 (data-ordered mode)로 설정되어, 몇초마다 메모리를 플러시해서 디스크에 저장했습니다. 하지만 ext4에서는 랩톱 모드 (laptop_mode)로 설정되어 저장 간격이 더 길어졌고, 시스템이 중간에 예기치 않게 꺼지면 데이터가 손실될 수 있었습니다. 이제 ext4가 패치가 되었지만, 여전히 프로그램을 설계할 때 fsync
를 적절히 사용하도록 주의를 기울여야만 합니다.
다음의 간단한 설정 파일 읽고 쓰기 예는 파일의 백업을 만드는 방법과, 데이터가 사라질 수 있는 예를 보여줍니다:
/* open and read configuration file e.g. ~/.kde/myconfig */ fd = open("./kde/myconfig", O_WRONLY|O_TRUNC|O_CREAT); read(myconfig); ... write(fd, bufferOfNewData, sizeof(bufferOfNewData)); close(fd);
더 나은 접근 방식은 다음과 같습니다:
open("/.kde/myconfig", O_WRONLY|O_TRUNC|O_CREAT); read(myconfig); ... fd = open("/.kde/myconfig.suffix", O_WRONLY|O_TRUNC|O_CREAT); write(fd, bufferOfNewData, sizeof(bufferOfNewData)); fsync; /* paranoia - optional */ ... close(fd); rename("/.kde/myconfig", "/.kde/myconfig~"); /* paranoia - optional */ rename("/.kde/myconfig.suffix", "/.kde/myconfig");