본문으로 이동
  • 현재 모든 문서는 작성 중입니다. 보시는 데 불편함이 있더라도 양해 부탁드립니다.

운영체제 기본/Linux/x86-64/BIOS 부팅/PID 1 생성: 두 판 사이의 차이

~ldmsys
역링크 갱신 완료 후 불필요한 호환 span id 제거
공통 둘러보기와 상하단 문서 이동 틀 적용
1번째 줄: 1번째 줄:
[[운영체제 기본|운영체제 기본 목차]] · [[운영체제 기본/x86-64 Linux의 BIOS 부팅|부팅 목차]]
{{문서 이동
|이전=← 이전 문서<br />[[운영체제 기본/x86-64 Linux의 BIOS 부팅/커널 초기화|커널 초기화]]
|목차=[[운영체제 기본/x86-64 Linux의 BIOS 부팅|BIOS 부팅 목차]]
|다음=다음 문서 →<br />[[운영체제 기본/x86-64 Linux의 BIOS 부팅/루트 파일시스템과 init 선택|루트 파일시스템과 init 선택]]
}}


Linux v6.12에서 부트 태스크는 <code>rest_init()</code>에 도달하면 PID 1과 <code>kthreadd</code>를 만든다. PID 1은 커널의 나머지 초기화를 맡고, 기존 부트 태스크인 PID 0은 idle 태스크로 남는다.
Linux v6.12에서 부트 태스크는 <code>rest_init()</code>에 도달하면 PID 1과 <code>kthreadd</code>를 만든다. PID 1은 커널의 나머지 초기화를 맡고, 기존 부트 태스크인 PID 0은 idle 태스크로 남는다.
35번째 줄: 39번째 줄:
<code>kernel_init_freeable()</code>에서 돌아온 뒤에도 비동기 초기화의 완료를 기다린다. 그래야 아직 실행 중인 초기화 코드가 있는데 그 코드를 담은 메모리를 먼저 해제하는 일이 없다. 이후 초기화용 메모리를 정리하고, 다음 장에서 다룰 init 선택과 exec로 진행한다.<ref name="main"/>
<code>kernel_init_freeable()</code>에서 돌아온 뒤에도 비동기 초기화의 완료를 기다린다. 그래야 아직 실행 중인 초기화 코드가 있는데 그 코드를 담은 메모리를 먼저 해제하는 일이 없다. 이후 초기화용 메모리를 정리하고, 다음 장에서 다룰 init 선택과 exec로 진행한다.<ref name="main"/>


'''이전:''' [[운영체제 기본/x86-64 Linux의 BIOS 부팅/커널 초기화|커널 초기화]] · '''다음:''' [[운영체제 기본/x86-64 Linux의 BIOS 부팅/루트 파일시스템과 init 선택|루트 파일시스템과 init 선택]]


== 참고 문헌 ==
== 참고 문헌 ==
<references />
<references />
{{문서 이동
|이전=← 이전 문서<br />[[운영체제 기본/x86-64 Linux의 BIOS 부팅/커널 초기화|커널 초기화]]
|목차=[[운영체제 기본/x86-64 Linux의 BIOS 부팅|BIOS 부팅 목차]]
|다음=다음 문서 →<br />[[운영체제 기본/x86-64 Linux의 BIOS 부팅/루트 파일시스템과 init 선택|루트 파일시스템과 init 선택]]
}}
{{운영체제 기본 둘러보기}}

2026년 11월 1일 (일) 00:15 판

틀:문서 이동

Linux v6.12에서 부트 태스크는 rest_init()에 도달하면 PID 1과 kthreadd를 만든다. PID 1은 커널의 나머지 초기화를 맡고, 기존 부트 태스크인 PID 0은 idle 태스크로 남는다.

PID 0·PID 1·kthreadd의 역할

rest_init()은 먼저 user_mode_thread(kernel_init, NULL, CLONE_FS)를 호출해 PID 1을 만든다. 이어 kernel_thread()로 kthreadd(PID 2)를 만든다. 기존 부트 태스크는 스케줄러를 거쳐 cpu_startup_entry()의 idle 경로로 진행한다.[1]

