suricata之进程亲和性(绑定cpu核心)

文件:util-affinity.h util-affinity.c

#ifndef __UTIL_AFFINITY_H__
#define __UTIL_AFFINITY_H__
#include "suricata-common.h"
#include "conf.h"

#if defined OS_FREEBSD
#include 
#include 
#include 
#include 
#include 
#define cpu_set_t cpuset_t
#elif defined __OpenBSD__
#include 
#include 
#include 
#elif defined OS_DARWIN
#include 
#include 
#include 

// thread_affinity_policy_data_t 是一种用于描述线程关联性(affinity)策略的数据结构。
// 关联性是指一种指导操作系统调度器的机制,使特定的线程更倾向于在特定的CPU核心或核心集上运行。这对于某些高性能计算任务或实时任务可能非常有用,因为它可以减少上下文切换和缓存失效的开销。
// thread_affinity_policy_data_t`是一种特定的数据类型,用于设定线程关联性策略。下面是这个结构的定义:
// typedef struct thread_affinity_policy {
// 	int affinity_tag;
// } thread_affinity_policy_data_t;
// 其中 `affinity_tag` 是一个整数,用于表示线程的关联标签(affinity tag)。线程具有相同关联标签的倾向于在同一处理器核心上运行。
// 当你要设置线程的关联性策略时,你可以创建一个 `thread_affinity_policy_data_t` 结构,设置适当的关联标签,
// 并使用 `thread_policy_set` 函数将其应用于特定线程。
// 示例:
// thread_affinity_policy_data_t policy;
// policy.affinity_tag = 1; // 1 is the affinity tag
// thread_policy_set(thread, THREAD_AFFINITY_POLICY, (thread_policy_t)&policy, THREAD_AFFINITY_POLICY_COUNT);
// 这里的 `THREAD_AFFINITY_POLICY` 和 `THREAD_AFFINITY_POLICY_COUNT` 是描述策略类型和大小的常量。
// 请注意,线程关联性是一个提示,而不是一个硬性规定。即使为线程设置了关联性策略,操作系统调度器仍然可能会在其他处理器上运行该线程。
// 关联性策略的效果也可能因操作系统和硬件架构的不同而有所不同。

// `affinity_tag`是一个抽象的标签,用于将具有相同关联性需求的线程组合在一起。
// 当你为多个线程设置相同的`affinity_tag`时,操作系统的调度器会尽量让这些线程在同一个CPU核心或核心组上运行。
// `affinity_tag`的具体值没有特定的含义。它只是一个标识符或标签,用于将具有相同关联性需求的线程组合在一起。
// 在以下示例中:
// policy.affinity_tag = 1; // 1 is the affinity tag
// 数字`1`只是一个标识符。你可以选择任何整数值作为关联标签,只要你在你的应用程序或系统中一致使用它就可以了。
// 如果你在多个线程之间设置相同的`affinity_tag`值,那么操作系统将尽量让这些线程在同一处理器核心上运行。
// 这样做的目的通常是为了提高缓存效率和性能,因为在同一核心上运行的线程可以共享缓存和其他资源。
// 请注意,线程关联性是一个建议性的机制,而不是强制性的。调度器可能会基于系统的其他需求和负载来忽略或覆盖关联性设置。

// 这条宏定义将 cpu_set_t 重新定义为 thread_affinity_policy_data_t。这样,在代码中使用 cpu_set_t 时,实际上是在使用 thread_affinity_policy_data_t 类型。
#define cpu_set_t thread_affinity_policy_data_t
// 这条宏定义重新定义了 CPU_SET 宏。它接受一个 CPU 编号 cpu_id 和一个 CPU 集合 new_mask 作为参数,
// 并将 new_mask 中的 affinity_tag 设置为 cpu_id + 1。这似乎是一种将 CPU 编号映射到 affinity_tag 的方式。
#define CPU_SET(cpu_id, new_mask) (*(new_mask)).affinity_tag = (cpu_id + 1)
// 这条宏定义重新定义了 CPU_ISSET 宏。它接受一个 CPU 编号 cpu_id 和一个 CPU 集合 new_mask 作为参数,
#define CPU_ISSET(cpu_id, new_mask) ((*(new_mask)).affinity_tag == (cpu_id + 1))
// 这条宏定义重新定义了 CPU_ZERO 宏。它接受一个 CPU 集合 new_mask 作为参数,并将 new_mask 中的 affinity_tag 设置为 THREAD_AFFINITY_TAG_NULL。
#define CPU_ZERO(new_mask) (*(new_mask)).affinity_tag = THREAD_AFFINITY_TAG_NULL
#endif

