최근 그룹에서 제가 기대하고 있는 공유 주제가 있습니다: "리눅스의 가상 메모리". 어느 날 밤 야근을 하다가 가상 메모리 개념에 대해 논의하던 중 리더가 몇몇 동료들이 가상 메모리를 제대로 이해하지 못하고 있다는 사실을 발견하고 이 동료를 위해 특별히 이 주제를 선택했습니다(웃음).
이전에는 운영체제의 개념을 어느 정도 이해하고 있었지만, 졸업 후에는 대학에서 4년 동안 컴퓨터공학을 전공한 시간이 아깝다는 생각이 조금 들었습니다. 그래서 퇴근 후에는 NetEase Cloud Classroom에서 하얼빈공업대학 운영체제 오픈클래스를 시청하고, 운영체제의 기본 개념을 설명하는 책 '리눅스 커널 설계 및 구현'도 읽는 시간을 가졌습니다. 게다가 작년에는 C 언어를 사용하여 간단한 서버를 작성하고 기본 시스템에 대해 더 많이 배웠습니다. 이 지식을 통해 애플리케이션 계층을 더 잘 이해할 수 있었고 최근 문제 해결 중에 많은 도움이 되었습니다.
며칠 전 다른 동료가 가상 메모리와 관련된 또 다른 질문을 했고, 저는 가상 메모리에 대한 이해가 충분히 깊지 않고 일부 개념이 모순되기까지 한다는 것을 깨달았습니다. 그래서 다음 번에는 실제 적용에 좀 더 능숙해지기를 바라면서 몇 가지 자료를 살펴보고 이 지식을 재구성했습니다.
가상 메모리가 운영 체제에서 가장 중요한 개념 중 하나라는 것은 의심의 여지가 없습니다. 나는 그것이 전체 시스템에서 메모리의 중요성 때문이라고 생각합니다. CPU는 매우 빠르지만 용량이 제한되어 있고 기능도 하나입니다. 다른 I/O 하드웨어는 다양한 고급 기능을 지원하지만 CPU보다 속도가 느립니다. 그러므로 그들 사이에서 완충 역할을 할 윤활유가 필요하며, 이것이 기억이 작용하는 곳입니다.
최신 운영 체제에서는 멀티태스킹이 표준이 되었습니다. 멀티 태스킹 병렬화는 CPU 활용도를 크게 향상시키지만, 여러 프로세스 간의 메모리 작업 충돌을 초래하기도 합니다. 가상 메모리의 개념은 이러한 문제를 해결하기 위한 것입니다.
위 그림은 가상 메모리에 대한 가장 간단하고 직관적인 설명입니다.
운영 체제에는 물리적 메모리 조각(중간 부분)과 두 개의 프로세스(실제로는 그 이상)인 P1과 P2가 있습니다. 운영 체제는 비밀리에 P1과 P2에게 내 전체 메모리가 귀하의 것임을 알려주므로 원하는 대로 사용하고 관리하세요. . 충분한. 그런데 사실 운영체제는 그들에게 큰 파이를 주었을 뿐입니다. 이 메모리들은 P1과 P2에게 주어졌다고 하지만 실제로는 일련번호만 주어졌습니다. P1과 P2가 실제로 이러한 메모리를 사용하기 시작할 때만 시스템은 프로세스를 위해 이동하고 다양한 블록을 결합하기 시작합니다. P2는 A 메모리를 사용하고 있다고 생각하지만 실제로는 다음과 같이 조용히 실제 B로 리디렉션되었습니다. P1과 P2가 C 메모리를 공유하더라도 이를 알지 못합니다.
프로세스를 속이는 운영체제의 이런 방식이 바로 가상 메모리입니다. P1, P2와 같은 프로세스의 경우 모두 자신이 전체 메모리를 점유하고 있다고 생각하며, 자신이 사용하는 물리적 메모리의 어떤 주소를 알지도 못하고 신경 쓸 필요도 없습니다.
가상 메모리는 운영체제에서 말하는 개념이다. 운영체제에게 가상 메모리는 비교표이다. P1이 A 메모리의 데이터를 얻으면 B 메모리의 데이터를 찾기 위해 물리 메모리의 A 주소로 가야 한다. . 물리적 메모리의 C 주소로 이동해야 합니다.
시스템의 기본 단위는 Byte라는 것을 알고 있습니다. 가상 메모리의 각 Byte가 물리적 메모리의 주소에 매핑되면 각 항목에는 최소 8바이트(32비트 가상 주소 -> 32비트 물리적 주소)가 필요합니다. 4G 메모리의 경우 비교 테이블을 저장하려면 32GB의 공간이 필요하기 때문에 이 테이블은 실제 물리적 주소조차 맞추기에는 너무 크기 때문에 운영체제에서는 页(Page)
라는 개념을 도입했습니다.
시스템이 시작되면 운영 체제는 전체 물리적 메모리를 4K 단위의 페이지로 나눕니다. 향후 메모리 할당 시 단위는 페이지이므로 물리적 메모리 페이지에 해당하는 가상 메모리 페이지의 매핑 테이블이 크게 줄어듭니다. 4G 메모리에는 8M 매핑 테이블만 필요합니다. 매핑 관계를 저장해야 하며 Linux는 메모리 소비를 줄이기 위해 페이징할 수 있는 대용량 메모리를 위한 다중 레벨 페이지 테이블도 설계합니다. 운영 체제 가상 메모리와 실제 메모리 간의 매핑 테이블을 页表
이라고 합니다.
가상 메모리 메커니즘을 통해 각 프로세스는 프로세스가 메모리에 액세스하면 운영 체제가 프로세스에서 제공하는 가상 메모리 주소를 물리적 주소로 변환한 다음 데이터를 획득한다고 생각합니다. 해당 물리적 주소에. CPU에는 가상 메모리 주소를 변환하는 데 특별히 사용되는 하드웨어가 있습니다. CPU는 또한 프로그램의 지역성으로 인해 페이지 테이블 주소 지정을 위한 캐시 전략을 설정하며 캐시 적중률은 98%에 달할 수 있습니다. 内存管理单元 MMU(Memory Management Unit)
를 생성합니다. 시스템은 커널 상태로 전환됩니다. 프로세스에 가상 주소를 할당합니다. 缺页中断
가상 메모리를 통해 메모리와 데이터를 더 쉽게 공유할 수 있습니다.
프로세스가 시스템 라이브러리를 로드할 때 항상 메모리의 일부를 먼저 할당하고 디스크의 라이브러리 파일을 이 메모리에 로드합니다. 실제 메모리 주소가 고유하기 때문에 시스템이 해당 주소를 발견하더라도 동일한 라이브러리가 시스템에 있습니다. 두 번 로드되었지만 각 프로세스에서 지정한 로드 메모리가 달라서 시스템이 아무것도 할 수 없었습니다.
가상 메모리를 사용할 때 시스템은 프로세스의 가상 메모리 주소를 라이브러리 파일이 있는 실제 메모리 주소로 가리키기만 하면 됩니다. 위 그림에서 볼 수 있듯이 프로세스 P1과 P2의 B 주소는 모두 물리적 주소 C를 가리킵니다.
가상 메모리를 사용하면 공유 메모리를 사용하는 방법도 매우 간단합니다. 시스템은 각 프로세스의 가상 메모리 주소를 시스템에서 할당한 공유 메모리 주소로 지정하기만 하면 됩니다.
가상 메모리를 사용하면 프로세스가 메모리를 "확장"할 수 있습니다.
앞서 가상 메모리는 페이지 폴트 인터럽트를 통해 프로세스에 물리적 메모리를 할당한다고 언급했습니다. 메모리가 항상 제한되어 있으면 어떨까요?
Linux에서는 SWAP 파티션을 제안합니다. 물리적 메모리가 할당되었지만 사용 가능한 메모리가 부족한 경우 임시로 사용되지 않은 메모리 데이터가 먼저 디스크에 배치되어 필요한 프로세스가 먼저 사용할 수 있습니다. 그런 다음 프로세스는 이를 다시 사용해야 합니다. 그런 다음 이 데이터는 메모리에 로드됩니다. Linux는 이 "스와핑" 기술을 통해 프로세스가 더 많은 메모리를 사용할 수 있도록 허용합니다.
저도 가상 메모리를 이해하면서 궁금한 점이 많았습니다.
가장 일반적인 문제는 32비트와 64비트입니다.
CPU는 물리적 버스를 통해 메모리에 액세스하므로 액세스 주소 범위는 머신 버스 수에 따라 제한됩니다. 32비트 시스템에는 각 버스에 비트 1과 로우를 나타내는 2개의 버스가 있습니다. 0이면 최대 액세스 가능 주소는 2^32비트 = 4GB이므로 32비트 시스템에 4G보다 큰 메모리를 삽입하는 것은 유효하지 않으며 CPU는 4G보다 큰 메모리에 액세스할 수 없습니다.
그러나 64비트 시스템에는 64비트 버스가 없으며 운영 체제에 따라 최대 메모리가 제한됩니다. Linux는 현재 최대 256G 메모리를 지원합니다.
가상 메모리 개념에 따르면 32비트 시스템에서 64비트 소프트웨어를 실행하는 것은 괜찮습니다. 그러나 시스템의 가상 메모리 주소 구조로 인해 32비트에서는 64비트 가상 주소를 사용할 수 없습니다. 시스템.
운영체제에서는 가상 메모리를 사용하는데, 메모리를 직접 조작하려면 어떻게 해야 하나요?
Linux는 각 장치를 /dev/
目录下的文件,我们可以通过这些设备文件直接操作硬件,内存也不例外。在 Linux 中,内存设置被映射为 /dev/mem
에 매핑하며, 루트 사용자는 이 파일을 읽고 쓰면서 메모리를 직접 조작할 수 있습니다.
TOP을 사용하여 시스템 성능을 보면 VIRT 열에서 Java 프로세스가 많은 양의 가상 메모리를 차지한다는 것을 알 수 있습니다.
이 문제가 발생하는 이유는 Java가 Glibc의 Arena 메모리 풀을 사용하여 대량의 가상 메모리를 할당하고 사용하지 않기 때문입니다. 또한 Java에서 읽은 파일도 가상 머신의 기본 구성에 따라 각 Java 스레드 스택이 1M의 가상 메모리를 차지합니다. 자세한 내용은 Linux의 멀티스레드 프로그램이 왜 그렇게 많은 가상 메모리를 소비하는지 확인할 수 있습니다.
실제 사용되는 물리적 메모리는 RES
(상주) 열에 따라 다릅니다. 이 열의 값은 실제로 물리적 메모리에 매핑되는 크기입니다.
리눅스 가상 메모리를 직접 관리할 수도 있습니다.
시스템 메모리 상태를 확인하는 방법은 다양합니다. free
、 vmstat
및 기타 명령으로 현재 시스템의 메모리 상태를 출력할 수 있습니다. 운영 체제의 게으른 특성으로 인해 사용 가능한 메모리가 단순한 것이 아니라는 점에 유의해야 합니다. , 프로세스가 실행되지 않을 때 많은 수의 버퍼/캐시가 사용됩니다. 재사용 후 즉시 정리되지 않습니다. 이전에 사용했던 프로세스를 계속 사용할 수 있으면 필요한 경우에도 활용할 수 있습니다. .
또한 cat /proc/meminfo
를 통해 더티 페이지 상태 등 시스템 메모리 사용량에 대한 세부 정보를 볼 수 있습니다. 자세한 내용은 /PROC/MEMINFO 미스터리에서 확인할 수 있습니다.
특정 프로세스의 가상 메모리 분포를 개별적으로 보려면 pmap pid
명령을 사용하면 각 가상 메모리 세그먼트의 점유율이 낮은 주소에서 높은 주소로 나열됩니다.
-XX
매개변수를 추가하면 더 자세한 정보를 출력할 수 있습니다.
Linux 시스템 구성을 수정하고 sysctl vm [-options] CONFIG
或 直接读写 /proc/sys/vm/
디렉터리의 파일을 사용하여 구성을 보고 수정할 수도 있습니다.
가상 메모리의 SWAP 기능은 프로세스가 메모리와 디스크 간에 대량의 데이터를 지속적으로 교환하도록 허용하는 것은 CPU를 크게 점유하고 시스템 운영 효율성을 저하시키므로 때때로 스왑을 사용하고 싶지 않습니다.
vm.swappiness=0
来设置内存尽量少使用 swap,或者干脆使用 swapoff
명령을 수정하여 SWAP을 비활성화할 수 있습니다.
가상 메모리의 개념은 이해하기 매우 쉽지만, 일련의 매우 복잡한 지식을 파생하게 됩니다. 이 기사에서는 몇 가지 기본 원칙에 대해서만 설명하고 가상 메모리 주소 지정에서 중간 세그먼트 레지스터 사용, 캐시 및 버퍼 애플리케이션 향상을 위한 운영 체제의 가상 메모리 사용 등과 같은 많은 세부 사항을 건너뜁니다. 그것에 대해서는 별도로 이야기하겠습니다.
위 내용은 리눅스 가상메모리, 잘 이해되셨나요?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!