리눅스 시스템 메모리 이해 및 최적화

리눅스 시스템에서 메모리 관리는 시스템 성능에 핵심적인 요소입니다. 시스템 자원 중 메모리는 애플리케이션의 원활한 동작을 위해 필수적이며, 이를 효율적으로 모니터링하고 관리하는 방법을 이해하는 것이 중요합니다.

메모리 사용 현황 모니터링

시스템 메모리 상태를 확인하는 가장 기본적인 도구는 free 명령입니다. 이 명령은 물리 메모리(RAM)와 스왑 공간의 총량, 사용량, 그리고 여유량을 보여줍니다.

$ free -h
              total        used        free      shared  buff/cache   available
Mem:            15G         3.1G        9.8G        8.0M        2.4G         12G
Swap:           7.8G          0B        7.8G

free 명령어의 출력은 다음과 같이 해석할 수 있습니다:

  • total: 시스템에 장착된 총 물리 메모리 및 스왑 공간.
  • used: 현재 사용 중인 물리 메모리 및 스왑 공간.
  • free: 현재 사용 가능하며 즉시 할당될 수 있는 물리 메모리 및 스왑 공간.
  • shared: 여러 프로세스에서 공유되고 있는 메모리 양.
  • buff/cache: 커널 버퍼(buffers)와 페이지 캐시(cache)로 사용되는 메모리 양. 이 메모리는 성능 향상을 위해 사용되며, 애플리케이션에서 메모리가 필요할 경우 즉시 회수되어 사용될 수 있습니다.
  • available: 현재 새로운 애플리케이션에서 사용할 수 있는 예상 메모리 양 (buff/cache 포함).

특히 buff/cache는 파일 I/O 성능 향상을 위해 사용되지만, 실제로는 언제든지 애플리케이션에 할당될 수 있는 '가용 메모리'로 간주됩니다. 따라서 순수하게 'free' 메모리만 보는 것보다는 'available' 메모리를 확인하는 것이 시스템의 실제 가용 메모리 상태를 더 정확하게 보여줍니다.

메모리 캐시 수동 해제

리눅스 커널은 디스크 I/O 성능을 높이기 위해 자주 접근하는 데이터를 메모리에 캐시(buff/cache)합니다. 특정 상황에서 (예: 벤치마킹 전, 시스템 메모리 문제를 진단할 때) 이 캐시를 수동으로 해제하여 메모리 상태를 초기화할 필요가 있을 수 있습니다.

캐시 해제 전에 sync 명령어를 실행하여 모든 변경된 버퍼 데이터를 디스크에 기록하는 것이 중요합니다. 그렇지 않으면 데이터 손실이 발생할 수 있습니다.

$ sync

캐시를 해제하는 방법은 /proc/sys/vm/drop_caches 파일에 특정 값을 쓰는 것입니다:

  • 페이지 캐시(Page Cache) 해제:
    $ echo 1 > /proc/sys/vm/drop_caches
    
  • 디렉터리 엔트리(dentries) 및 아이노드(inodes) 캐시 해제:
    $ echo 2 > /proc/sys/vm/drop_caches
    
  • 모든 캐시(페이지 캐시, dentries, inodes) 해제:
    $ echo 3 > /proc/sys/vm/drop_caches
    

강력한 데이터 처리 도구: dd

dd 명령어는 '데이터셋 복사 및 변환(convert and copy a file)'을 의미하며, 파일, 디바이스, 파티션 등 다양한 소스에서 대상으로 데이터를 복사하거나 변환하는 데 사용되는 강력한 유틸리티입니다. 저수준 디스크 작업에 주로 활용됩니다.

