Mac系统下如何将两个子进程绑定到同一处理器以测量上下文切换成本?
sched_setaffinity()) Got it, the problem you're hitting is that sched_setaffinity() is a Linux-specific system call—macOS's BSD/Mach-based kernel uses a different set of APIs for controlling CPU affinity. Let's walk through how to fix this so you can bind your two test processes to the same CPU core for accurate context switch measurements.
Why Your Current Code Fails on macOS
macOS doesn't implement the Linux sched_* affinity calls. The error you're seeing (undefined symbol for _sched_setaffinity) is the linker telling you it can't find that Linux-specific function in macOS's system libraries.
macOS Alternative: Mach Task Policy API
To bind an entire process to a specific CPU core on macOS, you'll use the task_policy_set() function from the Mach API. This lets you set the CPU_SET policy for a task (process) to restrict it to a subset of available cores.
Working Code Example
Here's a drop-in replacement for your sched_setaffinity() call, plus a reusable function to bind a process to a specific CPU:
#define _GNU_SOURCE #include <stdio.h> #include <unistd.h> #include <sys/time.h> #include <sys/wait.h> #include <mach/mach.h> #include <mach/thread_policy.h> // Bind the current process to the specified CPU core int bind_to_cpu(int cpu_num) { task_t task = mach_task_self(); cpu_set_t cpuset; CPU_ZERO(&cpuset); CPU_SET(cpu_num, &cpuset); kern_return_t result = task_policy_set( task, CPU_SET_POLICY, (task_policy_t)&cpuset, CPU_SET_POLICY_COUNT ); if (result != KERN_SUCCESS) { fprintf(stderr, "Failed to bind to CPU %d: %s\n", cpu_num, mach_error_string(result)); return -1; } return 0; } int main() { // Bind parent process to CPU 0 first if (bind_to_cpu(0) != 0) { return 1; } // Fork your two child processes here... pid_t pid1 = fork(); if (pid1 == 0) { // Child 1: re-bind to CPU 0 (forked processes inherit parent's affinity, but explicit is safe) bind_to_cpu(0); // Your child process logic here (pipe read/write for context switch test) return 0; } pid_t pid2 = fork(); if (pid2 == 0) { // Child 2: bind to the same CPU 0 bind_to_cpu(0); // Your child process logic here return 0; } // Wait for children to finish waitpid(pid1, NULL, 0); waitpid(pid2, NULL, 0); return 0; }
Key Notes
- Header Files: You need to include
<mach/mach.h>and<mach/thread_policy.h>for the Mach API types and functions. - Compilation: When compiling, you must link against the Mach library with the
-lmachflag. Your compile command should look like:gcc context_switch.c -o context_switch -lm -lmach - Inheritance: When you
fork()a process, the child inherits the parent's CPU affinity settings. However, explicitly callingbind_to_cpu()in each child ensures consistency, especially if you modify the parent's affinity later. - CPU Numbering: macOS cores are numbered starting from 0 (just like Linux). You can check the number of available cores with
sysctl hw.ncpuin the terminal.
For Thread-Level Affinity (If Needed)
If you ever need to bind individual threads instead of entire processes, use thread_policy_set() with the same CPU_SET_POLICY—just replace mach_task_self() with mach_thread_self() and adjust the policy parameters accordingly.
This setup will ensure both of your test processes run exclusively on the same CPU core, letting you accurately measure context switch overhead, just like the lmbench approach.
内容的提问来源于stack exchange,提问作者jin zhenhui




