리눅스 메모리 스와핑(swapping)
메모리 스와핑(Swapping)은 운영 체제에서 주기억 장치(RAM)가 부족할 때 사용되는 메모리 관리 기술입니다. 주로 리눅스와 유닉스 기반 시스템에서 사용됩니다. 메모리 스와핑은 하드 디스크나 SSD와 같은 보조 기억 장치를 사용하여 RAM에 더 이상 적재할 수 없는 데이터를 저장하고, 필요할 때 다시 RAM으로 되돌리는 방식으로 동작합니다.
메모리 스와핑은 시스템의 성능을 유지하기 위해 사용되지만, 스와핑 작업은 주 메모리보다 훨씬 느린 디스크 기반의 장치에 의존하므로, 실제로는 주 메모리가 아닌 스왑 영역에서 데이터를 처리하게 됩니다. 이로 인해 스와핑이 빈번하게 발생하면 성능 저하가 발생할 수 있습니다. 그래서 메모리 스와핑은 최대한 피하는 것이 좋습니다.
리눅스에서는 스왑 영역을 사전 설정하고 관리하는데, 스왑 파티션 또는 스왑 파일을 사용합니다. 스왑 파티션은 물리적인 파티션으로 할당되고, 스왑 파일은 일반 파일 시스템에서 지정된 공간으로 할당됩니다.
메모리 스와핑이 발생하는 경우
- 메모리 부족: 주 메모리(RAM)에 프로세스들과 운영 체제의 작업들이 많이 적재되어 메모리가 부족한 상태에서 스와핑이 발생합니다.
- 스와핑 튜닝: 일부 시스템 관리자는 스와핑을 튜닝하여 성능을 최적화하려고 할 때 스와핑을 능동적으로 사용할 수 있습니다. 이는 특정 프로세스의 우선순위 또는 프로세스 그룹에 대한 스와핑 옵션을 설정하여 수행됩니다.
메모리 스와핑 최적화
- 메모리 추가: 메모리 부족으로 인한 스와핑을 줄이기 위해 더 많은 RAM을 추가합니다.
- 스와핑 파티션/파일 크기 조정: 스와핑 파티션 또는 파일의 크기를 조정하여 스와핑 공간을 늘리거나 줄입니다.
- 스와핑 비율 조정: swappiness 설정을 통해 스와핑 비율을 조정할 수 있습니다. 이 값은 0에서 100 사이의 값으로, 0은 스와핑을 사용하지 않음을 의미하고, 100은 가능한 최대 스와핑을 의미합니다.
- 스와핑 비활성화: 필요에 따라 스와핑을 완전히 비활성화할 수 있지만, 메모리 부족으로 인해 시스템이 불안정해질 수 있으므로 주의가 필요합니다.
추가적으로, 스와핑이 빈번하게 발생하는 경우 스와핑 현상을 모니터링하여 원인을 파악하고, 불필요한 스와핑을 줄이는 데 도움이 되는 툴들이 있습니다. 예를 들어 vmstat, sar, htop 등을 사용하여 스와핑 관련 정보를 확인할 수 있습니다.
swap-in과 swap-out은 메모리 스와핑과 관련된 용어로, 주 메모리(RAM)와 스왑 영역(스왑 파티션 또는 스왑 파일) 간의 데이터 전송을 의미합니다. 이 두 용어는 리눅스와 유닉스 기반 시스템에서 자주 사용되는데, 메모리가 부족한 상태에서 시스템이 어떻게 데이터를 주 메모리와 스왑 영역 사이로 이동시키는지를 나타냅니다.
swap-in : 보조 기억장치(Disk)에서 주 기억장치(RAM)로 불러오는 과정
swap-out : 주 기억장치(RAM)에서 보조 기억장치(Disk)로 내보내는 과정
- Swap-in (스왑 인)
Swap-in은 스왑 영역에서 주 메모리로 데이터를 이동시키는 동작을 의미합니다. 스왑 영역에 저장된 데이터가 주 메모리에 필요한 상황이 발생할 때 발생합니다. 이런 상황은 주로 사용자가 사용하지 않던 프로그램을 다시 실행할 때, 프로세스를 생성하거나 다시 활성화할 때, 그리고 데이터를 읽어와야 할 때 등이 있습니다. Swap-in이 발생하면 스왑 영역에 저장된 데이터가 주 메모리로 이동하게 되므로 해당 데이터에 접근하는 데 걸리는 시간이 상당히 느려질 수 있습니다.
- Swap-out (스왑 아웃)
Swap-out은 주 메모리에서 스왑 영역으로 데이터를 이동시키는 동작을 의미합니다. 메모리가 부족하거나 더 많은 주 메모리 공간을 확보해야 할 때 발생합니다. 스왑 영역으로 이동되는 데이터는 주로 오랫동안 사용되지 않는 프로세스 또는 프로세스의 일부 데이터입니다. 이러한 데이터는 현재 필요하지 않기 때문에 스왑 영역으로 이동하여 주 메모리에서 해제하고 추가적인 공간을 마련합니다.
메모리 스와핑은 시스템 성능에 영향을 미치는 요소 중 하나이므로, 스왑의 사용 빈도와 양을 모니터링하고 적절한 조치를 취하는 것이 중요합니다. 스와핑이 너무 자주 발생하거나 스와핑 비율이 높으면 추가적인 메모리가 필요하거나 메모리 사용을 최적화할 필요가 있을 수 있습니다. 스와핑이 지나치게 발생하는 경우 성능 저하와 느린 응답 시간을 경험할 수 있으므로 이를 최소화하도록 조치하는 것이 좋습니다.
메모리 디버깅 도구로 strace와 valgrind를 사용하는 방법
이 두 도구는 리눅스와 유닉스 기반 시스템에서 프로그램의 동작과 메모리 사용에 대한 정보를 추적하고 디버깅하는 데 도움이 됩니다.
1. strace 사용 방법
strace는 프로세스가 실행 중에 시스템 호출과 신호를 추적하는 데 사용되는 유틸리티입니다. 프로그램이 어떤 시스템 호출을 수행하고 있는지, 파일을 읽고 쓰는 등의 동작, 그리고 발생하는 신호들을 추적하여 분석할 수 있습니다.
사용 방법은 아래와 같습니다.
strace -o output.txt your_program [program_options]
strace -e trace=file systemctl restart vsftpd
execve("/usr/bin/systemctl", ["systemctl", "restart", "vsftpd"], 0x7ffd4d846230 /* 24 vars */) = 0
access("/etc/ld.so.preload", R_OK) = -1 ENOENT (그런 파일이나 디렉터리가 없습니다)
open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
open("/lib64/librt.so.1", O_RDONLY|O_CLOEXEC) = 3
open("/lib64/libselinux.so.1", O_RDONLY|O_CLOEXEC) = 3
open("/lib64/liblzma.so.5", O_RDONLY|O_CLOEXEC) = 3
open("/lib64/liblz4.so.1", O_RDONLY|O_CLOEXEC) = 3
open("/lib64/libgcrypt.so.11", O_RDONLY|O_CLOEXEC) = 3
open("/lib64/libcap.so.2", O_RDONLY|O_CLOEXEC) = 3
open("/lib64/libgcc_s.so.1", O_RDONLY|O_CLOEXEC) = 3
open("/lib64/libpthread.so.0", O_RDONLY|O_CLOEXEC) = 3
open("/lib64/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
open("/lib64/libpcre.so.1", O_RDONLY|O_CLOEXEC) = 3
open("/lib64/libdl.so.2", O_RDONLY|O_CLOEXEC) = 3
open("/lib64/libgpg-error.so.0", O_RDONLY|O_CLOEXEC) = 3
open("/lib64/libattr.so.1", O_RDONLY|O_CLOEXEC) = 3
stat("/etc/sysconfig/64bit_strstr_via_64bit_strstr_sse2_unaligned", 0x7ffc6b38f950) = -1 ENOENT (그런 파일이나 디렉터리가 없습니다)
access("/etc/system-fips", F_OK) = -1 ENOENT (그런 파일이나 디렉터리가 없습니다)
statfs("/sys/fs/selinux", 0x7ffc6b390bb0) = -1 ENOENT (그런 파일이나 디렉터리가 없습니다)
statfs("/selinux", 0x7ffc6b390bb0) = -1 ENOENT (그런 파일이나 디렉터리가 없습니다)
open("/proc/filesystems", O_RDONLY) = 3
stat("/etc/sysconfig/64bit_strstr_via_64bit_strstr_sse2_unaligned", 0x7ffc6b390770) = -1 ENOENT (그런 파일이나 디렉터리가 없습니다)
access("/etc/selinux/config", F_OK) = 0
open("/usr/lib/locale/locale-archive", O_RDONLY|O_CLOEXEC) = 3
open("/proc/self/stat", O_RDONLY|O_CLOEXEC) = 3
stat("/proc/1/root", {st_mode=S_IFDIR|0555, st_size=244, ...}) = 0
stat("/", {st_mode=S_IFDIR|0555, st_size=244, ...}) = 0
stat("/proc/1/root", {st_mode=S_IFDIR|0555, st_size=244, ...}) = 0
stat("/", {st_mode=S_IFDIR|0555, st_size=244, ...}) = 0
lstat("/run/systemd/system/", {st_mode=S_IFDIR|0755, st_size=160, ...}) = 0
stat("/proc/1/root", {st_mode=S_IFDIR|0555, st_size=244, ...}) = 0
stat("/", {st_mode=S_IFDIR|0555, st_size=244, ...}) = 0
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=4993, si_uid=0, si_status=0, si_utime=0, si_stime=0} ---
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_KILLED, si_pid=4994, si_uid=0, si_status=SIGTERM, si_utime=0, si_stime=0} ---
+++ exited with 0 +++
- strace: strace 명령어를 실행합니다.
- -o output.txt: 추적 정보를 output.txt 파일에 저장합니다. 이 부분을 생략하면 추적 정보가 표준 출력에 표시됩니다.
- your_program: 디버깅하려는 프로그램의 실행 파일 경로를 지정합니다.
- [program_options]: 프로그램에 전달할 옵션과 인자들을 지정합니다.
strace는 프로그램이 어떻게 동작하는지, 어떤 시스템 호출이 발생하는지 등을 추적하여 보여줍니다. output.txt 파일에 저장된 정보를 통해 세부적인 분석이 가능합니다.
2. valgrind 사용 방법
valgrind는 메모리 누수, 잘못된 메모리 사용, 스레드 문제 등을 디버깅하는 데 사용되는 강력한 도구입니다. valgrind는 C, C++, 그리고 다른 프로그래밍 언어로 작성된 프로그램들을 디버깅하는 데 사용될 수 있습니다.
사용 방법은 아래와 같습니다.
yum install -y valgrind
valgrind --tool=memcheck your_program [program_options]
valgrind --leak-check=full --leak-resolution=med --log-file=/tmp/valgrind.log /usr/sbin/vsftpd
$ cat /tmp/valgrind.log
==5248== Memcheck, a memory error detector
==5248== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==5248== Using Valgrind-3.15.0 and LibVEX; rerun with -h for copyright info
==5248== Command: /usr/sbin/vsftpd
==5248== Parent PID: 4022
==5248==
==5249==
==5249== HEAP SUMMARY:
==5249== in use at exit: 4,535 bytes in 22 blocks
==5249== total heap usage: 48 allocs, 26 frees, 11,981 bytes allocated
==5249==
==5249== LEAK SUMMARY:
==5249== definitely lost: 0 bytes in 0 blocks
==5249== indirectly lost: 0 bytes in 0 blocks
==5249== possibly lost: 0 bytes in 0 blocks
==5249== still reachable: 4,535 bytes in 22 blocks
==5249== suppressed: 0 bytes in 0 blocks
==5249== Reachable blocks (those to which a pointer was found) are not shown.
==5249== To see them, rerun with: --leak-check=full --show-leak-kinds=all
==5249==
==5249== For lists of detected and suppressed errors, rerun with: -s
==5249== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
==5248==
==5248== HEAP SUMMARY:
==5248== in use at exit: 375 bytes in 18 blocks
==5248== total heap usage: 43 allocs, 25 frees, 7,793 bytes allocated
==5248==
==5248== LEAK SUMMARY:
==5248== definitely lost: 0 bytes in 0 blocks
==5248== indirectly lost: 0 bytes in 0 blocks
==5248== possibly lost: 0 bytes in 0 blocks
==5248== still reachable: 375 bytes in 18 blocks
==5248== suppressed: 0 bytes in 0 blocks
==5248== Reachable blocks (those to which a pointer was found) are not shown.
==5248== To see them, rerun with: --leak-check=full --show-leak-kinds=all
==5248==
==5248== For lists of detected and suppressed errors, rerun with: -s
==5248== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
- valgrind: valgrind 명령어를 실행합니다.
- --tool=memcheck: valgrind의 memcheck 도구를 사용하여 메모리 관련 문제를 검사합니다.
- your_program: 디버깅하려는 프로그램의 실행 파일 경로를 지정합니다.
- [program_options]: 프로그램에 전달할 옵션과 인자들을 지정합니다.
valgrind는 메모리 누수와 잘못된 메모리 접근 등을 탐지하고, 오류와 경고 메시지를 출력합니다. 이를 통해 메모리 관련 문제를 찾고 해결할 수 있습니다.
참고: valgrind는 프로그램 실행 시간이 증가하고, 성능에 영향을 미칠 수 있으므로, 실제 운영환경에서 사용하기보다는 디버깅 목적으로 사용하는 것이 좋습니다. 또한, valgrind를 사용하려면 해당 도구가 설치되어 있어야 합니다. 필요한 경우 패키지 관리자를 통해 설치하세요.
'리눅스' 카테고리의 다른 글
리눅스에서 네트워크 어댑터의 MTU를 변경하는 방법(Adapter MTU 변경) (0) | 2023.07.30 |
---|---|
리눅스 스왑 메모리(Swap Memory) (0) | 2023.07.29 |
[draft] MySQL Login Path 설정하는 방법 (0) | 2023.07.29 |
[draft] 우분투에서 wheel 그룹을 설정하는 관리하는 방법 (0) | 2023.07.26 |
[draft] MySQL 클라이언트를 설치하는 방법 (0) | 2023.07.26 |