즉 rest_init()이 자기 스택에서 평범하게 kernel_init()을 호출하고 그대로 init이 되는 구조가 아니다. 새 태스크에는 별도 실행 문맥이 생긴다. 실행 상태와 자원의 구분은 프로세스와 스레드에서 설명한다. 이후 어떤 태스크가 CPU를 사용할지는 스케줄링에 따라 달라진다. PID 1은 새로 생겼지만 기존 PID 0이 사라진 것은 아니다.[2]

PID 0: start_kernel -> rest_init -----------------> idle
                         |
                         +-- create PID 1 -> kernel_init
                         |
                         +-- create PID 2 -> kthreadd

user_mode_thread와 kernel_init

함수 이름의 user mode를 “이 호출 직후 CPU가 사용자 모드가 된다”로 읽으면 안 된다. user_mode_thread()는 시작 함수와 인자를 kernel_clone_args에 담아 kernel_clone()에 넘긴다. 이 경우 시작 함수는 커널 내부 함수인 kernel_init()이다.[2]

kernel_thread()와의 중요한 차이는 kthread 속성을 설정하지 않는다는 점이다. 계속 커널 스레드로 남을 태스크와 나중에 사용자 실행 이미지를 갖게 될 태스크의 생성 방식이 구별된다. 실제로 kernel_execve()는 PF_KTHREAD가 설정된 태스크의 호출을 거부한다. 따라서 “PID 1은 처음에 커널 코드를 실행한다”는 설명은 맞지만, 이를 곧바로 “일반 커널 스레드를 만든 뒤 exec한다”로 바꾸면 v6.12 구현과 어긋난다.[2][3]

권한 수준과 태스크 종류도 같은 말이 아니다. 사용자 프로그램을 실행할 태스크 역시 커널에 진입해 커널 코드를 실행할 수 있다. PID 1은 아직 첫 사용자 실행 이미지를 얻기 전이다. 보호 경계 자체는 보호를 참고한다.

kthreadd 생성과 PID 1의 대기

PID 1이라는 번호를 얻도록 init을 먼저 생성하지만, init이 진행하며 사용할 커널 스레드 생성 기반인 kthreadd는 그다음 만들어진다. 단순히 소스에서 생성 호출을 두 줄 연속 적었다고 새 태스크들이 반드시 원하는 순서로 실행되는 것은 아니다.[1]

이 의존 관계를 표현하는 것이 kthreadd_done completion이다. completion은 한쪽이 작업 완료를 알리고 다른 쪽이 그 사건을 기다리는 동기화 수단이다. 조건을 기다리는 작업과 깨우기의 관계는 동시성과 연결된다. kernel_init()은 시작하자마자 기다리고, rest_init()은 kthreadd 준비 후 완료를 알린다. “태스크를 먼저 만들었다”와 “필요한 기반이 준비되었으니 진행해도 된다”를 분리한 것이다.[1]

PID 1의 커널 초기화와 initcall

대기가 끝나면 kernel_init_freeable()이 SMP와 나머지 초기화를 진행한다. 여기에는 do_basic_setup()을 통한 initcall 실행도 포함된다.[1]

initcall은 부팅 중 실행할 초기화 함수를 정해진 단계에 등록하는 방식이다. 소스의 각 부분이 등록한 함수들을 초기화 경로가 순회하며 실행하므로, start_kernel() 안에 모든 드라이버의 함수 이름이 직접 나열될 필요는 없다. 예를 들어 rootfs에 initramfs를 푸는 populate_rootfs()도 rootfs_initcall로 등록되어 있다.[1][4]

kernel_init_freeable()에서 돌아온 뒤에도 비동기 초기화의 완료를 기다린다. 그래야 아직 실행 중인 초기화 코드가 있는데 그 코드를 담은 메모리를 먼저 해제하는 일이 없다. 이후 초기화용 메모리를 정리하고, 다음 장에서 다룰 init 선택과 exec로 진행한다.[1]


참고 문헌

  1. ↑ 1.0 1.1 1.2 1.3 1.4 1.5 v6.12 init/main.c, rest_init.
  2. ↑ 2.0 2.1 2.2 v6.12 kernel/fork.c, user_mode_thread, kernel_thread, kernel_clone.
  3. ↑ v6.12 fs/exec.c, kernel_execve.
  4. ↑ v6.12 init/initramfs.c, populate_rootfs 및 rootfs_initcall 등록.

틀:문서 이동