리눅스 커널 메모리 관리

sungho·2024년 12월 1일
0

가상 메모리

목록 보기
3/11

메모리 관리는 프로세스가 효율적으로 메모리를 사용할 수 있도록 지원합니다. 리눅스 메모리 관리 서브시스템의 주요 구성 요소를 살펴보겠습니다.

1. Linux Memory Management Subsystems

리눅스의 메모리 관리 서브시스템은 서로 긴밀하게 연관되어 있습니다.

가상 주소 공간 관리

  • task_struct
    • 프로세스를 나타내며 메모리 관리에 관한 정보를 포함
  • mm (Memory Management)
    • task_struct의 일부로, 메모리 관련 작업을 처리
  • vmarea
    • 프로세스의 가상 메모리 섹션을 나타냄
      • text : 실행 가능한 코드가 포함
      • data : 초기화된 전역 및 정적 변수가 저장
      • heap : 동적 메모리 할당에 사용
      • stack : 함수 호출 스택을 관리

주소 변환

  • pgd (Page Global Directory), pmd (Page Middle Directory), pte (Page Table Entry)
    • 가상 주소를 물리적 주소로 변환하는 다단계 페이지 테이블의 구조

물리적 메모리 관리

  • 사용된 페이지
    • 페이지 캐시 또는 스왑 캐시에 존재
    • 익명(anon) 또는 없음(none)
    • 활성 리스트 또는 비활성 리스트, 슬랩 캐시의 일부

프리 페이지 관리

  • 프리 페이지
    • 버디 시스템을 통해 관리

수요 페이징 및 스와핑

  • 파일 맵(File-map) 및 스왑 맵(Swap-map)
    • 매핑 여부에 따라 파일이나 스왑 영역에 연결

프로세스 가상 주소 공간 관리

  • 프로세스에 대해 고유한 가상 주소 공간을 제공

가상주소 공간 영역

  • 코드 영역
    • 실행할 프로그램의 코드가 저장
  • 데이터 영역
    • 전역 변수와 정적 변수가 저장
  • 힙 영역
    • 동적 메모리 할당을 위한 공간
  • 스택 영역
    • 함수 호출 시 지역 변수가 저장되는 공간

가상 주소 공간 관리는 vm_area_struct와 같은 구조체를 통해 프로세스의 메모리 접근을 관리

주소 변환 계층

  • 가상 주소를 물리 주소로 변환하는 주소 변환 계층을 제공
  • 페이지 테이블을 사용하여 가상 주소와 물리 주소 간의 매핑을 관리
  • 페이지 테이블은 페이지 폴트가 발생할 경우 커널은 페이지 테이블을 업데이트하여 필요한 페이지를 메모리에 로드

요구 페이징 및 페이지 교체

요구페이징

  • 요구 페이징(demand paging) 기법을 사용하여 메모리 사용을 최적화
  • 프로세스가 실제로 필요로 할 때만 페이지를 메모리에 로드하는 방식
  • 페이지가 메모리에 존재하지 않을 경우 페이지 폴트가 발생하며 커널은 페이지 폴트 핸들러를 통해 해당 페이지를 디스크에서 메모리로 로드

페이지 교체 알고리즘

  • 메모리가 부족할 때 어떤 페이지를 디스크로 퇴거할지를 결정
  • LRU(Least Recently Used)와 같은 알고리즘을 사용하여 가장 오랫동안 사용되지 않은 페이지를 선택하여 교체

물리 메모리 조직 및 처리

  • 물리 메모리를 효율적으로 관리하기 위해 다양한 기법을 사용
  • 물리 메모리는 페이지 프레임으로 나뉘며 각 페이지 프레임은 페이지 테이블을 통해 가상 주소와 매핑
  • 메모리 할당 및 해제를 관리하며 메모리 조각화 문제를 최소화하기 위해 Buddy System과 같은 메모리 할당 기법을 사용

