
macOS 및 iOS용 Mach, FreeBSD 및 IOKit을 결합한 하이브리드 커널입니다. x86_64 및 ARM64에서 핵심 OS 서비스, 드라이버 프레임워크 및 보안 정책 시행을 제공합니다.
XNU 커널은 macOS 및 iOS 운영 체제에서 사용되는 Darwin 운영 체제의 일부입니다. XNU는 X is Not Unix의 약어입니다. XNU는 Carnegie Mellon University에서 개발된 Mach 커널과 FreeBSD의 구성 요소, 그리고 IOKit이라고 하는 드라이버 작성을 위한 C++ API를 결합한 하이브리드 커널입니다. XNU는 단일 프로세서 및 다중 프로세서 구성 모두에 대해 x86_64 및 ARM64에서 실행됩니다.
config - 지원 아키텍처 및 플랫폼에 대한 내보내진 API 구성SETUP - 커널 구성, 버전 관리 및 kextsymbol 관리를 위한 기본 도구 세트EXTERNAL_HEADERS - 빌드 시 의존성 순환을 피하기 위해 다른 프로젝트에서 가져온 헤더. 이러한 헤더는 소스가 업데이트될 때 정기적으로 동기화되어야 합니다.libkern - 드라이버 및 kext 처리를 위한 C++ IOKit 라이브러리 코드libsa - 시작을 위한 커널 부트스트랩 코드libsyscall - 사용자 공간 프로그램을 위한 시스템 콜 라이브러리 인터페이스libkdd - 커널 청크 데이터와 같은 커널 데이터를 구문 분석하기 위한 사용자 라이브러리 소스makedefs - 커널 빌드를 위한 최상위 규칙 및 정의osfmk - Mach 커널 기반 서브시스템pexpert - 인터럽트 처리, 원자 연산 등과 같은 플랫폼별 코드security - 강제 접근 검사 정책 인터페이스 및 관련 구현bsd - BSD 서브시스템 코드tools - 커널 테스트, 디버깅 및 프로파일링을 위한 유틸리티 세트DEVELOPMENT 커널 빌드xnu make 시스템은 인수로 KERNEL_CONFIGS 및 ARCH_CONFIGS 변수를 기반으로 커널을 빌드할 수 있습니다. 구문은 다음과 같습니다:```text
make SDKROOT= ARCH_CONFIGS= KERNEL_CONFIGS=
위치:
* `<sdkroot>`: 디스크에 있는 macOS SDK 경로입니다. (기본값: `/`)
* `<variant>`: `debug`, `development`, `release`, `profile` 중 하나이며, 커널 코드 전체에서 컴파일 플래그와 어서트(assert)를 구성합니다.
* `<arch>`: 빌드할 아키텍처를 지정합니다. (예: `X86_64`)
실행 중인 OS와 동일한 아키텍처로 커널을 빌드하려면 다음을 입력하세요.```text
make SDKROOT=macosx.internal
또한, ARCH_CONFIGS를 통한 아키텍처 구성과 KERNEL_CONFIGS를 통한 커널 구성이 지원됩니다.```text
make SDKROOT=macosx.internal ARCH_CONFIGS=X86_64 KERNEL_CONFIGS=DEVELOPMENT
make SDKROOT=macosx.internal ARCH_CONFIGS=X86_64 KERNEL_CONFIGS="RELEASE DEVELOPMENT DEBUG"
> 참고: 기본적으로 아키텍처는 빌드 머신의 아키텍처로 설정되며, 기본 커널 구성은 `DEVELOPMENT`용으로 빌드하도록 설정됩니다.
이렇게 하면 부팅 가능한 이미지, kernel.[config], 그리고 심볼이 포함된 커널 바이너리인 kernel.[config].unstripped도 생성됩니다.
커널을 DSTROOT에 설치하려면 `install_kernels` 타겟을 사용하세요:```text
make install_kernels DSTROOT=/tmp/xnu-dst
더 만족스러운 커널 디버깅 경험을 위해, 모든 지역 변수와 인수에 접근할 수 있지만 DEBUG 커널의 모든 추가 검사 없이, make 명령에 다음과 같은 내용을 추가하십시오:```text CFLAGS_DEVELOPMENTARM64="-O0 -g -DKERNEL_STACK_MULTIPLIER=2" CXXFLAGS_DEVELOPMENTARM64="-O0 -g -DKERNEL_STACK_MULTIPLIER=2"
`DEVELOPMENT`와 `ARM64`를 적절한 빌드 및 플랫폼으로 바꾸는 것을 잊지 마세요.
> 추가 플래그: `EXTRA_CFLAGS` 빌드 설정을 사용하여 명령줄에서 C 컴파일러에 추가 플래그를 전달할 수 있습니다. 이 플래그는 기본 `CFLAGS`에 추가되며, 설정의 기본값은 빈 문자열입니다.
>
> 이 설정을 사용하면 예를 들어 전처리기 매크로로 보호되는 디버깅 코드를 선택적으로 활성화할 수 있습니다. 사용 예...
>
> ```text
> make SDKROOT=macosx.internal PRODUCT_CONFIGS=j314s
> EXTRA_CFLAGS='-DKERNEL_STACK_MULTIPLIER=2'
> ```
* RELEASE 커널 설정으로 빌드하려면
```text
make KERNEL_CONFIGS=RELEASE SDKROOT=/path/to/SDK
```
### FAT 커널 바이너리 빌드
환경 변수나 make 명령 실행 시 아키텍처를 정의하세요.```text
make ARCH_CONFIGS="X86_64" exporthdrs all
XNU 빌드 시스템은 선택적으로 색상 서식이 적용된 빌드 출력을 생성할 수 있습니다. 이 기능을 활성화하려면 XNU_LOGCOLORS 환경 변수를 y로 설정하거나, make 명령어에 LOGCOLORS=y를 전달하면 됩니다.
xnu 버전은 SDK 또는 KDK의 System/Library/Extensions/System.kext/Info.plist 파일에 있는 CFBundleVersion을 읽어 파생됩니다.
이 값은 환경 변수나 make 명령줄에서 RC_DARWIN_KERNEL_VERSION 변수를 설정하여 사용자 정의할 수 있습니다.
자세한 내용은 doc/building/xnu_version.md를 참조하십시오.
기본적으로 설치 단계에서 DWARF 디버그 정보 저장소가 생성됩니다. 이는 kernel.development.<variant>.dSYM이라는 "번들"입니다.
기존의 STABS 디버그 정보 형식(디버그 정보가 kernel.development.unstripped 이미지에 포함됨)을 선택하려면 BUILD_STABS 환경 변수를 설정하십시오.```sh
export BUILD_STABS=1
make
## 커널 캐시 빌드하기
xnu 커널을 테스트하려면, kext와 커널을 단일 부팅 이미지로 연결하는 kernelcache를 빌드해야 합니다.
kernelcache를 빌드하려면 다음 메커니즘을 사용할 수 있습니다:
* `kextd`를 사용한 자동 kernelcache 생성.
kextd 데몬은 `/System/Library/Extensions` 디렉토리의 변경 사항을 계속 감시합니다.
따라서 새 커널을 다음과 같이 설정할 수 있습니다.
```text
cp BUILD/obj/DEVELOPMENT/X86_64/kernel.development /System/Library/Kernels/
touch /System/Library/Extensions
ps -e | grep kextd
```
* `kextcache`를 수동으로 호출하여 새 kernelcache를 빌드합니다.
```text
kextcache -q -z -a x86_64 -l -n -c /var/tmp/kernelcache.test -K /var/tmp/kernel.test /System/Library/Extensions
```
## 대상 머신에서 커널 캐시 부팅하기
개발 커널과 iBoot는 부트 인수를 구성하여 테스트 커널을 안전하게 부팅하고, 문제가 발생하면 이전에 사용된 kernelcache로 안전하게 되돌릴 수 있도록 지원합니다.
이러한 설정을 얻기 위한 단계는 다음과 같습니다:
1. `kextcache` 명령어를 사용하여 `/kernelcache.test`로 커널 캐시를 생성합니다.
2. 기존 부트 구성을 대체 파일로 복사합니다.
```sh
cp /Library/Preferences/SystemConfiguration/com.apple.Boot.plist /next_boot.plist
```
3. 설정에 맞게 kernelcache와 boot-args를 업데이트합니다.
```sh
plutil -insert "Kernel Cache" -string "kernelcache.test" /next_boot.plist
plutil -replace "Kernel Flags" -string "debug=0x144 -v kernelsuffix=test " /next_boot.plist
```
4. 새 구성을 `/Library/Preferences/SystemConfiguration/`에 복사합니다.
```sh
cp /next_boot.plist /Library/Preferences/SystemConfiguration/boot.plist
```
5. 새 구성으로 볼륨을 bless합니다.
```text
sudo -n bless --mount / --setBoot --nextonly --options "config=boot"
```
`--nextonly` 플래그는 `boot.plist` 구성을 한 번의 부팅에만 사용하도록 지정합니다.
따라서 커널 패닉이 발생하면 전원을 재부팅하여 원래 커널로 쉽게 복구할 수 있습니다.
## 태그 및 cscope 생성하기
빌드 환경을 설정하고 최상위 디렉토리에서 다음을 실행합니다:
make tags # 대소문자 구분 볼륨에서 ctags 및 etags를 빌드하고, 대소문자 미구분 볼륨에서는 ctags만 빌드합니다.
make TAGS # etags를 빌드합니다.
make cscope # cscope 데이터베이스를 빌드합니다.
## XNU에서 새 헤더 파일 설치하기
XNU는 다음 위치에 헤더 파일을 설치합니다:
a. $(DSTROOT)/System/Library/Frameworks/Kernel.framework/Headers
b. $(DSTROOT)/System/Library/Frameworks/Kernel.framework/PrivateHeaders
c. $(DSTROOT)/usr/include/
d. $(DSTROOT)/usr/local/include/
e. $(DSTROOT)/System/DriverKit/usr/include/
f. $(DSTROOT)/System/Library/Frameworks/IOKit.framework/Headers
g. $(DSTROOT)/System/Library/Frameworks/IOKit.framework/PrivateHeaders
h. $(DSTROOT)/System/Library/Frameworks/System.framework/PrivateHeaders
`Kernel.framework`는 커널 확장에서 사용됩니다.\
`System.framework`, `/usr/include` 및 `/usr/local/include`는 사용자 수준 애플리케이션에서 사용됩니다.\
`IOKit.framework`는 IOKit 사용자 공간 클라이언트에서 사용됩니다.\
`/System/DriverKit/usr/include`는 사용자 공간 드라이버에서 사용됩니다.\
프레임워크의 `PrivateHeaders`에 있는 헤더 파일은 **Apple 내부 개발**에만 사용할 수 있습니다.
헤더 파일이 포함된 디렉토리에는 다른 위치에 설치해야 할 파일 목록을 생성하는 Makefile이 있어야 합니다.
디렉토리에 첫 번째 헤더 파일을 추가하는 경우, `xnu/bsd/sys/Makefile`과 유사한 Makefile을 만들어야 합니다.
헤더 파일을 설치하려는 위치에 따라 올바른 파일 목록에 헤더 파일을 추가합니다.
각 파일 목록에서 헤더 파일이 설치되는 기본 위치는 다음과 같습니다:
a. `DATAFILES` : 사용자 수준에서 헤더 파일을 사용할 수 있도록 하려면 -
`$(DSTROOT)/usr/include`
`$(DSTROOT)/System/Library/Frameworks/System.framework/PrivateHeaders`
b. `DRIVERKIT_DATAFILES` : DriverKit 사용자 공간 드라이버에서 헤더 파일을 사용할 수 있도록 하려면 -
`$(DSTROOT)/System/DriverKit/usr/include`
c. `PRIVATE_DATAFILES` : 사용자 수준에서 Apple 내부에서 헤더 파일을 사용할 수 있도록 하려면 -
`$(DSTROOT)/System/Library/Frameworks/System.framework/PrivateHeaders`
d. `EMBEDDED_PRIVATE_DATAFILES` : macOS에서는 사용자 수준에서 `EXTRA_DATAFILES`로, 임베디드 OS에서는 `EXTRA_PRIVATE_DATAFILES`로 Apple 내부에서 사용할 수 있도록 하려면 -
`$(DSTROOT)/usr/include` (`EXTRA_DATAFILES`)
`$(DSTROOT)/usr/local/include` (`EXTRA_PRIVATE_DATAFILES`)
e. `KERNELFILES` : 커널 수준에서 헤더 파일을 사용할 수 있도록 하려면 -
`$(DSTROOT)/System/Library/Frameworks/Kernel.framework/Headers`
`$(DSTROOT)/System/Library/Frameworks/Kernel.framework/PrivateHeaders`
f. `PRIVATE_KERNELFILES` : Apple 내부에서 커널 확장을 위해 헤더 파일을 사용할 수 있도록 하려면 -
`$(DSTROOT)/System/Library/Frameworks/Kernel.framework/PrivateHeaders`
g. `MODULEMAPFILES` : 사용자 수준에서 모듈 맵 파일을 사용할 수 있도록 하려면 -
`$(DSTROOT)/usr/include`