enum {
    RECEIVE_CPU_SET,
    WORKER_CPU_SET,
    VERDICT_CPU_SET,
    MANAGEMENT_CPU_SET,
    MAX_CPU_SET
};

// BALANCED_AFFINITY: 这个常量值可能表示一种"平衡"的线程亲和性配置模式。
// 在多线程程序中,线程亲和性指的是将线程绑定到特定的 CPU 核心或处理器,以优化性能。
// "平衡"的线程亲和性可能意味着线程会在多个 CPU 核心之间分配,以实现负载均衡。

// EXCLUSIVE_AFFINITY: 这个常量值可能表示一种"独占"的线程亲和性配置模式。
// 在这种模式下,每个线程会被绑定到一个特定的 CPU 核心或处理器,从而实现更精细的性能控制和优化。
// 这可以用于确保某些关键任务始终在同一核心上执行,避免由于核心切换而引起的性能下降。

// MAX_AFFINITY: 这个常量值可能表示一个枚举值的上限。在这里,它可能被用来表示枚举的最大值或可选项的总数。
enum {
    BALANCED_AFFINITY,
    EXCLUSIVE_AFFINITY,
    MAX_AFFINITY
};

// 用于存储线程亲和性(thread affinity)的相关设置信息。
// 用于保存不同线程亲和性类型的相关信息,包括名称、模式、优先级、线程数目以及允许运行的 CPU 集合等。
// 它可能在代码中用于组织和管理不同线程亲和性设置的数据。
// 从配置中读取节点信息,然后将其保存到这个结构体中。
typedef struc ThreadsAffinityType_ {
    const char *name; // 一个指向字符串的指针,用于存储线程亲和性类型的名称。
    uint8_t mode_flag; // 一个8位无符号整数,用于存储线程亲和性的模式标志。
    int prio; // 一个整数,用于存储线程亲和性的优先级。
    uint32_t nb_threads; // 一个32位无符号整数,用于存储线程数目。
    SCMutex taf_mutex; // 一个名为 taf_mutex 的互斥锁,用于保护线程亲和性设置的访问。
    uint16_t lcpu; /* use by exclusive mode */

#if !defined __CYGWIN__ && !defined OS_WIN32 && !defined __OpenBSD__ && !defined sun
    cpu_set_t cpu_set; // 一个16位无符号整数,在独占模式(exclusive mode)下使用。
    cpu_set_t lowprio_cpu; // 一个 CPU 集合,用于存储低优先级线程允许运行的 CPU。
    cpu_set_t medprio_cpu; // 一个 CPU 集合,用于存储中优先级线程允许运行的 CPU。
    cpu_set_t hiprio_cpu; // 一个 CPU 集合,用于存储高优先级线程允许运行的 CPU。
#endif
} ThreadsAffinityType;

/** store thread affinity mode for all type of threads */
#ifndef _THREAD_AFFINITY
extern ThreadsAffinityType thread_affinity[MAX_CPU_SET];
#endif

void AffinitySetupLoadFromConfig(void);
ThreadsAffinityType * GetAffinityTypeFromName(const char *name);

int AffinityGetNextCPU(ThreadsAffinityType *taf);

void BuildCpusetWithCallback(const char *name, ConfNode *node,
                             void (*Callback)(int i, void * data),
                             void *data);

#endif /* __UTIL_AFFINITY_H__ */



















#include "suricata-common.h"
#define _THREAD_AFFINITY
#include "util-affinity.h"
#include "util-cpu.h"
#include "util-byte.h"
#include "conf.h"
#include "threads.h"
#include "queue.h"
#include "runmodes.h"

// management-cpu-set - used for management (example - flow.managers, flow.recyclers)
// receive-cpu-set - used for receive and decode
// worker-cpu-set - used for streamtcp,detect,output(logging)
// verdict-cpu-set - used for verdict and respond/reject

