운영 체제의 어떤 프로세스가 ELF(Executable and Linked Format) 파일을 RAM에 로드하는지 알려줄 수 있는 사람이 있습니까?
답변1
사용자는 일반적으로 .o 파일, 일반 실행 파일, 공유 라이브러리의 세 가지 유형의 ELF 파일을 접하게 됩니다. 이러한 파일은 모두 서로 다른 목적으로 사용되지만 내부 구조 파일은 매우 유사합니다.
모든 다른 ELF 파일 유형(a.out 및 기타 여러 실행 파일 형식 포함)에 대한 공통 개념은 섹션 개념입니다. 섹션은 유사한 유형의 정보 모음입니다. 각 섹션은 파일의 일부를 나타냅니다. 예를 들어, 실행 가능한 코드는 항상 다음과 같은 파일에 배치됩니다.. 텍스트;사용자가 초기화한 모든 데이터 변수는. 데이터;초기화되지 않은 데이터는.bss.
실제로 모든 것이 뒤섞여 있는 실행 파일 형식을 설계할 수 있습니다(예:운영 체제). 그러나 실행 파일을 여러 부분으로 분할하면 중요한 이점이 있습니다. 예를 들어, 실행 파일의 실행 부분이 메모리에 로드되면 이러한 메모리 위치를 변경할 필요가 없습니다. 최신 머신 아키텍처에서 메모리 관리자는 메모리의 일부를 읽기 전용으로 표시할 수 있으므로 읽기 전용 메모리 위치를 수정하려고 하면 프로그램이 종료되고 코어가 덤프됩니다. 따라서 특정 메모리 위치가 변경되는 것을 원하지 않는다고 말할 수 있을 뿐만 아니라 읽기 전용 메모리 위치를 수정하려는 모든 시도가 응용 프로그램의 버그를 나타내는 치명적인 오류라고 지정할 수도 있습니다. 즉, 일반적으로 각 메모리 바이트의 읽기 전용 상태를 개별적으로 설정할 수는 없지만 페이지라고 하는 메모리 영역의 보호는 개별적으로 설정할 수 있습니다. i386 아키텍처에서 페이지 크기는 4096바이트이므로 주소 0-4095는 읽기 전용이고 바이트 4096 이상은 쓰기 가능함을 나타낼 수 있습니다.
실행 파일의 모든 실행 부분이 읽기 전용 메모리에 있고 모든 수정 가능한 메모리 위치(예: 변수)가 쓰기 가능한 메모리에 있기를 원한다는 점을 고려하면 실행 파일의 모든 실행 부분을 하나의 섹션으로 그룹화하는 것이 가장 효율적입니다. 메모리 (.text 부분), 수정 가능한 모든 데이터 영역을 다른 메모리 영역(이하.data 섹션).
사용자가 초기화한 데이터 변수와 사용자가 초기화하지 않은 데이터 변수를 더욱 구분합니다. 사용자가 변수의 초기 값을 지정하지 않으면 해당 값을 저장하기 위해 실행 파일에서 공간을 낭비할 필요가 없습니다. 따라서 초기화된 변수는 .data 섹션으로 그룹화되고 초기화되지 않은 변수는 .bss 섹션으로 그룹화됩니다. 이는 파일에서 공간을 차지하지 않기 때문에 특별합니다. 초기화되지 않은 변수에 필요한 공간을 알려줄 뿐입니다.
커널에 실행 파일을 로드하고 실행하도록 요청하면 먼저 이미지 헤더에서 이미지 로드 방법에 대한 단서를 찾습니다. 실행 파일에서 .text 섹션을 찾아서 적절한 메모리 부분에 로드하고 해당 페이지를 읽기 전용으로 표시합니다. 그런 다음 실행 파일에서 .data 섹션을 찾아 이를 사용자의 주소 공간(이번에는 읽기 및 쓰기 메모리)에 로드합니다. 마지막으로 이미지 헤더에서 .bss 섹션의 위치와 크기를 찾아 적절한 메모리 페이지를 사용자의 주소 공간에 추가합니다. 사용자가 .bss의 변수에 대한 초기 값을 지정하지 않더라도 관례적으로 커널은 이 모든 메모리를 0으로 초기화합니다.
보시다시피 실행 파일을 메모리에 로드하는 명령을 실행하는 것은 실제로 커널입니다. 이러한 호출의 결과인 텍스트 부분은 읽기 전용 메모리에 로드되고 데이터 부분은 읽기-쓰기 메모리에 로드됩니다.
답변2
이는 운영 체제에 따라 다릅니다.
예를 들어, GNU Hurd에서 실행 파일은 다음으로 구성됩니다.실행 서버.
보다 일반적인 모놀리식 운영 체제에서는 다음과 같이 수행됩니다.
커널은 실행 가능 링커와 동적 링커를 메모리에 매핑합니다.
동적 링커는 공유 객체를 메모리에 매핑합니다.
Linux 커널 자체는 ELF 파일로 저장됩니다. 이 파일은 GRUB와 같은 부트 로더에 의해 로드됩니다.