8.11. The Dynamic Pager ProgramThe dynamic pager program (/sbin/dynamic_pager) is a user-level process that creates and deletes backing store (swap) files in the designated directory /var/vm/. Notwithstanding its name, dynamic_pager is not a Mach pager and is not involved otherwise in actual paging operations. It is only a manager of swap space for use by the kernel. By default, Mac OS X uses dynamically created, variable-size paging files instead of dedicated swap partitions. The kernel writes data to these paging files in groups of pages (clusters).
dynamic_pager can be instructedthrough the -S command-line optionto use a fixed size for the paging files. In its typical mode of operation, dynamic_pager works with two byte limits: a high-water mark and a low-water mark. When there are fewer bytes free in the swap files than allowed by the high-water mark, dynamic_pager creates a new file and adds it to the swap pool by notifying the kernel. When there are more bytes free in the paging files than allowed by the low-water mark, the kernel sends a notification to dynamic_pager to trigger deletion of a swap file (only one swap file is deleted per notification). Note that the swap file being deleted is likely to have some paged-out pages in itsuch pages are brought into the kernel and eventually paged out to another swap file. The high- and low-water marks can be specified to dynamic_pager through its -H and -L command-line options, respectively. If these limits are not explicitly specified, dynamic_pager calculates them when it starts. The startup script /etc/rc launches dynamic_pager, instructing it whether to encrypt the paging file data (the -E option) and specifying the path prefix of the swap files (/private/var/vm/swapfile by default).
The free page level in the kernel must remain below the maximum_pages_free threshold for at least PF_LATENCY (10) intervals of PF_INTERVAL (3) seconds each before the kernel will send a notification for swap file deletion. # /etc/rc ... if [ ${ENCRYPTSWAP:=-NO-} = "-YES-" ]; then encryptswap="-E" else encryptswap="" fi /sbin/dynamic_pager ${encryptswap} -F ${swapdir}/swapfile When it starts, dynamic_pager determines the high- and low-water marks and other limits based on command-line arguments, free file system space, installed physical memory, and built-in hard limits. Specifically, it establishes the following limits and rules.
dynamic_pager uses the macx_swapon() system call [bsd/vm/dp_backing_store_file.c] to add a file to the backing store. The corresponding removal call is macx_swapoff(), which removes a file from the backing store. The files themselves are created and deleted from the file system by dynamic_pager. Note that dynamic_pager passes a swap file's pathnamerather than a file descriptorto the kernel. The kernel (or rather, dynamic_pager's thread running in the kernel) internally looks up the pathname through namei() to acquire the corresponding vnode. dynamic_pager uses another system callmacx_triggers()to enable or disable swap encryption and to set callbacks for high- and low-water marks. kern_return_t macx_triggers(int hi_water, int low_water, int flags, mach_port_t alert_port); The kernel processes an invocation of macx_triggers() based on the flags argument as follows.
Additionally, macx_triggers() elevates the calling thread's status as follows.
Mac OS X 10.4 supports encryption of the data written by the kernel to the swap files. This feature can be enabled through the "Use secure virtual memory" checkbox in the Security system preference pane. When enabled, the following line is written to /etc/hostconfig: ENCRYPTSWAP=-YES- As we saw earlier, /etc/rc parses /etc/hostconfig, and if the ENCRYPTSWAP variable is set to YES, dynamic_pager is launched with the -E option. The kernel uses a form of the AES encryption algorithm for encrypting swap file data. Even without swap file encryption, the kernel prevents user-space programs from directly reading swap data by using a special implementation of the read() system call. The vn_read() and vn_rdwr_64() internal functions in the VFS layer check the vnode they are dealing with to see if it corresponds to a swap file. If so, these functions call vn_read_swapfile() [bsd/vfs/vfs_vnops.c] instead of the usual internal read routine. // bsd/vfs/vfs_vnops.c ... if (vp->v_flag & VSWAP) { // special case for swap files error = vn_read_swapfile(vp, uio); } else { error = VNOP_READ(vp, uio, ioflag, &context); } ... vn_read_swapfile() reads zero-filled pages[16] instead of the actual contents of the file.
|