// 用于存储不同线程亲和性类型的设置信息。
ThreadsAffinityType thread_affinity[MAX_CPU_SET] = {
    {
        .name = "receive-cpu-set",
        // 表示"独占亲和性模式"。在这种模式下,每个线程都将被分配到特定的CPU核心,不与其他线程共享核心。这可以避免线程之间的干扰,但需要更精细的调度策略来保证性能。
        .mode_flag = EXCLUSIVE_AFFINITY,
        .prio = PRIO_MEDIUM,
        .lcpu = 0,
    },
    {
        .name = "worker-cpu-set",
        .mode_flag = EXCLUSIVE_AFFINITY,
        .prio = PRIO_MEDIUM,
        .lcpu = 0,
    },
    {
        .name = "verdict-cpu-set",
        // 表示"平衡亲和性模式"。在这种模式下,线程将在可用的多个CPU核心之间平均分配,以实现负载均衡。这样可以确保各个核心被充分利用,从而提高整体的性能。
        .mode_flag = BALANCED_AFFINITY,
        .lcpu = 0,
    },
    {
        .name = "management-cpu-set",
        .mode_flag = BALANCED_AFFINITY,
        .prio = PRIO_MEDIUM,
        .lcpu = 0,
    },

};

int thread_affinity_init_done = 0;

/**
 * \brief find affinity by its name
 * \retval a pointer to the affinity or NULL if not found
 */
ThreadsAffinityType * GetAffinityTypeFromName(const char *name)
{
    int i;
    for (i = 0; i < MAX_CPU_SET; i++) {
        if (!strcmp(thread_affinity[i].name, name)) {
            return &thread_affinity[i];
        }
    }
    return NULL;
}

#if !defined __CYGWIN__ && !defined OS_WIN32 && !defined __OpenBSD__ && !defined sun
static void AffinitySetupInit(void)
{
    int i, j;
    // 使用 UtilCpuGetNumProcessorsConfigured() 函数获取已配置的处理器数量,保存在变量 ncpu 中。
    int ncpu = UtilCpuGetNumProcessorsConfigured();

    SCLogDebug("Initialize affinity setup\n");
    /* be conservative relatively to OS: use all cpus by default */
    for (i = 0; i < MAX_CPU_SET; i++) {
        // 在循环内部,获取名为 thread_affinity 数组中第 i 个元素的 cpu_set_t 成员的指针 cs。
        cpu_set_t *cs = &thread_affinity[i].cpu_set;
        CPU_ZERO(cs); // 使用 CPU_ZERO 宏将 cs 初始化为空的 CPU 集合。
        // 使用嵌套的 for 循环遍历变量 j 从 0 到 ncpu - 1,然后使用 CPU_SET 宏将编号为 j 的处理器加入到当前的 CPU 集合 cs 中。
        for (j = 0; j < ncpu; j++) {
            CPU_SET(j, cs);
        }
        //使用 SCMutexInit 函数初始化名为 thread_affinity 数组中第 i 个元素的 taf_mutex 互斥锁。
        SCMutexInit(&thread_affinity[i].taf_mutex, NULL);
    }
    return;
}

// 该函数用于构建一个 CPU 集合,并在集合中的每个 CPU 上执行一个回调函数。
/**
 * 根据配置节点构建一个 CPU 集合,并通过回调函数对每个 CPU 进行处理。
 *
 * @param name 名称标识,用于错误信息输出
 * @param node 配置节点,包含要构建的 CPU 集合的信息
 * @param Callback 回调函数,将被用于处理每个 CPU
 * @param data 传递给回调函数的额外数据
 */