2. TLB(Translation Lookaside Buffer)

  • 주소 변환을 빠르게 수행하기 위한 캐시
  • 최근에 사용된 페이지 테이블 엔트리를 저장하여 페이지 테이블에 접근하는 시간감소
  • TLB의 크기는 보통 16~256개의 엔트리를 가지며 LRU(Least Recently Used) 알고리즘을 사용하여 교체 정책을 결정
  • TLB의 효율적인 사용은 메모리 접근 성능을 크게 향상

3. 대규모 페이지 지원(Huge Pages)

  • 대규모 페이지 기능을 지원하여 메모리 관리의 효율성 증가
  • 일반 페이지보다 큰 크기를 가지며 페이지 테이블의 크기를 줄이고 페이지 폴트 발생 빈도를 낮추어 성능을 향상
  • 데이터베이스와 같은 메모리 집약적인 애플리케이션에서 유용하게 사용

대규모 페이지 사용 방법

  • 기능
    • 시스템에서 사용할 대규모 페이지의 수를 설정
  • 방법
echo 1 > /proc/sys/vm/nr_hugepages

4. NUMA 아키텍처에서의 메모리 관리

  • NUMA 아키텍처는 여러 프로세서가 각각의 로컬 메모리에 접근할 수 있는 구조
  • 프로세스가 로컬 메모리에 접근할 때 성능을 최적화
  • 메모리 접근 지연을 줄이고 멀티코어 시스템에서의 성능을 향상시키는 데 기여

5. 시스템 호출 예시

  • mmap
    • 파일이나 장치를 메모리에 매핑하는 데 사용

    • 호출은 메모리 매핑을 통해 파일의 내용을 메모리에서 직접 접근

      #include <sys/mman.h>
      #include <fcntl.h>
      #include <unistd.h>
      
      int main() {
          int fd = open("example.txt", O_RDONLY);
          size_t length = 4096; // 매핑할 크기
          char *map = mmap(NULL, length, PROT_READ, MAP_PRIVATE, fd, 0);
          if (map == MAP_FAILED) {
              perror("mmap");
              return 1;
          }
          // 파일 내용 사용
          munmap(map, length);
          close(fd);
          return 0;
      }
      
  • brk 및 sbrk
    • 프로세스의 힙 영역을 확장하거나 축소하는 데 사용

    • brk는 힙의 끝 주소를 설정

    • sbrk는 힙의 크기를 증가시키거나 감소

      #include <unistd.h>
      
      int main() {
          void *old_brk = sbrk(0); // 현재 힙의 끝 주소를 가져옴
          sbrk(1024); // 힙을 1024바이트 증가
          return 0;
      }
      

6. 메모리 관리와 관련된 일반적인 문제점 및 디버깅 팁

문제점

  • 메모리 누수
    • 할당된 메모리를 해제하지 않으면 메모리 누수가 발생
    • 모든 동적 메모리 할당 후에는 반드시 해제를 수행 필요
  • 페이지 폴트
    • 페이지 폴트가 자주 발생하면 성능이 저하
    • 메모리 접근 패턴을 최적화하거나 대규모 페이지를 사용이 필요

디버깅 팁

  • valgrind
    • 메모리 누수를 검사하고, 메모리 오류를 찾는 데 유용한 도구
  • /proc/PID/maps
    • 특정 프로세스의 메모리 맵을 확인하여 메모리 사용 현황을 파악가능

7. 결론

리눅스 커널의 메모리 관리 서브시스템은 프로세스가 메모리를 효율적으로 관리하고 사용할 수 있도록 돕는 중요한 기능입니다. 프로세스 가상 주소 공간 관리, 주소 변환 계층, 요구 페이징 및 페이지 교체, 물리 메모리 조직 및 처리, TLB, 대규모 페이지 지원, NUMA 아키텍처에서의 메모리 관리 등 다양한 구성 요소가 상호작용하여 메모리 관리의 효율성을 높입니다.

0개의 댓글