XNU Architecture Overview
XNU = “X is Not Unix”. Hybrid kernel kết hợp Mach microkernel (Carnegie Mellon), FreeBSD (POSIX), và IOKit (NeXT/Apple).
Ba Layers Của XNU
Layer 1: Mach (osfmk/)
Microkernel core — quản lý low-level primitives.
| Subsystem | Chức năng | Files chính |
|---|---|---|
| IPC | Message passing, port management | ipc/mach_msg.c, ipc/ipc_port.c |
| Tasks/Threads | Execution units, scheduling | kern/task.c, kern/thread.c |
| Virtual Memory | Address spaces, pagers, page fault | vm/vm_map.c, vm/vm_fault.c |
| Scheduling | Thread scheduling, priorities | kern/sched_prim.c |
| Zones | Memory allocator (zalloc) | kern/zalloc.c, kern/kalloc.c |
Key concepts:
- Mach coi mọi thứ là port — communicate qua messages
- Task = container cho resources (address space, ports, threads)
- Thread = đơn vị thực thi
- VM subsystem quản lý virtual ↔ physical mapping
Layer 2: BSD (bsd/)
POSIX compatibility layer — APIs mà userspace programs dùng.
| Subsystem | Chức năng | Files chính |
|---|---|---|
| Process model | pid, fork, exec, wait | kern/kern_proc.c, kern/kern_fork.c |
| Credentials | uid, gid, groups, entitlements | kern/kern_credential.c |
| File Systems | VFS, APFS, HFS+ | vfs/vfs_syscalls.c |
| Networking | Sockets, TCP/IP stack | net/, netinet/ |
| Syscalls | POSIX system call interface | kern/syscalls.master |
| Security | MAC framework, sandbox hooks | security/mac_base.c |
Mối quan hệ với Mach:
- BSD
struct procwrap Machstruct task— 1:1 mapping - BSD process = Mach task + BSD metadata (pid, credentials, file descriptors)
- BSD syscalls = thin wrappers gọi Mach primitives underneath
Layer 3: IOKit (iokit/)
Object-oriented driver framework — restricted C++ (no exceptions, no RTTI).
| Component | Chức năng |
|---|---|
| IOService | Base class cho drivers, service matching |
| IOUserClient | Interface giữa userspace ↔ driver |
| IOMemoryDescriptor | Memory management cho drivers |
| IORegistryEntry | Global registry (device tree) |
| IOWorkLoop | Event-driven work queue |
| OSObject | Reference-counted base class |
Driver hierarchy:
IOService (root)
└── IOPlatformExpertDevice
└── AppleARMPE
└── IOPlatformDevice
├── AppleT8103 (SoC driver)
├── AGXAccelerator (GPU)
├── IOSurface (Graphics buffers)
├── AppleANS3 (NVMe/NAND)
└── AppleUSBHostController (USB)
Cách Ba Layers Tương Tác
Syscall Flow
User Space
════════════════════════════════════════════
Kernel Space
App calls read(fd, buf, len)
│
├─→ SVC #0x80 (syscall instruction)
│
▼
ARM64 Exception Vector (EL1)
│
├─→ BSD syscall handler (bsd/dev/arm/systemcalls.c)
│ └─→ sys_read() [bsd/kern/sys_generic.c]
│ └─→ VFS layer → APFS driver
│ └─→ IOKit storage driver
│
├─→ Mach trap handler (osfmk/arm64/trap.c)
│ └─→ mach_msg_overwrite_trap()
│ └─→ IPC subsystem
│
└─→ Machine-dependent trap
└─→ thread_exception_return()
Memory Allocation Path
Userspace: malloc(size)
→ libsystem_malloc.dylib (userspace allocator)
→ mach_vm_allocate() (if needs pages from kernel)
→ vm_map_enter() (Mach VM)
→ pmap_enter() (ARM64 page tables)
Kernel internal: kalloc(size)
→ kalloc zone lookup
→ zalloc(zone)
→ zone_expand() if empty
→ kernel_memory_allocate()
→ pmap_enter() (map physical page)
IOKit UserClient Call Path
Userspace: IOConnectCallMethod(connection, selector, ...)
→ Mach message to IOKit port
→ is_iokit_rpc() [iokit/Kernel/IOUserClient.cpp]
→ IOUserClient::externalMethod(selector, args)
→ dispatch table lookup
→ Specific driver method
Kernel Startup Sequence
1. iBoot loads kernelcache into memory
2. Kernel entry point: start (osfmk/arm64/start.s)
→ arm_init() — setup MMU, page tables
→ machine_startup() — platform init
→ kernel_bootstrap() — init subsystems:
├── zone_init() — memory zones
├── ipc_init() — Mach IPC
├── vm_mem_bootstrap() — virtual memory
├── clock_init() — timekeeping
└── IOKit init — driver matching
3. BSD init:
├── bsd_init() — BSD subsystem
├── vfs_mountroot() — mount root filesystem
└── bsdinit_task() — launch /sbin/launchd (PID 1)
4. launchd starts system daemons
Kernel Address Space Layout (ARM64 iOS)
0xFFFFFE0000000000 ┐
│ Kernel virtual address space
│
├── Kernelcache (__TEXT, __DATA, ...)
├── Zone maps (kalloc zones)
├── IOKit objects
├── IPC port/message objects
├── Page tables (pmap structures)
└── Device MMIO mappings
│
0xFFFFFFFFFFFFFFFF ┘
KASLR slide: random offset added to base address each boot
Typical: 0xFFFFFE0007004000 + slide (0x000000XXXX000000)
Tài Nguyên
- XNU Source Code
- Apple — Kernel Programming Guide
- Jonathan Levin — macOS and iOS Internals Vol. II (Kernel)
- Tanuj Ravi Rao — XNU Kernel and Darwin