// 这个函数在处理配置节点中的 CPU 集合信息时,根据输入的字符串表示,解析出要处理的 CPU 范围,
// 并通过回调函数对每个 CPU 进行处理。对于不同的指定情况(如 "all"、范围、单个 CPU),函数会根据不同的情况进行处理,
// 同时还包括了一些错误检查和报错处理。回调函数 Callback 将会在每个 CPU 上调用,并可以用来进行一些特定的处理。
void BuildCpusetWithCallback(const char *name, ConfNode *node,
                             void (*Callback)(int i, void * data),
                             void *data)
{
    ConfNode *lnode;
    TAILQ_FOREACH(lnode, &node->head, next) {
        int i;
        long int a,b;
        int stop = 0;
        int max = UtilCpuGetNumProcessorsOnline() - 1;
        // 处理特殊情况:指定全部 CPU
        if (!strcmp(lnode->val, "all")) {
            a = 0;
            b = max;
            stop = 1;
        }// 处理范围指定情况,例如 "1-3" 
        else if (strchr(lnode->val, '-') != NULL) {
            // strchr:这个函数将从字符串的开头开始,寻找第一个匹配-的字符。如果找到,它将返回一个指向该字符的指针。如果找不到,它将返回NULL。
            char *sep = strchr(lnode->val, '-');
            char *end;
            // 这行代码使用C库中的strtoul函数来将字符串lnode->val的内容转换为一个无符号长整型数(unsigned long)。这里的转换是基于10进制的。
            a = strtoul(lnode->val, &end, 10);
            // 以下代码用于解析和验证范围情况的输入
            // 包括判断范围是否合法,是否超出上限等
            if (end != sep) {
                SCLogError(SC_ERR_INVALID_ARGUMENT,
                        "%s: invalid cpu range (start invalid): \"%s\"",
                        name,
                        lnode->val);
                exit(EXIT_FAILURE);
            }
            b = strtol(sep + 1, &end, 10);
            if (end != sep + strlen(sep)) {
                SCLogError(SC_ERR_INVALID_ARGUMENT,
                        "%s: invalid cpu range (end invalid): \"%s\"",
                        name,
                        lnode->val);
                exit(EXIT_FAILURE);
            }
            if (a > b) {
                SCLogError(SC_ERR_INVALID_ARGUMENT,
                        "%s: invalid cpu range (bad order): \"%s\"",
                        name,
                        lnode->val);
                exit(EXIT_FAILURE);
            }
            if (b > max) {
                SCLogError(SC_ERR_INVALID_ARGUMENT,
                           "%s: upper bound (%ld) of cpu set is too high, only %d cpu(s)",
                           name,
                           b, max + 1);
            }
        } else {
            // 处理单个 CPU 指定情况,例如 "1"
            char *end;
            a = strtoul(lnode->val, &end, 10);
            // 以下代码用于解析和验证单个 CPU 指定情况的输入
            // 包括判断输入是否为整数等
            if (end != lnode->val + strlen(lnode->val)) {
                SCLogError(SC_ERR_INVALID_ARGUMENT,
                        "%s: invalid cpu range (not an integer): \"%s\"",
                        name,
                        lnode->val);
                exit(EXIT_FAILURE);
            }
            b = a;
        }
        // 遍历处理范围内的每个 CPU
        for (i = a; i<= b; i++) {
            Callback(i, data);// 调用回调函数处理当前 CPU
        }
        // 如果是 "all" 指定,就退出循环
        if (stop)
            break;
    }
}

static void AffinityCallback(int i, void *data)
{
    CPU_SET(i, (cpu_set_t *)data);
}

static void BuildCpuset(const char *name, ConfNode *node, cpu_set_t *cpu)
{
    BuildCpusetWithCallback(name, node, AffinityCallback, (void *) cpu);
}
#endif /* OS_WIN32 and __OpenBSD__ */

/**
 * \brief Extract cpu affinity configuration from current config file
 */
// 从配置文件中加载线程亲和性


