리눅스데브코스 [10주차 - 4]<가상 메모리 관련 시스템콜 실습>

심우열·2023년 6월 8일
0

1: 주소공간 확인

malloc()을 통해 heap 영역의 크기를 키워보기(1MB이상)

1. C 코드

1. malloc 없을 경우

1. 코드

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main(int argc, char *argv[]){

    int *arr;
    
//    for(int i=0;i<1000;i++)
//       arr=malloc(1024);

    sleep(1000);
    free(arr);

    return 0;
}

2. cat /proc/[pid]/maps

아래와 같이 heap 영역이 없는 것을 알 수 있다

2. malloc 있을 경우

1. 코드

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main(int argc, char *argv[]){

    int *arr;
    
   for(int i=0;i<1000;i++)
      arr=malloc(1024);

    sleep(1000);
    free(arr);

    return 0;
}

2. cat /proc/[pid]/maps

  • 아래와 같이 heap 영역이 생성된 것을 확인할 수 있다.
  • heap 메모리 주소공간을 계산해보면 대략 1MB가 나오는 것을 확인할 수 있다.

3. ltrace

  • 전부 malloc(1024) 인 것을 확인 할 수 있다.

4. strarce

  • 첫 brk() 시스템 콜을 통해 heap 영역을 생성하고, 계속해서 brk() 시스템 콜을 호출하여 필요에 따라 heap 영역을 키워가는 것을 확인할 수 있다.

2: mmap()을 통한 파일 접근

1. "hello world!" 내용의 test.txt 생성

touch test.txt; echo "hello world!" > test.txt

2. test.txt 파일의 내용을 바꾸는 C코드 작성

  • mmap()으로 test.txt 를 mapping 하고 파일의 내용을 읽고 printf()로 출력
  • 파일의 내용을 "byebye world!!!!!" 로 바꾸고 close()

1. 코드

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

int main(int argc, char *argv[])
{
    const char* file_path = "test.txt";
    const char* new_content = "byebye world!!!!!\n";
    int file_descriptor;
    struct stat file_info;
    char* file_data;

    //open the file
    file_descriptor = open(file_path, O_RDWR);
    if(file_descriptor == -1){
        perror("Error opening file");
        return 1;
    }

    //Get file information
    if(fstat(file_descriptor, &file_info)== -1){
        perror("Error getting file information");
        close(file_descriptor);
        return 1;
    }

    // Map the file into memory = mmap()
    file_data = mmap(NULL, file_info.st_size, PROT_READ | PROT_WRITE, 
        MAP_SHARED, file_descriptor,0 );
    if(file_data == MAP_FAILED){
        perror("Error mapping file to memory");
        close(file_descriptor);
        return 1;
    }

    //Output file content
    printf("File contents:\n%s\n", file_data);

    //Change file content
    strcpy(file_data, new_content);

    //Clean up
    munmap(file_data, file_info.st_size);
    close(file_descriptor);
 
    return 0;
}

2. 변경 내용 확인

  • 변경할 내용의 뒷부분이 잘리는 것을 확인 할 수 있다.

3. fallocate() 함수를 이용해 파일 크기 키우기

posix_fallocate(file_descriptor, 0, 늘리고자 하는 크기)

1. 코드

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

int main(int argc, char *argv[])
{
    const char* file_path = "test.txt";
    const char* new_content = "byebye world!!!!!\n";
    int file_descriptor;
    struct stat file_info;
    char* file_data;

    //open the file
    file_descriptor = open(file_path, O_RDWR);
    if(file_descriptor == -1){
        perror("Error opening file");
        return 1;
    }

    //Get file information
    if(fstat(file_descriptor, &file_info)== -1){
        perror("Error getting file information");
        close(file_descriptor);
        return 1;
    }

    // Map the file into memory = mmap()
    file_data = mmap(NULL, file_info.st_size, PROT_READ | PROT_WRITE, 
        MAP_SHARED, file_descriptor,0 );
    if(file_data == MAP_FAILED){
        perror("Error mapping file to memory");
        close(file_descriptor);
        return 1;
    }

    //Output file content
    printf("File contents:\n%s\n", file_data);

    //Change file content
    strcpy(file_data, new_content);

    //fallocate()
    posix_fallocate(file_descriptor,0,1024);

    //Clean up
    munmap(file_data, file_info.st_size);
    close(file_descriptor);
 
    return 0;
}

2. 변경 내용 확인

  • 변경 내용이 전부 입력 된 것을 확인 할 수 있다.

3: mlock() madvise() 동작 확인

0. free memory 확보하기

sudo su
echo 3 > /proc/sys/vm/drop_caches
free

1. mmap()을 통해 대용량 메모리 할당(약 4GB)

  • MAP_PRIVATE, MAP_ANNONYMOUS 플래그 사용

1. 코드

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

#define B 1024
#define MB (B * B)
#define GB (MB * B)

int main(int argc, char *argv[])
{
    int* ptr, i;

    ptr = mmap(NULL, 4L * GB, PROT_READ | PROT_WRITE, MAP_PRIVATE | 
        MAP_ANONYMOUS, -1, 0);
    if(ptr == MAP_FAILED){
        perror("Error mapping memory");
        return 1;
    } 
    printf("4GB Allocated\n");

    sleep(60);
    return 0;
}

2. free memory 확인

  • free memory의 양에 변화 가 없다

2. mlock() 을 통해 메모리 pinning 수행(약 1GB)

  • free 명령을 통해 free 메모리의 감소 확인

1. 코드

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

#define B 1024
#define MB (B * B)
#define GB (MB * B)

int main(int argc, char *argv[])
{
    int* ptr, i;

    ptr = mmap(NULL, 4L * GB, PROT_READ | PROT_WRITE, MAP_PRIVATE | 
        MAP_ANONYMOUS, -1, 0);
    if(ptr == MAP_FAILED){
        perror("Error mapping memory");
        return 1;
    } 

    printf("4GB Allocated!\n");

    if(mlock(ptr, 1L * GB)<0){
        perror("Error mlock memory");
        return 1;
    }
    printf("1GB pinned!\n");

    sleep(60);

    if(munlock(ptr, 1L * GB)<0){
        perror("Error unlock memory");
        return 1;
    }

    munmap(ptr, 4L * GB);

    return 0;
}

2. free memory 확인

3. madvise()를 통해 mlock()한 공간의 반(약 500MB) 반납

  • MAD_DONTNEED 사용
  • free 명령어를 통해 free 메모리의 증가 확인

1. 코드

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

#define B 1024
#define MB (B * B)
#define GB (MB * B)

int main(int argc, char *argv[])
{
    int* ptr, i;

    ptr = mmap(NULL, 4L * GB, PROT_READ | PROT_WRITE, MAP_PRIVATE | 
        MAP_ANONYMOUS, -1, 0);
    if(ptr == MAP_FAILED){
        perror("Error mapping memory");
        return 1;
    } 

    printf("4GB Allocated!\n");

    if(mlock(ptr, 1L * GB)<0){
        perror("Error mlock memory");
        return 1;
    }
    printf("1GB pinned!\n");

    if(madvise(ptr, 512L * MB, MAD_DONTNEED) < 0) {
        perror("failed to advise memory");
        return 1;
    }

    printf("512MB dont't need\n");

      sleep(60);

    if(munlock(ptr, 512L * MB) < 0) {
        perror("failed to unlock memory");
        return 1;
    }


    munmap(ptr, 4L * GB);

    return 0;
}

2. free memory 확인

-MAD_DONTNEED 가 안됨..

profile
Dev Ops, "Git, Linux, Docker, Kubernetes, ansible, " .

0개의 댓글