기본 사용법: dd if=/경로/소스 of=/경로/대상 [옵션...]

  • if=FILE: 입력 소스 파일 또는 디바이스를 지정합니다. (기본값: 표준 입력)
  • of=FILE: 출력 대상 파일 또는 디바이스를 지정합니다. (기본값: 표준 출력)
  • bs=BYTES: 한 번에 읽고 쓰는 블록 크기를 BYTES로 지정합니다. (ibsobs를 동시에 설정)
  • count=BLOCKS: 지정된 블록 수만큼만 복사합니다.
  • skip=BLOCKS: 입력 시작 부분에서 BLOCKS만큼 건너뛰고 복사를 시작합니다.
  • seek=BLOCKS: 출력 시작 부분에서 BLOCKS만큼 건너뛰고 쓰기를 시작합니다.
  • conv=CONVERSION[,CONVERSION...]: 데이터를 변환할 방법을 지정합니다.
    • notrunc: 출력 파일을 자르지 않고 덮어씁니다.
    • noerror: 읽기 오류 발생 시에도 작업을 중단하지 않습니다.
    • sync: 각 입력 블록을 ibs 크기로 채웁니다.
    • fdatasync: 물리적 쓰기 완료 후 반환합니다.

dd 명령어 활용 예시

1. MBR (Master Boot Record) 백업 및 손상

MBR은 디스크의 첫 번째 섹터에 위치하며 부팅 정보를 담고 있습니다. 중요한 시스템 파일을 백업하거나 손상시키는 데 dd를 사용할 수 있습니다.

  • MBR 백업: /dev/sda의 첫 512바이트(MBR)를 /tmp/mbr.bak 파일로 백업합니다.
    $ sudo dd if=/dev/sda of=/tmp/mbr.bak bs=512 count=1
    
  • MBR 부트로더 손상 (주의!): /dev/zero의 널(NULL) 바이트로 /dev/sda의 MBR 부트로더 영역을 덮어씁니다. 이 작업은 시스템을 부팅 불능 상태로 만들 수 있으니 매우 주의해야 합니다.
    $ sudo dd if=/dev/zero of=/dev/sda bs=64 count=1 seek=446
    

2. 특정 파일 영역 복사 및 삽입

파일의 특정 바이트 범위만 읽어 다른 파일의 특정 위치에 쓰는 작업입니다.

예를 들어, source_file.bin 파일의 64번째 바이트부터 128바이트를 읽어 target_file.bin 파일의 32번째 바이트 위치에 덮어쓰려면:

$ dd if=source_file.bin of=target_file.bin bs=1 count=128 skip=63 seek=31 conv=notrunc

3. 디스크 또는 파티션 이미지 생성 및 복원

  • 전체 디스크 백업: /dev/sdb 전체 디스크를 /backup/disk_image.img 파일로 백업합니다.
    $ sudo dd if=/dev/sdb of=/backup/disk_image.img
    
  • 압축된 디스크 이미지 백업: /dev/sdc 디스크를 gzip으로 압축하여 /backup/disk_image.gz로 저장합니다.
    $ sudo dd if=/dev/sdc | gzip > /backup/disk_image.gz
    
  • 디스크 이미지 복원: /backup/disk_image.img 파일을 /dev/sdd 디스크로 복원합니다. 이 작업은 대상 디스크의 모든 데이터를 덮어쓰므로 주의해야 합니다.
    $ sudo dd if=/backup/disk_image.img of=/dev/sdd
    
  • 압축된 이미지 복원: gzip으로 압축된 이미지를 해제하면서 /dev/sde 디스크로 복원합니다.
    $ gzip -dc /backup/disk_image.gz | sudo dd of=/dev/sde
    

4. 물리 메모리 데이터를 파일로 복사

시스템의 물리 메모리 내용을 파일로 덤프할 수 있습니다. 이는 포렌식 분석 등에 활용될 수 있습니다.

$ sudo dd if=/dev/mem of=/root/memory_dump.bin bs=1M

5. CD/DVD 드라이브에서 ISO 이미지 생성

광학 드라이브에서 직접 ISO 이미지를 만들 수 있습니다.

$ sudo dd if=/dev/cdrom of=/home/user/my_disc.iso

6. 디스크 데이터 영구 삭제 (보안 삭제)

/dev/urandom(임의 데이터) 또는 /dev/zero(널 바이트)를 사용하여 디스크 파티션의 데이터를 덮어씀으로써 복구 불가능하게 만들 수 있습니다. 이 작업은 돌이킬 수 없으므로 극도의 주의가 필요합니다.