void AffinitySetupLoadFromConfig()
{
#if !defined __CYGWIN__ && !defined OS_WIN32 && !defined __OpenBSD__ && !defined sun
    // 在代码中,使用 ConfNode 类型的指针变量 root 获取配置节点 "threading.cpu-affinity"。
    ConfNode *root = ConfGetNode("threading.cpu-affinity");
    ConfNode *affinity;

    // 如果之前没有进行线程亲和性的初始化(thread_affinity_init_done == 0),
    // 则调用 AffinitySetupInit() 函数进行初始化,并将标志 thread_affinity_init_done 设置为 1。
    if (thread_affinity_init_done == 0) {
        AffinitySetupInit();
        thread_affinity_init_done = 1;
    }
    // 如果无法获取名为 "threading.cpu-affinity" 的配置节点,输出一条信息并返回。
    SCLogDebug("Load affinity from config\n");
    if (root == NULL) {
        SCLogInfo("can't get cpu-affinity node");
        return;
    }
    // 使用 TAILQ_FOREACH 宏遍历名为 root 的配置节点的链表,即遍历配置中 "threading.cpu-affinity" 节点下的子节点。
    TAILQ_FOREACH(affinity, &root->head, next) { // affinity被配置为root->head
        if (strcmp(affinity->val, "decode-cpu-set") == 0 ||
            strcmp(affinity->val, "stream-cpu-set") == 0 ||
            strcmp(affinity->val, "reject-cpu-set") == 0 ||
            strcmp(affinity->val, "output-cpu-set") == 0) {
            continue;
        }

        // 获取当前子节点的值,并将其保存到名为 setname 的变量中。
        const char *setname = affinity->val;
        if (strcmp(affinity->val, "detect-cpu-set") == 0)
            setname = "worker-cpu-set";
        // 使用函数 GetAffinityTypeFromName() 根据 setname 获取与之相关的线程亲和性类型。
        ThreadsAffinityType *taf = GetAffinityTypeFromName(setname);
        ConfNode *node = NULL;
        ConfNode *nprio = NULL;
        // 检查从GetAffinityTypeFromName函数获得的线程亲和性类型是否为NULL。如果不是NULL,表示找到了匹配的类型,记录一条配置级别的日志。
        if (taf == NULL) {
            FatalError(SC_ERR_FATAL, "unknown cpu-affinity type");
        } else {
            SCLogConfig("Found affinity definition for \"%s\"", setname);
        }

        // 清空 taf 对象中的 CPU 集合。
        CPU_ZERO(&taf->cpu_set);
        // 获取名为 "cpu" 的子节点,如果找不到,输出信息。
        node = ConfNodeLookupChild(affinity->head.tqh_first, "cpu");
        if (node == NULL) {
            SCLogInfo("unable to find 'cpu'");
        } else {
            // 使用函数 BuildCpuset() 根据子节点的信息构建 CPU 集合,并保存到 taf->cpu_set 中。
            BuildCpuset(setname, node, &taf->cpu_set);
        }
        // 初始化线程亲和性类型的cpu_set为零。
        CPU_ZERO(&taf->lowprio_cpu);
        CPU_ZERO(&taf->medprio_cpu);
        CPU_ZERO(&taf->hiprio_cpu);
        // 类似上面的步骤,这里初始化lowprio_cpu、medprio_cpu 和 hiprio_cpu 为零。
        // 然后,从 "prio" 子节点中查找 "low"、"medium" 和 "high" 节点,用于设置不同优先级的线程亲和性。
        // 将不同优先级的节点放入taf不同优先级集合中
        nprio = ConfNodeLookupChild(affinity->head.tqh_first, "prio");
        if (nprio != NULL) {
            node = ConfNodeLookupChild(nprio, "low");
            if (node == NULL) {
                SCLogDebug("unable to find 'low' prio using default value");
            } else {
                BuildCpuset(setname, node, &taf->lowprio_cpu); 
            }

            node = ConfNodeLookupChild(nprio, "medium");
            if (node == NULL) {
                SCLogDebug("unable to find 'medium' prio using default value");
            } else {
                BuildCpuset(setname, node, &taf->medprio_cpu);
            }

            node = ConfNodeLookupChild(nprio, "high");
            if (node == NULL) {
                SCLogDebug("unable to find 'high' prio using default value");
            } else {
                BuildCpuset(setname, node, &taf->hiprio_cpu);
            }
            node = ConfNodeLookupChild(nprio, "default");
            if (node != NULL) {
                if (!strcmp(node->val, "low")) {
                    taf->prio = PRIO_LOW;
                } else if (!strcmp(node->val, "medium")) {
                    taf->prio = PRIO_MEDIUM;
                } else if (!strcmp(node->val, "high")) {
                    taf->prio = PRIO_HIGH;
                } else {
                    FatalError(SC_ERR_FATAL, "unknown cpu_affinity prio");
                }
                SCLogConfig("Using default prio '%s' for set '%s'",
                        node->val, setname);
            }
        }

        node = ConfNodeLookupChild(affinity->head.tqh_first, "mode");
        if (node != NULL) {
            if (!strcmp(node->val, "exclusive")) {
                taf->mode_flag = EXCLUSIVE_AFFINITY;
            } else if (!strcmp(node->val, "balanced")) {
                taf->mode_flag = BALANCED_AFFINITY;
            } else {
                FatalError(SC_ERR_FATAL, "unknown cpu_affinity node");
            }
        }

        node = ConfNodeLookupChild(affinity->head.tqh_first, "threads");
        if (node != NULL) {
            // 线程数,结果从node->val转到taf->nb_threads中
            if (StringParseUint32(&taf->nb_threads, 10, 0, (const char *)node->val) < 0) {
                FatalError(SC_ERR_INVALID_ARGUMENT, "invalid value for threads "
                           "count: '%s'", node->val);
            }
            if (! taf->nb_threads) {
                FatalError(SC_ERR_FATAL, "bad value for threads count");
            }
        }
    }
#endif /* OS_WIN32 and __OpenBSD__ */
}

