You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Mac系统下如何将两个子进程绑定到同一处理器以测量上下文切换成本?

How to Bind Processes to a Single CPU on macOS (Instead of 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 -lmach flag. 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 calling bind_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.ncpu in 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

火山引擎 最新活动