mmap관련 급질문. MAP_SHARED 와 MAP_PRIVATE
글쓴이: meconfidence / 작성시간: 화, 2004/04/13 - 4:51오후
제가 mmap이라는 함수를 쓰게 됬는데요,
int read_file,write_file,count; void * read_buf; void * write_buf; const int field_width = 136; read_file = open("1min_file.txt",O_RDONLY); write_file = open("1min_file.txt",O_RDWR); // count = lseek(read_file,0,SEEK_END); read_buf = mmap(0,count,PROT_READ,MAP_SHARED,read_file,0); write_buf = mmap(0,count,PROT_WRITE,MAP_SHARED,write_file,0); // 문제가 되는 부분.. memcpy(write_buf,read_buf+field_width,count-field_width); memcpy(write_buf+count-field_width,"20040408,100800,100.000,100.000,100.000,100.000,100.000,100.000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000\n",field_width); munmap(read_buf,count); munmap(write_buf,count); close(read_file);close(write_file);
이 코드 이전에, 다른 곳에서 이미 open("1min_file.txt",O_RDWR|O_CREAT|O_TRUNC|0777);로 열려 있는 상태입니다.
그랬더니 위의 코드에서
write_buf = mmap(0,count,PROT_WRITE,MAP_SHARED,write_file,0);
가 에러 EINVAL을 반환하더라구여..
EINVAL을 찾아보니, start나 length나 offset가 적당하지 않다 (즉, 너무 크거나 PAGESIZE 경계로 정렬되어 있지 않다.) 이렇게 나와있네요...
MAP_SHARED를 MAP_PRIVATE으로 고쳤더니 코드는 이상없이 돌아가는데,write_buf의 변경 내용이 해당 파일에 반영되지가 않습니다.
다른 곳에서 open해서 이렇게 된건지는 모르겠지만, 위의 코드만을 돌리면 잘 돌아갑니다.. 어디가 문제인지, 또 어떻게 해결해야될지 모르겠네요..
고수님들 한수 배우겠습니다.. :D
Forums:
Re: mmap관련 급질문. MAP_SHARED 와 MAP_PRIVATE
이렇게 하시면 1min_file.txt 이 정상적으로 open되지 않을 것 같습니다.
O_TRUNCATE 를 주시면, 이미 파일이 있는 경우 그 파일의 내용을 모두 없앱니다. (아마 이것을 의도하셨을 수도 있으셨겠네요.)
그 후, 0777 은 아마 파일생성시에 파일 모드를 지정해 주신 것으로 생각되는데,
파일모드는 open()의 두번째 파라메터인 flag와 OR 시키는 것이 아니라
세번째 파라메터로 주게 되어 있습니다.
컴파일러 에러를 안 낸 것은 파일모드가 optional 파라메터이기 때문입니다.
파일 생성모드에 garbage 값이 들어가서 생성한 파일의 모드가 이상하게 되어 있을 것입니다.
구현에 따라 | 0777 때문에 O_EXCL 과 O_CREAT 가 동시에 flag로 지정되는 경우에는 open() 이 실패할 수도 있을 것이고요.
일단 다른 쪽에서 open 하는 부분을 아래와 같이 수정해서 해 보시기 바랍니다.
open("1min_file.txt", O_RDWR|O_CREAT|O_TRUNC, 0777);
O_TRUNC 는 해당하는 로직에 맞도록 생략하시거나 유지하시거나 하시고요.
일단 count 값을 찍어보세요.
Solaris 메뉴얼 상에는 mmap()의 두번째 파라메터 len 이 0보다 작거나 같은 경우에는
EINVAL 이 발생한다고 되어 있습니다.
mmap()에서 에러가 발생하지않고 넘어간다고 하더라도
파일이 존재하지않거나 사이즈가 0인상태, 또는 사이즈가 field_width 보다 작은 상태에서는 memcpy 에서 오류가 발생합니다.
그리고 파일크기가 field_width 보다 작은 경우에는 mmap된 영역의 field_width 까지 메모리 연산을 성공적으로 했다고 해도
그 내용이 실제 파일에 반영되지 않습니다.
파일 크기를 확인하셔서 크기가 적어도 field_width만큼 되는지 확인하시고,
그렇지 않은 경우에는 파일크기를 적어도 그 만큼으로 늘려주신 다음에
mmap()을 수행하셔야 됩니다.
(이 경우는 로직상 mmap을 안 쓰고 그냥 field 를 파일에 쓰는 것이 빠를 것 같긴 합니다만...)
open()과 mmap()을 두번 사용하셨는데, 한번만 사용하셔도 될듯합니다.
open()시에 읽기/쓰기 가능하게 주시고, PROT_READ | PROT_WRITE 되게 하면 될듯 싶습니다.
MAP_PRIVATE 시에 mmap()이 성공한 것은 일단 count가 0이라는 가정하에 의외의 결과입니다.
open()을 포함해서 mmap()의 리턴값과 에러 코드를 확인하는 부분을 올려줘봐 주실 수 있는지요?
Re: mmap관련 급질문. MAP_SHARED 와 MAP_PRIVATE
우선 답변 올려주신데 대해서 정말 감사드립니다.. :D :) :o
open하는 부분을 잘 못 올렸네요..
| 0777 가 아니라 , 말씀하신것과 같이 열었습니다.
open("1min_file.txt", O_RDWR|O_CREAT|O_TRUNC, 0777);
count값을 찍어보니 208이 나옵니다..
field_width는 104로 count값 208(파일사이즈)보다 작습니다.
현재 문제가 되는 부분이 memcpy 하기 이전인 mmap입니다.
말씀하신대로 하면 편리하긴 한데, 제가 쓸 파일이 MB단위라서 mmap을 쓰려구 합니당..
말씀하신대로 mmap, open을 동시에 하고, 에러코드 확인하는 부분 올렸습니다
실제 프로그램 도중에 다음과 같이 에러 메시지가 뜹니다.
mmap with error 22(Invalid argument)
하지만, 여기서도 MAP_SHARED를 MAP_PRIVATE으로 하면
mmap success!
메시지가 뜹니다.
하지만 역시나, MAP_PRIVATE의 경우에는 파일에 변경되지 않습니다..
답글 달아주세요~ :wink:
항상 감사하는 마음으로...
댓글 달기