운영체제 기본/Linux의 ELF 로딩/execve와 실행 이미지 교체: 두 판 사이의 차이

BIOS 부팅·i8042 키보드 각론의 새 문서명으로 내부 링크 갱신
PID 1 전용 실행 설명을 BIOS 부팅 장으로 이동
 
71번째 줄: 71번째 줄:
<code>point_of_no_return</code>은 실제 주소 공간 교체보다 먼저 설정된다. 이미 다른 스레드와 실행 상태를 정리하기 시작했다면 단순히 이전 코드로 돌아갈 수 없기 때문이다. 이 경계를 넘은 뒤 로딩에 실패하면 커널은 기존 프로그램으로 정상 복귀하지 않고 프로세스를 종료시킨다. 따라서 실행 교체는 모든 단계에서 되돌릴 수 있는 작업은 아니다.<ref name="exec" />
<code>point_of_no_return</code>은 실제 주소 공간 교체보다 먼저 설정된다. 이미 다른 스레드와 실행 상태를 정리하기 시작했다면 단순히 이전 코드로 돌아갈 수 없기 때문이다. 이 경계를 넘은 뒤 로딩에 실패하면 커널은 기존 프로그램으로 정상 복귀하지 않고 프로세스를 종료시킨다. 따라서 실행 교체는 모든 단계에서 되돌릴 수 있는 작업은 아니다.<ref name="exec" />


== 새 프로그램의 시작과 PID 1의 실행 ==
== 새 프로그램의 시작 ==


로딩이 끝나면 ELF 로더는 새 프로그램의 진입 주소와 초기 스택 주소를 사용자 레지스터 상태에 설정한다. 커널 내부 함수들은 반환할 수 있지만, 사용자 모드로 나갈 때 실행할 위치는 이미 바뀌었다. 이것이 “<code>execve()</code>는 성공하면 반환하지 않는다”는 말의 의미다. 이전 프로그램의 호출 다음 줄이 아니라 새 프로그램의 시작 코드가 실행된다.<ref name="elf" />
로딩이 끝나면 ELF 로더는 새 프로그램의 진입 주소와 초기 스택 주소를 사용자 레지스터 상태에 설정한다. 커널 내부 함수들은 반환할 수 있지만, 사용자 모드로 나갈 때 실행할 위치는 이미 바뀌었다. 이것이 “<code>execve()</code>는 성공하면 반환하지 않는다”는 말의 의미다. 이전 프로그램의 호출 다음 줄이 아니라 새 프로그램의 시작 코드가 실행된다.<ref name="elf" />
부팅 중 PID 1의 프로그램을 실행할 때도 같은 로더를 사용한다. 어떤 파일을 실행할지는 [[운영체제 기본/x86-64 Linux의 BIOS 부팅/루트 파일시스템과 init 선택|루트 파일시스템과 init 선택]]에서 다룬다. 선택된 파일을 실행하는 <code>run_init_process()</code>는 <code>kernel_execve()</code>를 호출한다. 이 함수는 커널에 있는 인수 문자열을 복사한다는 차이가 있지만, <code>bprm_execve()</code>에서 일반 실행 경로와 합쳐져 같은 binfmt와 ELF 로더를 사용한다.<ref name="exec" /><ref>Linux v6.12, [https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/init/main.c?h=v6.12 init/main.c]. <code>run_init_process()</code>와 <code>kernel_init()</code>.</ref>
일반 <code>execve()</code>는 시스템 콜의 사용자 복귀 경로로 나가고, PID 1의 첫 실행은 초기 태스크의 커널 함수가 반환하는 경로에서 사용자 모드로 나간다. 두 경우 모두 로더가 준비한 새 주소 공간과 레지스터로 실행을 시작한다.<ref>Linux v6.12, [https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/x86/kernel/process.c?h=v6.12 arch/x86/kernel/process.c], <code>ret_from_fork()</code>.</ref>


이제 실행 파일은 열렸고 ELF 로더도 선택되었다. 다음 [[운영체제 기본/Linux의 ELF 로딩/ELF 세그먼트와 주소 공간|ELF 세그먼트와 주소 공간]]에서는 로더가 프로그램 헤더를 읽어 코드와 데이터를 가상 주소 공간에 배치하는 방법을 살펴본다.
이제 실행 파일은 열렸고 ELF 로더도 선택되었다. 다음 [[운영체제 기본/Linux의 ELF 로딩/ELF 세그먼트와 주소 공간|ELF 세그먼트와 주소 공간]]에서는 로더가 프로그램 헤더를 읽어 코드와 데이터를 가상 주소 공간에 배치하는 방법을 살펴본다.