섹션 4.4에서 TLPI를 읽고 있습니다.
시스템 호출은 호출자에게 정보를 반환하는 데 사용되는 버퍼에 메모리를 할당하지 않습니다. 대신, 이전에 할당된 올바른 크기의 메모리 버퍼에 대한 포인터를 전달해야 합니다. 이는 호출자에게 정보를 반환하기 위해 메모리 버퍼를 할당하는 일부 라이브러리 함수와 대조됩니다.
이러한 경우에 시스템 호출이 메모리를 할당하지 않는 이유는 무엇입니까? 이것은 사용자가 (불필요하게 새 메모리를 할당하는 대신) 기존 버퍼를 사용할 수 있도록 하는 메모리 최적화입니까? 다른 이유가 있나요?
답변1
많은 개발자들은 이것이 malloc()
시스템 호출이 아니라는 사실을 잊어버립니다. C 라이브러리 함수입니다. 실제 메모리 할당은 다음을 통해 수행됩니다.brk
시스템 호출은 매우 다르게 동작합니다.
malloc()
간단히 말해서, 프로그램에는 확장해야 하는 데이터를 저장하기 위해 할당된 RAM이 하나만 있습니다.필요하다면사용 brk()
. 그러나 malloc
.을 사용하여 버퍼를 해제한 후에는 버퍼를 쉽게 재사용할 수 있습니다 free()
. 버퍼가 해제되면 (반드시 그런 것은 아니지만) 다음과 같이 운영 체제에 반환되지 않습니다.일반적으로 힙 중앙에 위치합니다..
이제 귀하의 질문에 답해 보겠습니다. 시스템 호출이 내부적으로 버퍼를 할당할 수 없는 이유는 무엇입니까?
커널은 프로그램이 데이터 블록을 어떻게 사용하는지 전혀 모릅니다. C 라이브러리를 사용하고 있다고 가정할 수 없습니다. 그렇지 않으면 malloc
데이터 구조와 상호 작용할 수 없으며 버퍼를 할당하기 위해 어떤 데이터 구조를 사용하고 있는지 확실하지 않습니다. 이는 해제될 수 있는 버퍼를 할당할 수 없음을 의미합니다 free()
.
이론적으로는 사용되지 않은 주소 공간에 전체 RAM 페이지를 할당할 수 있지만 이를 해제하려면 완전히 새로운 시스템 호출이 필요하며 이는 free()
일반적으로 시스템 호출을 발생시키지 않는 것보다 훨씬 더 비쌉니다. 버퍼가 전체 페이지보다 훨씬 작기 때문에 이는 매우 낭비적입니다.
마지막으로, 많은 경우 프로그램의 특정 위치에 이미 데이터가 필요할 수 있다는 점을 이해하는 것이 좋습니다. 데이터를 원하는 위치에 직접 쓰도록 시스템 호출에 요청할 수 있으면 코드에서 데이터를 복사하고 페이지를 해제하도록 강제할 필요가 없습니다.
답변2
커널이 메모리를 할당하기를 원할 때 호출합니다 mmap()
. 호출할 때 mmap()
원하는 플래그를 선택해야 합니다. 할당을 PROT_EXEC
, MAP_HUGE_2MB
또는 로 설정하시겠습니까 MAP_LOCKED
? 특정 주소( )에 할당하시겠습니까 MAP_FIXED
?
따라서 할당을 분리하는 것이 더 간단할 것입니다. 이는 모든 시스템 호출에서 이러한 플래그에 대한 매개변수를 제공할 필요가 없음을 의미합니다.
커널을 사용하여 메모리 할당을 해제하려면 또 다른 시스템 호출이 필요합니다 munmap()
.
더 빠르게덕-커널 할당을 직접 사용하지 않는 경우 할당합니다. free()
는 시스템 호출이 아니므로 munmap()
.
역사적인 이유도 있습니다. 원래 UNIX 커널은 임의의 메모리 페이지를 할당하고 해제할 수 없었습니다. 를 호출하면 brk()
힙 메모리의 크기가 늘어납니다. 힙 내의 메모리 블록을 해제하도록 커널에 요청할 수 없습니다.