특히 커널 및 시스템 아키텍처에서 Linux 메모리 할당의 세부 사항을 이해하는 것이 중요합니다. Linux 메모리 할당에 대해 자세히 알아보고 그 뒤에서 무슨 일이 일어나고 있는지 이해해 보겠습니다.
컴퓨터에서 프로세스가 실행 가능하려면 메모리에 저장되어 있어야 합니다. 이렇게 하려면 메모리의 프로세스에 필드를 할당해야 합니다. 메모리 할당은 특히 커널과 시스템 아키텍처에서 주의를 기울여야 할 중요한 문제입니다.
Linux 메모리 할당을 자세히 살펴보고 그 뒤에서 무슨 일이 일어나고 있는지 이해해 보겠습니다.
대부분의 소프트웨어 엔지니어는 이 프로세스의 세부 사항을 모릅니다. 그러나 시스템 프로그래머 후보자라면 이에 대해 더 많이 알아야 합니다. 할당 프로세스를 살펴보면 Linux 및 glibc 라이브러리에 대해 작은 세부 정보를 만드는 것이 필요합니다.
애플리케이션에 메모리가 필요한 경우 운영 체제에 요청해야 합니다. 커널의 이 요청에는 당연히 시스템 호출이 필요합니다. 사용자 모드에서는 메모리를 직접 할당할 수 없습니다.
**malloc()** 일련의 함수는 C 언어에서 메모리 할당을 담당합니다. 여기서 물어볼 질문은 glibc 함수인 malloc()이 직접 시스템 호출을 수행하는지 여부입니다.
리눅스 커널에는 malloc이라는 시스템 호출이 없습니다. 그러나 애플리케이션 메모리 요구 사항에 대한 두 가지 시스템 호출이 있습니다. brk 및 mmap입니다.
glibc 함수를 통해 애플리케이션에서 메모리를 요청하게 되므로 현재 glibc가 어떤 시스템 호출을 사용하고 있는지 알고 싶을 수도 있습니다. 대답은 둘 다입니다.
각 프로세스에는 연속적인 데이터 필드가 있습니다. brk 시스템 호출을 통해 데이터 필드 제한을 결정하는 프로그램 인터럽트 값이 증가하고 할당 프로세스가 수행됩니다.
이 방법을 사용하여 메모리를 할당하는 것은 매우 빠르지만, 사용하지 않은 공간을 시스템에 반환하는 것이 항상 가능한 것은 아닙니다.
예를 들어 brk 시스템 호출을 위해 malloc() 함수를 통해 각 필드 크기가 16KB인 5개의 필드를 할당한다고 가정해 보겠습니다. 두 번째 필드를 완료하면 관련 리소스가 시스템에서 사용할 수 있도록 반환(할당 취소)될 수 없습니다. 두 번째 필드가 시작되는 위치를 표시하기 위해 주소 값을 줄이고 brk를 호출하면 세 번째, 네 번째, 다섯 번째 필드의 해제가 완료되기 때문입니다.
이 경우 메모리 손실을 방지하기 위해 glibc의 malloc 구현은 프로세스 데이터 필드에서 할당된 위치를 모니터링한 다음 free() 함수에 지정된 대로 시스템에 반환하여 시스템이 여유 공간을 추가 메모리에 사용할 수 있도록 합니다. 분배하다.
즉, 16KB 영역 5개를 할당한 후 free() 함수를 사용하여 두 번째 영역을 반환하고, 잠시 후 또 다른 16KB 영역을 요청하면 brk 시스템 호출을 통해 데이터 영역을 확장하는 대신 이전의 주소가 돌아왔습니다.
단, 새로 요청한 영역이 16KB보다 큰 경우 영역 2를 사용할 수 없으므로 brk 시스템 호출을 통해 새 영역을 할당하여 데이터 영역을 확장합니다. 2번 영역은 사용하지 않지만 크기가 다르기 때문에 애플리케이션에서 사용할 수 없습니다. 이와 같은 시나리오로 인해 메모리의 모든 부분을 실제로 완전히 활용할 수 없는 내부 조각화라는 현상이 발생합니다.
더 나은 이해를 위해 다음 샘플 애플리케이션을 컴파일하고 실행해 보세요.
으아악애플리케이션을 실행하면 다음과 유사한 출력이 표시됩니다.
으아악strace를 사용한 brk의 출력은 다음과 같습니다.
으아악보시다시피 데이터 필드의 끝 주소에 0x21000이 추가되었습니다. 0x5608595d7000 값을 통해 이를 이해할 수 있습니다. 따라서 대략 0x21000 또는 132KB의 메모리가 할당됩니다.
여기서 고려해야 할 두 가지 사항이 있습니다. 첫 번째는 예제 코드에 명시된 것보다 더 많이 할당하는 것입니다. 다른 하나는 할당을 제공하는 brk 호출을 유발하는 코드 줄입니다.
위의 샘플 애플리케이션을 차례로 실행해 보면 매번 다른 주소 값을 보게 됩니다. 이러한 방식으로 주소 공간을 무작위로 변경하면 보안 공격 작업이 크게 복잡해지고 소프트웨어 보안이 향상됩니다.
但是,在 32 位架构中,通常使用 8 位来随机化地址空间。增加位数将不合适,因为剩余位上的可寻址区域将非常低。此外,仅使用 8 位组合不会使攻击者的事情变得足够困难。
另一方面,在 64 位体系结构中,由于可以为 ASLR 操作分配的位太多,因此提供了更大的随机性,并且提高了安全程度。
Linux 内核还支持基于 Android 的设备,并且 ASLR 功能在 Android 4.0.3 及更高版本上完全激活。即使仅出于这个原因,也可以说 64 位智能手机比 32 位版本具有显着的安全优势。
通过使用以下命令暂时禁用 ASLR 功能,之前的测试应用程序每次运行时都会返回相同的地址值:
echo 0 | sudo tee /proc/sys/kernel/randomize_va_space
要将其恢复到以前的状态,在同一个文件中写入 2 而不是 0 就足够了。
mmap 是 Linux 上用于内存分配的第二个系统调用。通过 mmap 调用,内存中任何区域的空闲空间都映射到调用进程的地址空间。
在以这种方式完成的内存分配中,当您想使用前面 brk 示例中的 free() 函数返回第二个 16KB 分区时,没有机制可以阻止此操作。从进程的地址空间中删除相关的内存段。它被标记为不再使用并返回系统。
因为与使用 brk 相比,使用 mmap 的内存分配非常慢,所以需要分配 brk。
使用 mmap,内存的任何空闲区域都映射到进程的地址空间,因此在该进程完成之前,已分配空间的内容被重置。如果没有以这种方式进行重置,则属于先前使用相关内存区域的进程的数据也可以被下一个不相关的进程访问。这样就不可能谈论系统中的安全性。
内存分配非常重要,尤其是在优化和安全问题上。如上面的示例所示,不完全理解此问题可能意味着破坏系统的安全性。
甚至许多编程语言中存在的类似于 push 和 pop 的概念也是基于内存分配操作的。能够很好地使用和掌握系统内存对于嵌入式系统编程和开发安全和优化的系统架构都是至关重要的。
如果您还想涉足 Linux 内核开发,请考虑首先掌握 C 编程语言。
综上所述,Linux 中的内存分配是一个需要注意和理解的重要问题,特别是对于程序员、内核开发人员和系统架构师而言。熟练掌握内存分配可以提高软件性能和安全性,并在嵌入式系统编程和系统架构方面提供更好的支持。同时,C 编程语言的掌握也是涉足 Linux 内核开发的关键。
위 내용은 Linux에서 메모리 할당이 작동하는 방식의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!