Linux API/linux

mmap() 과 munmap() 예제

구차니 2023. 11. 17. 16:54

munmap은 주소와 길이만 있으면 되는데

mmap은 fd가 있어야 한다.

#include <sys/mman.h>
void *mmap(void *addr, size_t lengthint " prot ", int " flags , int fd, off_t offset);
int munmap(void *addr, size_t length);

[링크 : https://linux.die.net/man/2/mmap]

 

그래서 직접 구현하려니 먼가 복잡하고 귀찮아서 찾아보니 실행되는 녀석 발견.

테스트 소스를 긁어와서 빌드하고 실행하면 되는데, 아래와 같이 두개의 인자를 주어야 한다.

일종의 cp 명령을 코드로 짠 느낌.

$ ./a.out in_filename out_filename 

#include <stdio.h>
#include <sys/mman.h>
#include <stdlib.h>
#include <fcntl.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>

int main(int argc, char *argv[]){
        int srcfd, dstfd; //src 파일 서술자, dst 파일 서술자
        void *src, *dst;  //src 메모리 주소, dst 메모리 주소
        size_t copysz; //다음 copy할  메모리 내용 size
        struct stat sbuf;
        off_t fsz = 0; //다음 읽기, 쓰기를 기록할 위치(offset)
        long page_size; //시스템의 PAGE SIZE

        if((srcfd = open(argv[1], O_RDONLY)) < 0) {
                fprintf(stderr, "can't open %s for reading \n",argv[1]);
                exit(1);
        }

        if((dstfd = open(argv[2], O_RDWR | O_CREAT | O_TRUNC, 0777)) < 0){
                fprintf(stderr, "can't open %s for writing\n", argv[2]);
                exit(1);
        }


        //file 사이즈 얻기 위한 용도
        if(fstat(srcfd, &sbuf) < 0){
                fprintf(stderr, "fstat error\n");
                exit(1);
        }

        if(ftruncate(dstfd, sbuf.st_size) < 0){
                fprintf(stderr, "ftruncate error\n");
                exit(1);
        }

        page_size = sysconf(_SC_PAGESIZE);
        printf("page_size : %ld\n", page_size);

        while(fsz < sbuf.st_size){

                if((sbuf.st_size - fsz ) > page_size)
                        copysz = page_size;
                else
                        copysz = sbuf.st_size - fsz;

                //src 주소 설정
                if((src = mmap(0, copysz, PROT_READ, MAP_SHARED, srcfd, fsz))
                                == MAP_FAILED){
                        fprintf(stderr, "mmap error for input \n");
                        printf("error : %s\n",strerror(errno));
                        exit(1);
                }

                //dst 주소 설정 , 여기서 MAP_SHARED를 MAP_RPIVATE로 바꾸면? dst파일에 저장되지 않는다.
                if((dst = mmap(0, copysz, PROT_READ|PROT_WRITE, MAP_SHARED, dstfd, fsz)) == MAP_FAILED){
                        fprintf(stderr, "mmap error for output\n");
                        exit(1);
                }

                //src -> dst로 내용 복사
                memcpy(dst, src, copysz);

                //메모리 해제
                munmap(src, copysz);
                munmap(dst, copysz);
                //복사한 내용만큼 다음 메모리 위치를 이동시킬 offset 증가
                fsz += copysz;

        }

        exit(0);
}

[링크 : https://reakwon.tistory.com/225]

 

특이한건 munmap() 에서 copysz를 /2로 해서 넣어도 return 값이 0 으로 나온다.

                int ret = munmap(src, copysz / 2);
printf("ret[%d]\n",ret);
                ret = munmap(dst, copysz / 2);
printf("ret[%d]\n",ret);

그러면.. 예상한것과 좀 다른데..

나중에 프로그램을 천천히 실행하도록 해서 메모리 누수가 발생하는지 찾아봐야 할 듯..