2012-03-20 1 views
1

커널이 가상 메모리를 실제 메모리에 매핑하는 것을 알고 있습니다. 하지만/proc/pid/maps 파일에있는 프로세스의 가상 메모리를 누가 실제로 생성하는지 알고 싶습니다.누가 Linux에서 가상 메모리를 생성합니까?

1) 컴파일러/링커가 프로세스의 가상 메모리 영역을 만들고 커널이 실제 메모리에 매핑합니다 (가상 메모리 영역은 중요하지 않으므로 모든 매핑이 중요합니다)?

2) 또는 커널 자체가 프로세스를 포크하는 동안 가상 메모리 공간을 생성하고 실제 메모리에 매핑합니까?

마지막으로 mmap 시스템 호출 (1) 또는 (2)는 무엇을 수행합니까?

답변

1

커널은 실제로 를 만들고 당신은/proc/PID /지도에서 볼 가상 메모리 영역을 관리하는 엔티티입니다. 각 프로세스 (struct task_struct)의 상태를 유지하는 구조 내에는 struct mm_struct (linux/sched.h에 있음)이 있으며 특히 그 안에는 struct vm_area_struct * mmap이 있습니다. 프로세스 주소 공간에 매핑 된 모든 메모리 영역 (영역 설명자)의 커널에 의해 유지 관리되는 목록입니다. mmap이 호출되면이 목록에 새 요소가 추가되고/proc/pid/maps에 표시됩니다.

파일 지원 영역의 대부분은 다음과 같습니다./proc/pid/maps에 나열된 libc.so는 프로세스 시작시 동적 링커 (ld.so)의 코드에 의해 매핑됩니다.

또한 커널은 절대적으로 필요한 경우가 아니면이 영역의 주소에 대한 가상 - 실제 매핑을 생성하지 않습니다.

희망이 있습니다.

3

귀하의 주장은 실제로 어느 정도 정확합니다.

실행 가능한 ELF 파일의 경우 링커는 링커 스크립트를 사용하여 가상 공간의 주소를 프로그램의 모든 기호에 할당합니다.이 기호는 모두 시작 주소와 크기를 갖는 섹션으로 그룹화됩니다. ld --verbose을 호출하여 사용되는 기본 스크립트를 볼 수 있습니다. 바이너리 섹션과 그 주소는 readelf 또는 objdump과 같은 도구를 사용하여 볼 수 있습니다. readelf -l /bin/cat. 그런 다음 cat /proc/self/maps을 실행하면 /bin/cat이 매핑되는 주소가 일치해야합니다. 따라서 커널 시스템 호출 execve은 다음을 수행합니다. 현재 프로세스의 주소 공간을 인수로 주어진 실행 파일이 매핑 된 새로운 주소 공간으로 바꾸십시오.

물론 코드의 모든 비트에 정적 주소가 할당되어 있으면 공유 라이브러리의 문제를 해결할 수 있습니다. 공유 라이브러리는 위치 독립적 코드를 사용하므로 프로세스 주소 공간의 모든 곳에서 매핑 될 수 있습니다. 여기서 커널은 진행 방법을 결정합니다.

mmap은 (1) 또는 (2) 중 어느 것도 수행하지 않으며, 주소 공간의 지정된 주소에 파일 또는 메모리 일부를 매핑합니다 (또는 커널이 사용할 주소를 결정하게합니다). 실제로 프로그램에서 사용하는 공유 라이브러리를 매핑하는 데 사용됩니다.방법을 보려면 strace /bin/true을 실행하고 이진 파일에서 프로세스의 주소 공간을 생성하기 위해 먼저 execve을 호출하는 방법과 프로그램 로더가 libc 파일을 열고 관련 섹션을 올바른 권한으로 mmap 한 방법을 확인하십시오.

:
execve("/bin/true", ["/bin/true"], [/* 69 vars */]) = 0 
... 
open("/lib/libc.so.6", O_RDONLY|O_CLOEXEC) = 3 
mmap(NULL, 3804080, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f224f351000 
mprotect(0x7f224f4e8000, 2097152, PROT_NONE) = 0 
mmap(0x7f224f6e8000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x197000) = 0x7f224f6e8000 

다음 기사도 읽어 볼 가치가있을 수 있습니다