/**
 * \brief Return next cpu to use for a given thread family
 * \retval the cpu to used given by its id
 */
 // 这段代码定义了一个名为 AffinityGetNextCPU 的函数,用于在线程关联类型 (ThreadsAffinityType) 的上下文中获取下一个可用的 CPU 编号。
 // 这个函数可以用于设置线程的 CPU 亲和性,确保线程在特定的 CPU 上运行。
int AffinityGetNextCPU(ThreadsAffinityType *taf)
{
    // 变量初始化: 初始化变量 ncpu 和 iter,分别用于存储当前选择的 CPU 编号和迭代次数。
    int ncpu = 0;
#if !defined __CYGWIN__ && !defined OS_WIN32 && !defined __OpenBSD__ && !defined sun
    int iter = 0;
    // 锁定亲和性结构: 使用 SCMutexLock 锁定亲和性结构的互斥锁,确保在多线程环境中对其进行安全访问。
    SCMutexLock(&taf->taf_mutex);
    // 查找下一个 CPU: 使用 while 循环来找到 CPU 集合中的下一个可用 CPU。
    // 循环中的 CPU_ISSET 宏用于检查给定的 CPU 编号是否在 CPU 集合中。
    // 如果不在,则增加 CPU 编号并继续循环。如果超过在线 CPU 的数量,则重新开始从第一个 CPU,并增加迭代计数。
    ncpu = taf->lcpu;
    while (!CPU_ISSET(ncpu, &taf->cpu_set) && iter < 2) {
        ncpu++;
        if (ncpu >= UtilCpuGetNumProcessorsOnline()) {
            ncpu = 0;
            iter++;
        }
    }
    if (iter == 2) {
        SCLogError(SC_ERR_INVALID_ARGUMENT, "cpu_set does not contain "
                "available cpus, cpu affinity conf is invalid");
    }
    // 更新亲和性结构: 更新 taf 结构的 lcpu 成员,以便下次调用该函数时从下一个 CPU 开始。
    taf->lcpu = ncpu + 1;
    if (taf->lcpu >= UtilCpuGetNumProcessorsOnline())
        taf->lcpu = 0;
    SCMutexUnlock(&taf->taf_mutex);
    SCLogDebug("Setting affinity on CPU %d", ncpu);
#endif /* OS_WIN32 and __OpenBSD__ */
    return ncpu;
}

主要结构:用于存储线程亲和性(thread affinity)的相关设置信息。
typedef struct ThreadsAffinityType_ {

    const char *name; // 一个指向字符串的指针,用于存储线程亲和性类型的名称。

    uint8_t mode_flag; // 一个8位无符号整数,用于存储线程亲和性的模式标志。

    int prio; // 一个整数,用于存储线程亲和性的优先级。

    uint32_t nb_threads; // 一个32位无符号整数,用于存储线程数目。

    SCMutex taf_mutex; // 一个名为 taf_mutex 的互斥锁,用于保护线程亲和性设置的访问。

    uint16_t lcpu; /* use by exclusive mode */

#if !defined __CYGWIN__ && !defined OS_WIN32 && !defined __OpenBSD__ && !defined sun

    cpu_set_t cpu_set; // 一个16位无符号整数,在独占模式(exclusive mode)下使用。

    cpu_set_t lowprio_cpu; // 一个 CPU 集合,用于存储低优先级线程允许运行的 CPU。

    cpu_set_t medprio_cpu; // 一个 CPU 集合,用于存储中优先级线程允许运行的 CPU。

    cpu_set_t hiprio_cpu; // 一个 CPU 集合,用于存储高优先级线程允许运行的 CPU。

#endif

} ThreadsAffinityType;

主要函数:
        1.AffinitySetupLoadFromConfig函数

        2.BuildCpusetWithCallback函数

通常情况下的cpu亲和性使用方法为:

#include 

int main() {
    cpu_set_t cpuset;
    CPU_ZERO(&cpuset);  // 清空 cpuset 集合
    CPU_SET(0, &cpuset);  // 将 CPU 0 加入 cpuset 集合

    int result = sched_setaffinity(0, sizeof(cpu_set_t), &cpuset);
    if (result == -1) {
        perror("sched_setaffinity");
        return 1;
    }

    return 0;
}

在上面的示例中,CPU_ZERO 用于初始化 cpu_set_t 数据结构并将其所有位清零。然后,使用 CPU_SET 将特定的CPU核心(在这里是CPU 0)添加到集合中。最后,使用 sched_setaffinity 将当前进程绑定到所设置的CPU核心。如果操作成功,函数将返回0,否则将返回-1。

你可能感兴趣的:(suricata概述及源码分析,网络安全)