|
|
write 한다고 디스크에 바로 반영되지 않는다.
fsync() 또는 O_DSYNC 를 사용해야 하지만
윈도우는 사용 못한다.
(다른 방법이 있겠지만 나는 못 찾았다.)
결국... http://gamejigi.tistory.com/10 로 해결!!
FILE *fp = fopen( "test", "wbc" );
fwrite( "DATA", 4, 1, fp );
fflush( fp );
fclose( fp );
윗글로 해결이 안되면..
http://kyrias.tistory.com/23 글 참고..
참고 글 ...
http://kyrias.tistory.com/23 글 참고..
HANDLE hFile = CreateFile( "test", 0, FILE_SHARE_WRITE, 0, TRUNCATE_EXISTING, FILE_FLAG_WRITE_THROUGH );
DWORD sz = 0;
WriteFile( hFile, "data", 4, &sz, NULL );
FlushFileBuffers( hFile );
CloseHandle( hFile );
참고 글 ...
1. Synchronus IO vs Direct IO
IO 수행시 즉시 디스크에 반영 하느냐 아니냐 차이
fopen 는 응용프로그램 단계에서 IO 버퍼링
open 는 시스템 버퍼
open 옵션의 O_DSYNC 는 Synchrouns IO (fsnyc() 도 가능)
단순히 open 시 몇 초 후에 발생.
비정상적으로 전원이 나갈 시 문제 발생.
http://altistory.net/333
2. fopen vs open
fopen 은 system call 함수, C 표준 라이브러리 버퍼를 이용
=> fopen - open 버퍼 : 이중 버퍼 사용
open 은 system 에서 버퍼를 이용
빈번한 파일을 열고 닫을 경우, open 이 속도가 더 빠름 약 1.5배
O_DSYNC O_DIRECT ?
int fp = open(m, O_WRONLY | O_SYNC | O_CREAT | O_DIRECT);
fsync(fp);
fsyncdata(fp);
http://shchoi82.springnote.com/pages/8032464.xhtml
http://hidori.com/tag/fopen
http://mydroid.egloos.com/3585218
http://kldp.org/node/1350
http://jchern.tistory.com/20
http://www.joinc.co.kr/modules/moniwiki/wiki.php/open%20%26%20fopen
3. 하드디스크 저장 루틴
버퍼에 한계치를 걸어놓고 (매번 하면 느려지기 떄문) 그 한계치가 되거나
4. fflush
기존의 소스는 fflsuh 를 사용한다.
참고로 fflsuh 는 사용자 버퍼에서 커널 버퍼에 복사하는 역할
즉 fflsuh 는 stdlib.h 의 user space buffer 내용을 kernel로 내려버리는 역할.
이는 커널이 유휴 상황일 때, 디스크에 write 한다.
이를 보완하기 위해서는
fsync 를 사용해야 한다.
fsync 는 write 와 같은 쓰기 API에 갱신된 버퍼의 데이터를 실제 물리 디스크와
동기화 하는 API
이게 무슨 소리냐 하면
파일을 읽고 쓸때, 실제 물리적인 디스크에서 바로 읽고 쓰는게 아니라.
커널(OS)에 의해 통제를 받는다..
커널에 존재하는 버퍼에 일차적으로 저장되고, 버퍼가 가득차거나 일정시간이 되면
그 데이터를 실제 물리 디스크에 작성한다.
fdatsync 는 데이터만 싱크하기 때문에. 동기화 시간이 절약, 성능도 우수하다
하지만 계속 쓸 경우는 fsync 사용
5. write
5. write
write() 시스템 콜은 커널의 버퍼로 즉시 기록합니다.
커널의 버퍼로 기록한다고 해도 디스크에 즉시 기록하지는 않습니다.
기타.
기타.
1. fprintf, fwrite ,fputs 등의 함수는 사용자 라이브러리 함수로서 내부적으로 write 를 호출하도록 되어있습니다.
하지만 한번의 fprintf 가 반드시 write를 호출하는 것은 아닙니다.
2. fprintf 로 파일에 쓰는 경우 8192 바이트크기의 버퍼를 기본적으로 가지고 있으며 8192가 가득찬 이후에야 write를 호출합니다.
만약 fprintf로 터미널에 쓰는 경우는 개행문자를 만날때까지 버퍼에 채워두었다가 write를 합니다.
즉, 터미널이냐, 파일이냐 등의 기록 매체에 따라 버퍼의 크기와 동작에
약간의 차이가 있는 것입니다. setvbuf 함수의 맨페이지를 참고하세용
3. 커널의 버퍼에만 기록이 되고, 아직 디스크에 기록이 안된 상태에서
전원이 나가면 문제가 될것입니다.
4. 시스템의 커널데몬을 살펴보면..
updated 라는 것이 있는데
이것은 30분 간격으로 시스템의 커널버퍼를 디스크로 옮겨주는 기능을 합니다.
30분 간격으로 sync 를 호출해주는 것입니다.
fflush 는 사용자 영역의 버퍼를 커널의 버퍼로 이동시키는 역할을 하는 것입니다.
sync() : 시스템(kernel) 차원
커널내부(kernel level)의 버퍼캐시(buffer cache)의
내용 중 저장이 필요한 블럭을 실제로 디스크에
write한다.
fflush() : 응용프로그램 차원
사용자 영역(user level)의 버퍼(라이브러리
수준에서 제공되는)의 내용을 커널로 보낸다.
* 참고
유닉스는 비동기 파일시스템을 가지고 있습니다.
만일 사용자가 A라는 파일을 수정 및 저장해도
실제로 하드디스크에 저장하는 것이 아니라,
커널내부의 버퍼캐시에다 저장하고 리턴합니다.
이후 일정시간이 지나면 버퍼캐시 운영알고리즘에
의해서 또는, 사용자가 강제로 sync를 호출해서
동기화(실제 디스크 저장)를 이루게 됩니다.
IE9 이상으로 브라우저를 업그레이드하거나, 크롬, 파이어폭스 등 최신 브라우저를 이용해주세요.