fork() + exec()를 넘어
1 hour ago
1
- spawn templates는 같은 실행 파일을 반복 실행하는 애플리케이션에서 커널이 실행 파일 정보를 캐시해 이후 프로세스 시작을 빠르게 하려는 Linux 커널용 프로세스 생성 제안
- fork() 는 자식 프로세스를 위해 메모리를 포함한 전체 프로세스 상태를 복사해야 하고, 바로 뒤따르는 exec()가 그 메모리를 폐기하는 경우가 많아 기존 패턴의 비효율 발생
- spawn_template_create() 는 execfd 또는 절대 경로 filename 중 하나로 실행 파일을 지정해 템플릿 파일 디스크립터를 반환하고, 커널은 해당 파일을 열어 빠른 실행에 필요한 정보 캐시
- spawn_template_spawn() 은 일반 fork()/exec() 경로와 가까운 방식으로 동작하며 새 파일 실행 시 적용되는 검사는 유지하고, 커버레터의 벤치마크는 약 2% 개선 기록 {p:2}
- pidfd 기반 빈 프로세스 생성과 pidfd_config() 구성이 더 나은 접근으로 평가되며, 목표는 사용자 공간의 posix_spawn() 구현 지원
Unix 프로세스 생성 모델의 한계
- Unix 초기부터 fork()는 부모의 복사본으로 자식 프로세스를 만들고, exec()는 현재 프로세스의 자리에 새 프로그램을 실행하는 핵심 프로세스 지향 시스템 호출
- Linux 커널에서는 같은 핵심 기능이 clone()과 execve()로 더 잘 알려져 있음
- 이 프로세스 생성 모델에는 우아함과 단점이 모두 있으며, Li Chen의 spawn templates 제안은 현재 형태로 Linux 커널에 수용되지 않을 예정이지만 미래의 새 프로세스 생성 원시 연산으로 이어질 수 있음
- fork()는 자식 프로세스를 만들기 위해 메모리를 포함한 전체 프로세스 상태를 복사해야 하는 상대적으로 비싼 시스템 호출
- 수년간 여러 최적화가 있었지만 fork()는 근본적으로 비용이 큰 작업
- fork() 호출 뒤에 exec()가 바로 이어지는 경우가 많고, exec()는 자식을 위해 복사된 메모리를 모두 폐기
- vfork() 같은 최적화 시도가 있었지만 fork() 다음 exec() 패턴은 여전히 가능한 수준보다 더 비싼 구조
스폰 템플릿(Spawn templates)
- Li Chen의 패치 세트는 fork()와 exec() 패턴을 최적화하기 위해 같은 실행 파일을 반복 실행하는 애플리케이션에 초점
- 예시로 저장소 콘텐츠 정보를 얻기 위해 Git을 반복 실행해야 하는 프로그램이 해당 사례
- 이런 경우 프로그램은 여러 실행에 설정 비용을 분산하기 위해 템플릿을 만들고, 그 템플릿으로 호출 가속
- 템플릿 생성은 spawn_template_create() 시스템 호출 사용
- int spawn_template_create(struct spawn_template_create_args *args, size_t args_size); 형태의 시그니처
- 이 호출은 실행 파일 템플릿을 나타내는 파일 디스크립터 반환
- 실행 파일은 파일 디스크립터 execfd 또는 절대 경로 filename 중 하나로 지정해야 하며, 둘을 동시에 사용할 수 없음
- 커널은 지정된 파일을 열고, 이후 그 파일을 더 빠르게 실행하는 데 필요한 여러 정보 캐시
- 각 실행은 서로 다른 인수, 환경, 파일 디스크립터 변경, 신호 처리 변경을 가질 수 있음
- 구체적인 실행 정보는 spawn_template_spawn_args 구조체에 배치
- argv는 프로그램에 전달할 인수 목록을 가리키는 포인터
- envp는 프로그램 환경을 가리키는 포인터
- actions는 파일 디스크립터와 신호 처리 변경을 전달하는 spawn_template_action 배열 포인터
- spawn_template_action은 type, flags, fd, newfd, arg 필드로 구성
- 자식에서 파일 디스크립터 4를 닫아야 하는 경우 type은 SPAWN_TEMPLATE_ACTION_CLOSE, fd는 4로 설정
- 다른 액션은 파일 디스크립터 복제, 파일 열기, 작업 디렉터리 변경, 신호 처리 변경 지원
- 실행 정보가 채워진 뒤 spawn_template_spawn()으로 새 프로세스 실행
- int spawn_template_spawn(int template_fd, struct spawn_template_spawn_args *args, int args_size); 형태의 시그니처
- 내부 동작은 일반 fork()/exec() 경로에 가까운 방식
- 새 파일 실행 때 적용되는 일반 검사는 모두 그대로 유지
- 템플릿에 캐시된 정보로 전체 생성 흐름의 속도 향상
- 커버레터의 벤치마크 결과는 약 2% 개선이며, 예상 패턴에 맞는 애플리케이션에는 차이가 될 수 있는 수치 {p:2}
posix_spawn()을 향해
- Mateusz Guzik은 “전체 fork + exec 관용구는 끔찍하며 퇴출되어야 한다”는 평가
- 패치 세트의 이상한 지점은 fork() 부분을 그대로 둔다는 점이며, 비용 대부분이 거기에 있다는 판단
- 최적화는 현재 프로세스 복사를 제거하고 “깨끗한(pristine) 프로세스”를 만드는 방식이어야 함
- Christian Brauner는 exec를 위한 builder API 구상이 “그렇게 이상한 것은 아니다”라는 입장
- 다만 새 API는 기존 pidfd 추상화 위에 구축하는 접근을 선호
- 구체적 세부 사항은 없지만 pidfd_open()에 빈 프로세스를 만드는 옵션을 추가하는 방식이 올바른 접근
- 이후 새 pidfd_config() 시스템 호출을 여러 번 호출해 환경, 실행할 이미지 등 원하는 설정을 새 프로세스에 적용
- pidfd_config()는 fsconfig()와 유사한 역할
- 새 인터페이스의 중요한 목표는 사용자 공간에서 posix_spawn() 구현 지원
- posix_spawn()은 fork()/exec() 패턴의 대체재에 적합
- 현재 구현은 내부에서 fork()와 exec()를 숨기며, 네이티브 구현은 그 구조와 다른 구현
- Li Chen은 Brauner가 넓게 그린 API가 더 나아 보인다는 데 동의했고, 향후 작업을 그쪽으로 진행할 계획
- Linux 커널에는 spawn templates가 들어가지 않지만, 향후 작업이 결실을 맺으면 Linux가 적절한 posix_spawn() 구현을 갖게 될 수 있음
-
Homepage
-
개발자
- fork() + exec()를 넘어