$ sudo dd if=/dev/urandom of=/dev/sdb1

위 명령은 /dev/sdb1 파티션을 무작위 데이터로 채웁니다. 완료 후에는 해당 파티션을 더 이상 마운트하거나 사용할 수 없습니다.

스왑(Swap) 공간 생성 및 관리

스왑 공간은 물리 메모리가 부족할 때 사용되는 디스크 공간입니다. 리눅스 시스템은 메모리에 적재된 데이터 중 사용 빈도가 낮은 것을 스왑 공간으로 옮겨 물리 메모리를 확보합니다. 스왑 공간은 별도의 파티션으로 만들 수도 있지만, 일반 파일로도 생성하여 사용할 수 있습니다.

스왑 파일 생성

dd 명령을 사용하여 지정된 크기의 스왑 파일을 생성합니다. 여기서는 1GB 크기의 /var/swapfile.img 파일을 생성하는 예시입니다.

$ sudo dd if=/dev/zero of=/var/swapfile.img bs=1M count=1024
1024+0 records in
1024+0 records out
1073741824 bytes (1.1 GB, 1.0 GiB) copied, 1.2345 s, 870 MB/s
  • if=/dev/zero: 널(0) 바이트를 입력 소스로 사용합니다.
  • of=/var/swapfile.img: 생성될 스왑 파일의 경로와 이름을 지정합니다.
  • bs=1M: 블록 크기를 1MB로 설정합니다.
  • count=1024: 1024개의 블록을 복사하여 총 1024MB (1GB) 파일을 만듭니다.

스왑 파일 형식 지정

생성된 파일을 스왑 공간으로 사용하기 위해 mkswap 명령으로 스왑 파일 시스템 형식을 지정합니다.

$ sudo mkswap /var/swapfile.img
Setting up swapspace version 1, size = 1024 MiB (1073737728 bytes)
no label, UUID=...

스왑 공간 활성화

swapon 명령을 사용하여 생성된 스왑 파일을 시스템에 활성화합니다.

$ sudo swapon /var/swapfile.img

재부팅 후에도 스왑 공간이 자동으로 활성화되도록 하려면 /etc/fstab 파일에 다음 줄을 추가해야 합니다.

/var/swapfile.img none swap sw 0 0

스왑 사용률 최적화: swappiness

swappiness 매개변수는 리눅스 커널이 스왑 공간을 얼마나 적극적으로 사용할지 결정하는 값입니다. 이 값은 0에서 100 사이의 정수이며, 기본값은 대개 60입니다.

  • swappiness=0: 커널은 물리 메모리를 최대한 오래 사용하려고 노력하며, 메모리가 거의 가득 찰 때만 스왑을 사용합니다.
  • swappiness=100: 커널은 스왑 공간을 매우 적극적으로 사용하며, 메모리에 있는 데이터를 빠르게 스왑으로 옮기려 합니다.

일반적으로 데스크톱 시스템에서는 swappiness 값을 낮게 설정하여 물리 메모리 사용을 선호하는 것이 좋고, 서버에서는 애플리케이션의 특성에 따라 기본값(60)을 유지하거나 조절할 수 있습니다.

현재 swappiness 값 확인

$ cat /proc/sys/vm/swappiness
60

swappiness 값 임시 변경

현재 세션에서만 값을 변경하려면 다음 명령 중 하나를 사용합니다. 여기서는 값을 10으로 설정하는 예시입니다.

$ sudo sysctl vm.swappiness=10

또는

$ sudo echo 10 > /proc/sys/vm/swappiness

swappiness 값 영구 변경

시스템 재부팅 후에도 변경된 값이 유지되도록 하려면 /etc/sysctl.conf 파일을 수정해야 합니다.

/etc/sysctl.conf 파일을 열고 다음 줄을 추가하거나 수정합니다:

vm.swappiness=10

변경사항을 즉시 적용하려면 다음 명령을 실행합니다.

$ sudo sysctl -p

태그: linux memory-management swap dd cache

7월 21일 02:48에 게시됨