目录


NODEMASK 原理

NODEMASK 作为内核基础数据结构,常用于统计当前 Online/Possible Online NUMA NODE 的数量、判断 NUMA NODE 是否包含内存、判断 NUMA NODE 是否与 CPU 进行绑定等,NODEMASK 作为 NUMA 子系统不可或缺的一部分,为内核和其他子系统提供了 NUMA NODE 的多种信息,首先来看一下 NODEMASK 定义:

#ifdef CONFIG_NODES_SHIFT
#define NODES_SHIFT     CONFIG_NODES_SHIFT
#else
#define NODES_SHIFT     0
#endif

#define MAX_NUMNODES    (1 << NODES_SHIFT)

typedef struct { DECLARE_BITMAP(bits, MAX_NUMNODES); } nodemask_t;

在支持多 NUMA NODE 的架构体系中,内核可以最多支持 MAX_NUMNODES 个 NUMA NODE, NODEMASK 基于 Bitmap 机制,将每个 NUMA NODE 通过 bitmap 中的一个 bit 进行维护,因此定义了 NODEMASK 逻辑结构,每个 NUMA NODE 对应了 NODEMASK 中的一个 bit,也可以称为 node,通过 node 的置位或清零来维护指定信息。

node_states

在 NUMA 子系统中,内核为了更好的维护 NUMA NODE 与 CPU/Memory/Online/Offline 等信息,定义了一系列的 NODEMASK 来维护这些关系。NUMA 子系统定义了名为 node_states 的 NODEMASK 数组,其定义如下:

在 node_states[] 数组中定义了多种类型的 NODEMASK, 例如 N_ONLINE 对应的 NODEMASK 用于描述当前在线的 NUMA NODE 情况,只要某个 NUMA NODE 在线/在使用中,那么该 NUMA NODE ID 在 N_ONLINE NODEMASK 指定的 node 就置位,以此表示该 NUMA NODE 正在使用/在线. 同理, N_POSSIBLE 对应的 NODEMASK 用于表示正在线上或可能上线的 NUMA NODE 信息; N_MEMORY 用于表示已经具有高端内存或者普通内存的 NUMA NODE; N_HIGH_MEMORY 用于表示已经包含高端内存的 NUMA NODE; N_NORMAL_MEMORY 用于表示已经包含普通物理内存的 NUMA NODE 信息; N_CPU 则表示已经与 CPU 进行绑定的 NUMA NODE 信息。NODEMASK 机制提供了一系列的函数用于便捷的从 node_states[] 数组中获得 NUMA NODE 相关信息,开发者可以参考以下章节进一步了解:

NODEMASK 源码分析及实例运用

NODEMASK 不仅提供了维护 NUMA NODE 相关的信息,还提供了一整套的 NUMA NODE 运算机制,便于动态调整 NUMA NODE 的相关数据,具体可以参考以下章节:

NODEMASK 使用

开发者可以通过了解 NODEMASK 中技术实现细节,以及 NODEMASK 实践,可以参考以下章节:

NODEMASK 实践

NODEMASK 源码分析及实例运用


NODEMASK 使用

NODEMASK 机制提供了一套完整的接口,内核和其他子系统可以通过这套接口获得所需的功能,本节用于介绍如何使用 NODEMASK.

NODEMASK 基础逻辑操作

node_states


NODEMASK 实践


实践准备

本实践只支持多种架构,但在支持 NUMA 架构的进行实践最优,目前 BiscuitOS 实践支持 NUMA 的架构包括 X86_64 架构和 ARM64 架构. 本文以在 X86_64 架构中实践为例. 首先开发者需要搭建基于 X86_64 架构的 linux 5.0 实践环境,请参考如下问题:

> BiscuitOS Linux 5.0 X86_64 Usermanual

> BiscuitOS Linux 5.0 ARM64 Usermanual


实践部署

在部署完毕开发环境之后,实践过程中由于要构建多 NUMA NODE 的情况,因此需要修改 BiscuitOS 的启动参数,参数位于 RunBiscuitOS.sh 节本中:

BiscuitOS/output/linux-5.0-i386/RunBiscuitOS.sh

如上图,在 BiscuitOS 启动命令中需要添加描述 NUMA NODE 的信息:

        -object memory-backend-ram,id=mem0,size=512M \
        -numa node,memdev=mem0,cpus=0-1,nodeid=0 \

该命令用于创建一个独立的 NUMA NODE, 其包含了 512M 物理内存,并将 CPU 0 和 CPU 1 绑定到这个 NUMA NODE 上。开发者可以参考上面参数向 BiscuitOS 中添加一个或者多个 NUMA NODE.


实践执行

环境部署完毕之后,开发者可以 BiscuitOS 代码库中部署并安装多个 NODEMASK 实例进行实践,本节通过一个例子展示实例的使用办法,首先使用如下命令:

cd BiscuitOS
make menuconfig

  [*] Package  --->
      [*] nodemask  --->

开发者可以任意勾选一个实例进行实践,例如勾选 “first_ndoe”, 勾选完毕之后执行如下命令:

cd BiscuitOS/output/linux-5.0-x86_64/package/first_node-default
make download
make
make install
make pack
make run

通过上面的命令之后,可以看到 “first_node” 的实例通过一个模块被加载到内核执行,开发者可以使用该方法对 NODEMASK 进行实践. 更多实践细节,可以参考如下文档:

独立内核模块代码 – 独立程序开发办法


NODEMASK 源码分析及运用


node_states

在 NUMA 子系统中,内核为了更好的维护 NUMA NODE 与 CPU/Memory/Online/Offline 等信息,定义了一系列的 NODEMASK 来维护这些关系。NUMA 子系统定义了名为 node_states 的 NODEMASK 数组,其定义如下:

在 node_states[] 数组中定义了多种类型的 NODEMASK, 例如 N_ONLINE 对应的 NODEMASK 用于描述当前在线的 NUMA NODE 情况,只要某个 NUMA NODE 在线/在使用中,那么该 NUMA NODE ID 在 N_ONLINE NODEMASK 指定的 node 就置位,以此表示该 NUMA NODE 正在使用/在线. 同理, N_POSSIBLE 对应的 NODEMASK 用于表示正在线上或可能上线的 NUMA NODE 信息; N_MEMORY 用于表示已经具有高端内存或者普通内存的 NUMA NODE; N_HIGH_MEMORY 用于表示已经包含高端内存的 NUMA NODE; N_NORMAL_MEMORY 用于表示已经包含普通物理内存的 NUMA NODE 信息; N_CPU 则表示已经与 CPU 进行绑定的 NUMA NODE 信息。NODEMASK 机制提供了一系列的函数用于便捷的从 node_states[] 数组中获得 NUMA NODE 相关信息。


NODEMASK 作为内核基础数据结构,常用于统计当前 Online/Possible Online NUMA NODE 的数量、判断 NUMA NODE 是否包含内存、判断 NUMA NODE 是否与 CPU 进行绑定等,NODEMASK 作为 NUMA 子系统不可或缺的一部分,为内核和其他子系统提供了 NUMA NODE 的多种信息,首先来看一下 NODEMASK 定义:

#ifdef CONFIG_NODES_SHIFT
#define NODES_SHIFT     CONFIG_NODES_SHIFT
#else
#define NODES_SHIFT     0
#endif

#define MAX_NUMNODES    (1 << NODES_SHIFT)

typedef struct { DECLARE_BITMAP(bits, MAX_NUMNODES); } nodemask_t;

在支持多 NUMA NODE 的架构体系中,内核可以最多支持 MAX_NUMNODES 个 NUMA NODE, NODEMASK 基于 Bitmap 机制,将每个 NUMA NODE 通过 bitmap 中的一个 bit 进行维护,因此定义了 NODEMASK 逻辑结构,每个 NUMA NODE 对应了 NODEMASK 中的一个 bit,也可以称为 node,通过 node 的置位或清零来维护指定信息。


nr_online_nodes

int nr_online_nodes = 1;

nr_online_nodes 用于描述系统中在线的 NUMA NODE 个数.


node_online_map

#define node_online_map         node_states[N_ONLINE]

node_online_map 用于描述 NUMA 子系统中在线 NUMA NODE 的 NODEMASK.


node_possible_map

#define node_possible_map       node_states[N_POSSIBLE]

node_possible_map 用于描述 NUMA 子系统中可能在线 NUMA NODE 的 NODEMASK.


first_online_node

#define first_online_node       first_node(node_states[N_ONLINE])

first_online_node 用于描述第一个在线的 NUMA NODE。


first_memory_node

#define first_memory_node       first_node(node_states[N_MEMORY])

first_online_node 用于描述第一个包含内存的 NUMA NODE。


node_possible

#define node_possible(node)     node_state((node), N_POSSIBLE)

node_possible() 函数用于判断指定的 NUMA NODE 是否可能上线,如果可能则返回 true,反之返回 false。函数通过 N_POSSIBLE 标志和调用 node_state() 函数判断对应的的 node 是否置位,如果置位则表示 NUMA NODE 可能在线. 函数在 BiscuitOS 的使用如下:

cd BiscuitOS
make menuconfig

  [*] Package  --->
      [*] nodemask  --->
          [*] node_possible  --->

开发者可以参考文档进行使用:

独立内核模块代码 – 独立程序开发办法

测试代码
/*
 * Nodemask: node_possible
 *
 * (C) 2021.01.10 BuddyZhang1 <buddy.zhang@aliyun.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */

#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>

/* Module initialize entry */
static int __init BiscuitOS_init(void)
{
        int nid = numa_node_id();

        /* NUMA Statistic */
        printk("The number of online nodes: %d\n", num_online_nodes());
        printk("The number of possible nodes: %d\n", num_possible_nodes());

        if (node_online(nid))
                printk("The NUMA NODE %d is online.\n", nid);
        if (node_possible(nid))
                printk("The NUMA NODE %d is possible online.\n", nid);

        printk("Hello modules on BiscuitOS\n");

        return 0;
}

/* Module exit entry */
static void __exit BiscuitOS_exit(void)
{
}

module_init(BiscuitOS_init);
module_exit(BiscuitOS_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("BiscuitOS <buddy.zhang@aliyun.com>");
MODULE_DESCRIPTION("Common Device driver on BiscuitOS");
BiscuitOS 运行结果
/lib/modules/5.0.0/extra # insmod num_online_nodes-default.ko
num_online_nodes_default: loading out-of-tree module taints kernel.
The number of online nodes: 1
The number of possible nodes: 1
The NUMA NODE 0 is online.
The NUMA NODE 0 is possible online.
Hello modules on BiscuitOS
/lib/modules/5.0.0/extra #

node_state


node_online

#define node_online(node)       node_state((node), N_ONLINE)

node_online() 函数用于判断 NUMA NODE ID 对应的 NUMA NODE 是否在线,如果在线则返回 true,反之返回 false。函数通过 N_ONLINE 标志和调用 node_state() 函数从 node_states[] 数组中判断对应的 node 是否置位,如果置位,那么对应的 NUMA NODE 就在线,反之返回 false. 函数在 BiscuitOS 的使用如下:

cd BiscuitOS
make menuconfig

  [*] Package  --->
      [*] nodemask  --->
          [*] node_online  --->

开发者可以参考文档进行使用:

独立内核模块代码 – 独立程序开发办法

测试代码
/*
 * Nodemask: node_online
 *
 * (C) 2021.01.10 BuddyZhang1 <buddy.zhang@aliyun.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */

#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>

/* Module initialize entry */
static int __init BiscuitOS_init(void)
{
        int nid = numa_node_id();

        /* NUMA Statistic */
        printk("The number of online nodes: %d\n", num_online_nodes());
        printk("The number of possible nodes: %d\n", num_possible_nodes());

        if (node_online(nid))
                printk("The NUMA NODE %d is online.\n", nid);
        if (node_possible(nid))
                printk("The NUMA NODE %d is possible online.\n", nid);

        printk("Hello modules on BiscuitOS\n");

        return 0;
}

/* Module exit entry */
static void __exit BiscuitOS_exit(void)
{
}

module_init(BiscuitOS_init);
module_exit(BiscuitOS_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("BiscuitOS <buddy.zhang@aliyun.com>");
MODULE_DESCRIPTION("Common Device driver on BiscuitOS");
BiscuitOS 运行结果
/lib/modules/5.0.0/extra # insmod num_online_nodes-default.ko
num_online_nodes_default: loading out-of-tree module taints kernel.
The number of online nodes: 1
The number of possible nodes: 1
The NUMA NODE 0 is online.
The NUMA NODE 0 is possible online.
Hello modules on BiscuitOS
/lib/modules/5.0.0/extra #

node_state


num_possible_nodes

#define num_possible_nodes()    num_node_state(N_POSSIBLE)

num_possible_nodes() 函数用于获得当前系统中可能在线的 NUMA NODE 数量。函数通过 N_POSSIBLE 标志和调用 num_node_state() 函数从 node_states[] 数组中获得当前可能在线的 NUMA NODE 数量。函数在 BiscuitOS 的使用如下:

cd BiscuitOS
make menuconfig

  [*] Package  --->
      [*] nodemask  --->
          [*] num_possible_nodes  --->

开发者可以参考文档进行使用:

独立内核模块代码 – 独立程序开发办法

测试代码
/*
 * Nodemask: num_possible_nodes
 *
 * (C) 2021.01.10 BuddyZhang1 <buddy.zhang@aliyun.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */

#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>

/* Module initialize entry */
static int __init BiscuitOS_init(void)
{
        int nid = numa_node_id();

        /* NUMA Statistic */
        printk("The number of online nodes: %d\n", num_online_nodes());
        printk("The number of possible nodes: %d\n", num_possible_nodes());

        if (node_online(nid))
                printk("The NUMA NODE %d is online.\n", nid);
        if (node_possible(nid))
                printk("The NUMA NODE %d is possible online.\n", nid);

        printk("Hello modules on BiscuitOS\n");

        return 0;
}

/* Module exit entry */
static void __exit BiscuitOS_exit(void)
{
}

module_init(BiscuitOS_init);
module_exit(BiscuitOS_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("BiscuitOS <buddy.zhang@aliyun.com>");
MODULE_DESCRIPTION("Common Device driver on BiscuitOS");
BiscuitOS 运行结果
/lib/modules/5.0.0/extra # insmod num_online_nodes-default.ko
num_online_nodes_default: loading out-of-tree module taints kernel.
The number of online nodes: 1
The number of possible nodes: 1
The NUMA NODE 0 is online.
The NUMA NODE 0 is possible online.
Hello modules on BiscuitOS
/lib/modules/5.0.0/extra #

num_node_state


num_online_nodes

#define num_online_nodes()      num_node_state(N_ONLINE)

num_online_nodes() 函数用于获得当前在线的 NUMA NODE 数量。函数通过 N_ONLINE 标志和调用 num_node_state() 函数从 node_states[] 数组中获得当前在线 NUMA NODE 的数量。函数在 BiscuitOS 的使用如下:

cd BiscuitOS
make menuconfig

  [*] Package  --->
      [*] nodemask  --->
          [*] num_online_nodes  --->

开发者可以参考文档进行使用:

独立内核模块代码 – 独立程序开发办法

测试代码
/*
 * Nodemask: num_online_nodes
 *
 * (C) 2021.01.10 BuddyZhang1 <buddy.zhang@aliyun.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */

#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>

/* Module initialize entry */
static int __init BiscuitOS_init(void)
{
        int nid = numa_node_id();

        /* NUMA Statistic */
        printk("The number of online nodes: %d\n", num_online_nodes());
        printk("The number of possible nodes: %d\n", num_possible_nodes());

        if (node_online(nid))
                printk("The NUMA NODE %d is online.\n", nid);
        if (node_possible(nid))
                printk("The NUMA NODE %d is possible online.\n", nid);

        printk("Hello modules on BiscuitOS\n");

        return 0;
}

/* Module exit entry */
static void __exit BiscuitOS_exit(void)
{
}

module_init(BiscuitOS_init);
module_exit(BiscuitOS_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("BiscuitOS <buddy.zhang@aliyun.com>");
MODULE_DESCRIPTION("Common Device driver on BiscuitOS");
BiscuitOS 运行结果
/lib/modules/5.0.0/extra # insmod num_online_nodes-default.ko 
num_online_nodes_default: loading out-of-tree module taints kernel.
The number of online nodes: 1
The number of possible nodes: 1
The NUMA NODE 0 is online.
The NUMA NODE 0 is possible online.
Hello modules on BiscuitOS
/lib/modules/5.0.0/extra #

num_node_state


node_set_online

node_set_online() 函数用于将指定的 NUMA NODE 上线。参数 nid 指向需要上线的 NUMA NODE. 此处所说的上线仅仅是将 NODE NODE 信息添加到系统在线 NUMA NODE 信息里。函数首先通过 N_ONLINE 标志和调用 node_set_online() 函数将对应的 NUMA NODE 标记为 online, 然后调用 num_node_state() 函数将当前在线的 NODE NODE 数量更新到 nr_online_nodes. 函数在 BiscuitOS 的使用如下:

cd BiscuitOS
make menuconfig

  [*] Package  --->
      [*] nodemask  --->
          [*] node_set_online  --->

开发者可以参考文档进行使用:

独立内核模块代码 – 独立程序开发办法

测试代码
/*
 * Nodemask: node_set_online
 *
 * (C) 2021.01.10 BuddyZhang1 <buddy.zhang@aliyun.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */

#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>

/* Module initialize entry */
static int __init BiscuitOS_init(void)
{
        int nid = numa_node_id();

        /* Offline NUMA NODE */
        node_set_offline(nid);

        /* Check NUMA NODE state */
        if (!node_state(nid, N_ONLINE))
                printk("Warning NUMA NODE %d offline!\n", nid);

        /* Online NUMA NODE */
        node_set_online(nid);

        /* Check NUMA NODE state */
        if (node_state(nid, N_ONLINE))
                printk("NUMA NODE %d online!\n", nid);

        printk("Hello modules on BiscuitOS\n");

        return 0;
}

/* Module exit entry */
static void __exit BiscuitOS_exit(void)
{
}

module_init(BiscuitOS_init);
module_exit(BiscuitOS_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("BiscuitOS <buddy.zhang@aliyun.com>");
MODULE_DESCRIPTION("Common Device driver on BiscuitOS");
BiscuitOS 运行结果
/lib/modules/5.0.0/extra # insmod node_set_online-default.ko 
node_set_online_default: loading out-of-tree module taints kernel.
Warning NUMA NODE 0 offline!
NUMA NODE 0 online!
Hello modules on BiscuitOS
/lib/modules/5.0.0/extra # 

num_node_state

node_set_state


node_set_offline

node_set_offline() 函数用于将指定的 NUMA NODE 下线。参数 nid 指向指定的 NUMA NODE. 这里所谓的下线仅仅是将指定的 NUMA NODE 从 node_states[N_ONLINE] NODEMASK 中对应 node 清零,以此从资源统计上达到减少的目的。函数首先通过 N_ONLINE 标志和 node_clear_state() 函数将对应的 NODEMASK 清零,然后再调用 num_node_state() 函数将当前在线的 NUMA NODE 信息更新到 nr_online_nodes 变量里. 函数在 BiscuitOS 的使用如下:

cd BiscuitOS
make menuconfig

  [*] Package  --->
      [*] nodemask  --->
          [*] node_set_offline  --->

开发者可以参考文档进行使用:

独立内核模块代码 – 独立程序开发办法

测试代码
/*
 * Nodemask: node_set_offline
 *
 * (C) 2021.01.10 BuddyZhang1 <buddy.zhang@aliyun.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */

#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>

/* Module initialize entry */
static int __init BiscuitOS_init(void)
{
        int nid = numa_node_id();

        /* Offline NUMA NODE */
        node_set_offline(nid);

        /* Check NUMA NODE state */
        if (!node_state(nid, N_ONLINE))
                printk("Warning NUMA NODE %d offline!\n", nid);

        /* Online NUMA NODE */
        node_set_online(nid);

        /* Check NUMA NODE state */
        if (node_state(nid, N_ONLINE))
                printk("NUMA NODE %d online!\n", nid);

        printk("Hello modules on BiscuitOS\n");

        return 0;
}

/* Module exit entry */
static void __exit BiscuitOS_exit(void)
{
}

module_init(BiscuitOS_init);
module_exit(BiscuitOS_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("BiscuitOS <buddy.zhang@aliyun.com>");
MODULE_DESCRIPTION("Common Device driver on BiscuitOS");
BiscuitOS 运行结果
/lib/modules/5.0.0/extra # insmod node_set_offline-default.ko 
node_set_offline_default: loading out-of-tree module taints kernel.
Warning NUMA NODE 0 offline!
NUMA NODE 0 online!
Hello modules on BiscuitOS
/lib/modules/5.0.0/extra #

node_clear_state

num_node_state


next_memory_node

next_memory_node() 函数用于获得当前 NUMA NODE 之后包含物理内存的 NUMA NODE ID. 参数 nid 指向当前 NUMA NODE ID. 函数首先通过 N_MEMORY 标志从 node_states[] 数组中获得物理内存相关的 NODEMASK, 接着函数调用 next_node() 函数从当前 NUMA NODE ID 开始查找下一个置位的 node,找到的 ndoe 就是下一个包含物理内存的 NUMA NODE ID. 函数在 BiscuitOS 的使用如下:

cd BiscuitOS
make menuconfig

  [*] Package  --->
      [*] nodemask  --->
          [*] next_memory_node  --->

开发者可以参考文档进行使用:

独立内核模块代码 – 独立程序开发办法

测试代码
/*
 * Nodemask: next_memory_node
 *
 * (C) 2021.01.10 BuddyZhang1 <buddy.zhang@aliyun.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */

#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>

/* Module initialize entry */
static int __init BiscuitOS_init(void)
{
        int nid;

        /* Next online NUMA NODE */
        nid = next_memory_node(0);
        if (nid == MAX_NUMNODES)
                printk("Only NUMA NODE 0 contain memory\n");
        else
                printk("The next node which contain memory for NUMA NODE 0: %d\n", nid);

        printk("Hello modules on BiscuitOS\n");

        return 0;
}

/* Module exit entry */
static void __exit BiscuitOS_exit(void)
{
}

module_init(BiscuitOS_init);
module_exit(BiscuitOS_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("BiscuitOS <buddy.zhang@aliyun.com>");
MODULE_DESCRIPTION("Common Device driver on BiscuitOS");
BiscuitOS 运行结果
/lib/modules/5.0.0/extra # insmod next_memory_node-default.ko 
next_memory_node_default: loading out-of-tree module taints kernel.
Only NUMA NODE 0 contain memory
Hello modules on BiscuitOS
/lib/modules/5.0.0/extra #

next_node


next_online_node

next_online_node() 函数用于获得指定 NUMA NODE 之后在线的 NUMA NODE ID. 参数 nid 指向当前 NUMA NODE ID. 函数首先通过 N_ONLINE 标志从 node_states[] 数组中获得在线 NUMA NODE 的 NODEMASK,然后通过 next_node() 函数从 node 参数处开始,查找对应的 NODEMASK 下一个置位的 node,找到的 node 就是下一个在线的 NUMA NODE. 函数在 BiscuitOS 的使用如下:

cd BiscuitOS
make menuconfig

  [*] Package  --->
      [*] nodemask  --->
          [*] next_online_node  --->

开发者可以参考文档进行使用:

独立内核模块代码 – 独立程序开发办法

测试代码
/*
 * Nodemask: next_online_node
 *
 * (C) 2021.01.10 BuddyZhang1 <buddy.zhang@aliyun.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */

#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>

/* Module initialize entry */
static int __init BiscuitOS_init(void)
{
        int nid;

        /* Next online NUMA NODE */
        nid = next_online_node(0);
        if (nid == MAX_NUMNODES)
                printk("Only NUMA NODE 0\n");
        else
                printk("The next online node for NUMA NODE 0: %d\n", nid);

        printk("Hello modules on BiscuitOS\n");

        return 0;
}

/* Module exit entry */
static void __exit BiscuitOS_exit(void)
{
}

module_init(BiscuitOS_init);
module_exit(BiscuitOS_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("BiscuitOS <buddy.zhang@aliyun.com>");
MODULE_DESCRIPTION("Common Device driver on BiscuitOS");
BiscuitOS 运行结果
/lib/modules/5.0.0/extra # insmod next_online_node-default.ko 
next_online_node_default: loading out-of-tree module taints kernel.
Only NUMA NODE 0
Hello modules on BiscuitOS
/lib/modules/5.0.0/extra #

next_node


for_each_node_state

for_each_node_state() 函数用于遍历具有某类资源的 NUMA NODE. 参数 __node 用于遍历时存储 NUMA NODE ID,参数 __state 用于指明某类资源。函数首先通过 __state 参数从 node_states[] 数组中获得某类资源对应的 NODEMASK, 接着调用 for_each_node_mask() 函数遍历该 NODEMASK 上所有置位的 node,以此遍历具有该类资源的 NUMA NODE. 函数在 BiscuitOS 的使用如下:

cd BiscuitOS
make menuconfig

  [*] Package  --->
      [*] nodemask  --->
          [*] for_each_node_state  --->

开发者可以参考文档进行使用:

独立内核模块代码 – 独立程序开发办法

测试代码
/*
 * Nodemask: for_each_node_state
 *
 * (C) 2021.01.10 BuddyZhang1 <buddy.zhang@aliyun.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */

#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>

/* Module initialize entry */
static int __init BiscuitOS_init(void)
{
        int nid;

        /* Iterate special resource infomation */
        for_each_node_state(nid, N_CPU)
                printk("NUMA NODE %d contains one or more CPUs.\n", nid);

        printk("Hello modules on BiscuitOS\n");

        return 0;
}

/* Module exit entry */
static void __exit BiscuitOS_exit(void)
{
}

module_init(BiscuitOS_init);
module_exit(BiscuitOS_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("BiscuitOS <buddy.zhang@aliyun.com>");
MODULE_DESCRIPTION("Common Device driver on BiscuitOS");
BiscuitOS 运行结果
/lib/modules/5.0.0/extra # insmod for_each_node_state-default.ko 
for_each_node_state_default: loading out-of-tree module taints kernel.
NUMA NODE 0 contains one or more CPUs.
Hello modules on BiscuitOS
/lib/modules/5.0.0/extra #

for_each_node_mask


num_node_state

num_node_state() 函数用于判断已经获得某类资源的 NUMA NODE 数量。参数 state 用于指明资源的种类。函数首先通过 state 参数从 node_states[] 数组中获得指定的 NODEMASK, 然后调用 nodes_weight() 函数判断该 NODEMASK 中置位 node 的数量,以此获得该类资源 NUMA NODE 的数量。函数在 BiscuitOS 的使用如下:

cd BiscuitOS
make menuconfig

  [*] Package  --->
      [*] nodemask  --->
          [*] num_node_state  --->

开发者可以参考文档进行使用:

独立内核模块代码 – 独立程序开发办法

测试代码
/*
 * Nodemask: num_node_state
 *
 * (C) 2021.01.10 BuddyZhang1 <buddy.zhang@aliyun.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */

#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>

/* Module initialize entry */
static int __init BiscuitOS_init(void)
{
        printk("Number of node:\n");
        printk("Online-Node: %d\n", num_node_state(N_ONLINE));
        printk("Possible Online: %d\n", num_node_state(N_POSSIBLE));
        printk("Normal Memory: %d\n", num_node_state(N_NORMAL_MEMORY));
        printk("High/Normal Memory: %d", num_node_state(N_HIGH_MEMORY));
        printk("Memory: %d\n", num_node_state(N_MEMORY));
        printk("CPU: %d\n", num_node_state(N_CPU));

        printk("Hello modules on BiscuitOS\n");

        return 0;
}

/* Module exit entry */
static void __exit BiscuitOS_exit(void)
{
}

module_init(BiscuitOS_init);
module_exit(BiscuitOS_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("BiscuitOS <buddy.zhang@aliyun.com>");
MODULE_DESCRIPTION("Common Device driver on BiscuitOS");
BiscuitOS 运行结果
/lib/modules/5.0.0/extra # insmod num_node_state-default.ko 
num_node_state_default: loading out-of-tree module taints kernel.
Number of node:
Online-Node: 1
Possible Online: 1
Normal Memory: 1
High/Normal Memory: 1
Memory: 1
CPU: 1
Hello modules on BiscuitOS
/lib/modules/5.0.0/extra #

nodes_weight


node_clear_state

node_clear_state() 函数用于清理 NUMA NODE 指定资源的信息。参数 node 指明 NUMA NODE ID, 参数 state 指明某类资源。函数首先通过 state 参数从 node_states[] 数组中获得对应资源的 NODEMASK, 接着函数调用 __node_clear() 函数将对应的 node 清除。函数在 BiscuitOS 的使用如下:

cd BiscuitOS
make menuconfig

  [*] Package  --->
      [*] nodemask  --->
          [*] node_clear_state  --->

开发者可以参考文档进行使用:

独立内核模块代码 – 独立程序开发办法

测试代码
/*
 * Nodemask: node_clear_state
 *
 * (C) 2021.01.10 BuddyZhang1 <buddy.zhang@aliyun.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */

#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>

/* Module initialize entry */
static int __init BiscuitOS_init(void)
{
        int nid = numa_node_id();

        /* Node clear state */
        node_clear_state(nid, N_CPU);

        /* Check CPU State */
        if (!node_state(nid, N_CPU))
                printk("NUMA NODE %d doesn't contain any CPU.\n", nid);

        /* Node set state */
        node_set_state(nid, N_CPU);

        /* Check CPU State */
        if (node_state(nid, N_CPU))
                printk("NUMA NODE %d contains one or more CPUs.\n", nid);

        printk("Hello modules on BiscuitOS\n");

        return 0;
}

/* Module exit entry */
static void __exit BiscuitOS_exit(void)
{
}

module_init(BiscuitOS_init);
module_exit(BiscuitOS_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("BiscuitOS <buddy.zhang@aliyun.com>");
MODULE_DESCRIPTION("Common Device driver on BiscuitOS");
BiscuitOS 运行结果
/lib/modules/5.0.0/extra # insmod node_clear_state-default.ko 
node_clear_state_default: loading out-of-tree module taints kernel.
NUMA NODE 0 doesn't contain any CPU.
NUMA NODE 0 contains one or more CPUs.
Hello modules on BiscuitOS
/lib/modules/5.0.0/extra # 

__node_clear


node_set_state

node_set_state() 函数用于设置 NUMA NODE 指定资源信息。参数 node 指明 NUMA NODE ID, 参数 state 指明资源的种类. 函数首先通过 state 参数从 node_states[] 数组中获得指定资源对应的 NODEMASK, 然后通过 __node_set() 函数将指定的 ndoe 置位,以此达到 NUMA NODE 具有某类资源. 函数在 BiscuitOS 的使用如下:

cd BiscuitOS
make menuconfig

  [*] Package  --->
      [*] nodemask  --->
          [*] node_set_state  --->

开发者可以参考文档进行使用:

独立内核模块代码 – 独立程序开发办法

测试代码
/*
 * Nodemask: node_set_state
 *
 * (C) 2021.01.10 BuddyZhang1 <buddy.zhang@aliyun.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */

#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>

/* Module initialize entry */
static int __init BiscuitOS_init(void)
{
        int nid = numa_node_id();

        /* Node clear state */
        node_clear_state(nid, N_CPU);

        /* Check CPU State */
        if (!node_state(nid, N_CPU))
                printk("NUMA NODE %d doesn't contain any CPU.\n", nid);

        /* Node set state */
        node_set_state(nid, N_CPU);

        /* Check CPU State */
        if (node_state(nid, N_CPU))
                printk("NUMA NODE %d contains one or more CPUs.\n", nid);

        printk("Hello modules on BiscuitOS\n");

        return 0;
}

/* Module exit entry */
static void __exit BiscuitOS_exit(void)
{
}

module_init(BiscuitOS_init);
module_exit(BiscuitOS_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("BiscuitOS <buddy.zhang@aliyun.com>");
MODULE_DESCRIPTION("Common Device driver on BiscuitOS");
BiscuitOS 运行结果
/lib/modules/5.0.0/extra # insmod node_set_state-default.ko 
node_set_state_default: loading out-of-tree module taints kernel.
NUMA NODE 0 doesn't contain any CPU.
NUMA NODE 0 contains one or more CPUs.
Hello modules on BiscuitOS
/lib/modules/5.0.0/extra #

__node_set


node_state

node_state() 函数用于读取指定 NUMA NODE 的信息,参数 node 指明 NUMA NODE ID, state 参数用于指明读取信息的类型。在 NUMA 子系统中,将 NUMA 相关的资源信息存储在 node_states[] 数组中,函数通过从该数组中获取不同类型的信息,每种信息使用 NODEMASK 进行维护,函数使用 node_isset() 函数判断指定 NUMA NODE 在该 NODEMASK 上是否置位,以此获得 NUMA NODE 是否已经具备该信息。函数在 BiscuitOS 的使用如下:

cd BiscuitOS
make menuconfig

  [*] Package  --->
      [*] nodemask  --->
          [*] node_state  --->

开发者可以参考文档进行使用:

独立内核模块代码 – 独立程序开发办法

测试代码
/*
 * Nodemask: node_state
 *
 * (C) 2021.01.10 BuddyZhang1 <buddy.zhang@aliyun.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */

#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>

/* Module initialize entry */
static int __init BiscuitOS_init(void)
{
        int nid = numa_node_id();

        /* Check online */
        if (node_state(nid, N_ONLINE))
                printk("NUMA NODE %d has online.\n", nid);
        else
                printk("NUMA NODE %d has offline.\n", nid);

        /* Check possible online */
        if (node_state(nid, N_POSSIBLE))
                printk("NUMA NODE %d could become online at some point.\n", nid);

        /* Check normal momory */
        if (node_state(nid, N_NORMAL_MEMORY))
                printk("NUMA NODE %d has regular memory.\n", nid);

        /* Check Highmem memory */
        if (node_state(nid, N_HIGH_MEMORY))
                printk("NUMA NODE %d has regular or high memory.\n", nid);

        /* Check memory */
        if (node_state(nid, N_MEMORY))
                printk("NUMA NODE %d has memory (regular/high/movable)\n", nid);

        /* Check CPU */
        if (node_state(nid, N_CPU))
                printk("NUMA NODE %d has one or more CPUs.\n", nid);

        printk("Hello modules on BiscuitOS\n");

        return 0;
}

/* Module exit entry */
static void __exit BiscuitOS_exit(void)
{
}

module_init(BiscuitOS_init);
module_exit(BiscuitOS_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("BiscuitOS <buddy.zhang@aliyun.com>");
MODULE_DESCRIPTION("Common Device driver on BiscuitOS");
BiscuitOS 运行结果
/lib/modules/5.0.0/extra # insmod node_state-default.ko 
node_state_default: loading out-of-tree module taints kernel.
NUMA NODE 0 has online.
NUMA NODE 0 could become online at some point.
NUMA NODE 0 has regular memory.
NUMA NODE 0 has regular or high memory.
NUMA NODE 0 has memory (regular/high/movable)
NUMA NODE 0 has one or more CPUs.
Hello modules on BiscuitOS
/lib/modules/5.0.0/extra #


for_each_node_mask

for_each_node_mask() 函数用于遍历 NODEMASK 中所有置位的 node。参数 node 指向置位的位置,mask 参数指向遍历的 NODEMASK. 函数的实现根据 MAX_NUMNODES 而定,当 MAX_NUMNODES 大于 1,那么系统中存在多个 node,那么函数使用 for 循环,首先通过调用 first_node() 函数获得 NODEMASK 中第一个置位的 node,然后判断该 node 没有查过 MAX_NUMNODES, 那么函数执行遍历。遍历完一次之后,函数调用 next_node() 函数从当前 node 查找下一个置位 node,以此遍历 NODEMASK 中所有的置位 node.

如果 MAX_NUMNODES 等于 1,那么函数首先调用 nodes_empty() 判断 NODEMASK 是否为空,如果不为空,那么函数执行 1 次,且 node 为 0. 函数在 BiscuitOS 的使用如下:

cd BiscuitOS
make menuconfig

  [*] Package  --->
      [*] nodemask  --->
          [*] for_each_node_mask  --->

开发者可以参考文档进行使用:

独立内核模块代码 – 独立程序开发办法

测试代码
/*
 * Nodemask: for_each_node_mask
 *
 * (C) 2021.01.10 BuddyZhang1 <buddy.zhang@aliyun.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */

#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>

/* Module initialize entry */
static int __init BiscuitOS_init(void)
{
        nodemask_t node_a;
        int idx;

        /* Clear all */
        nodes_clear(node_a);

        /* set special node */
        node_set(12, node_a);
        node_set(16, node_a);

        /* iterator */
        for_each_node_mask(idx, node_a)
                printk("Online-node: %d\n", idx);

        printk("Hello modules on BiscuitOS\n");

        return 0;
}

/* Module exit entry */
static void __exit BiscuitOS_exit(void)
{
}

module_init(BiscuitOS_init);
module_exit(BiscuitOS_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("BiscuitOS <buddy.zhang@aliyun.com>");
MODULE_DESCRIPTION("Common Device driver on BiscuitOS");
BiscuitOS 运行结果
/lib/modules/5.0.0/extra # insmod for_each_node_mask-default.ko 
for_each_node_mask_default: loading out-of-tree module taints kernel.
Online-node: 12
Online-node: 16
Hello modules on BiscuitOS
/lib/modules/5.0.0/extra #

first_node

next_node


init_nodemask_of_node

init_nodemask_of_node() 函数用于初始化指定的 NODEMASK,并将指定的 node 置位。参数 node 指向需要置位的位置,参数 mask 指向 NODEMASK. 函数通过调用 nodes_clear() 函数将 NODEMASK 中所有的 node 清零,接着函数调用 node_set() 函数将 NODEMASK 指定的 node 置位. 函数在 BiscuitOS 的使用如下:

cd BiscuitOS
make menuconfig

  [*] Package  --->
      [*] nodemask  --->
          [*] nodes_and  --->

开发者可以参考文档进行使用:

独立内核模块代码 – 独立程序开发办法

测试代码
/*
 * Nodemask: init_nodemask_of_node
 *
 * (C) 2021.01.10 BuddyZhang1 <buddy.zhang@aliyun.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */

#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>

/* Module initialize entry */
static int __init BiscuitOS_init(void)
{
        nodemask_t node_a;
        int i;

        /* Initialize and set special node */
        init_nodemask_of_node(&node_a, 12);

        /* interate */
        for_each_node_mask(i, node_a)
                printk("Online-node: %d\n", i);

        printk("Hello modules on BiscuitOS\n");

        return 0;
}

/* Module exit entry */
static void __exit BiscuitOS_exit(void)
{
}

module_init(BiscuitOS_init);
module_exit(BiscuitOS_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("BiscuitOS <buddy.zhang@aliyun.com>");
MODULE_DESCRIPTION("Common Device driver on BiscuitOS");
BiscuitOS 运行结果
/lib/modules/5.0.0/extra # insmod init_nodemask_of_node-default.ko 
init_nodemask_of_node_default: loading out-of-tree module taints kernel.
Online-node: 12
Hello modules on BiscuitOS
/lib/modules/5.0.0/extra #

nodes_clear

node_set


first_unset_node/__first_unset_node

first_unset_node/__first_unset_node 函数用于从指定的 NODEMASK 中找到第一个清零的 node。参数 mask 指向指定的 NODEMASK. 函数通过调用 find_first_zero_bit() 函数在 NODEMASK 中找到第一个清零的 bit,然后将找到的结果与 MAX_NUMNODES 进行比较,以此确认找到的 node 没有越界. 函数在 BiscuitOS 的使用如下:

cd BiscuitOS
make menuconfig

  [*] Package  --->
      [*] nodemask  --->
          [*] first_unset_node  --->

开发者可以参考文档进行使用:

独立内核模块代码 – 独立程序开发办法

测试代码
/*
 * Nodemask:first_unset_node
 *
 * (C) 2021.01.10 BuddyZhang1 <buddy.zhang@aliyun.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */

#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>

/* Module initialize entry */
static int __init BiscuitOS_init(void)
{
        nodemask_t node_a;

        /* set all bits */
        nodes_setall(node_a);

        /* clear special bits */
        node_clear(12, node_a);

        /* first lowest clear bit */
        printk("The first clear bit: %d\n", first_unset_node(node_a));

        printk("Hello modules on BiscuitOS\n");

        return 0;
}

/* Module exit entry */
static void __exit BiscuitOS_exit(void)
{
}

module_init(BiscuitOS_init);
module_exit(BiscuitOS_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("BiscuitOS <buddy.zhang@aliyun.com>");
MODULE_DESCRIPTION("Common Device driver on BiscuitOS");
BiscuitOS 运行结果
/lib/modules/5.0.0/extra # insmod first_unset_node-default.ko 
first_unset_node_default: loading out-of-tree module taints kernel.
The first clear bit: 12
Hello modules on BiscuitOS
/lib/modules/5.0.0/extra #

find_first_zero_bit


next_node_in/__next_node_in

next_node_in/__next_node_in 函数用于在 NODEMASK 中从指定 node 中开始查找第一个置位的 node,如果没有找到,那么函数继续从第一个 node 开始查找。参数 n 指明从指定的 node 位置,src 参数用于指向需要查找的 NODEMASK. 函数核心在 __next_node_in() 函数中实现,函数首先在 14 行通过调用 __next_node() 函数获得指定的置位位置,如果找到,则返回; 反之如果没有找到,那么函数调用 __first_node() 函数从头开始查找. 函数在 BiscuitOS 的使用如下:

cd BiscuitOS
make menuconfig

  [*] Package  --->
      [*] nodemask  --->
          [*] next_node_in  --->

开发者可以参考文档进行使用:

独立内核模块代码 – 独立程序开发办法

测试代码
/*
 * Nodemask:next_node_in
 *
 * (C) 2021.01.10 BuddyZhang1 <buddy.zhang@aliyun.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */

#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>

/* Module initialize entry */
static int __init BiscuitOS_init(void)
{
        nodemask_t node_a;

        /* Clear all bits */
        nodes_clear(node_a);

        /* Set special bits */
        node_set(12, node_a);

        /* next lowest set bit */
        printk("The next bit for 13th: %d\n", next_node_in(13, node_a));

        printk("Hello modules on BiscuitOS\n");

        return 0;
}

/* Module exit entry */
static void __exit BiscuitOS_exit(void)
{
}

module_init(BiscuitOS_init);
module_exit(BiscuitOS_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("BiscuitOS <buddy.zhang@aliyun.com>");
MODULE_DESCRIPTION("Common Device driver on BiscuitOS");
BiscuitOS 运行结果
/lib/modules/5.0.0/extra # insmod next_node_in-default.ko 
next_node_in_default: loading out-of-tree module taints kernel.
The next bit for 13th: 12
Hello modules on BiscuitOS
/lib/modules/5.0.0/extra #

__first_node

first_node

__next_node


next_node/__next_node

next_node/__next_node 函数用于在 NODEMASK 中获得从指定 node 之后第一个置位的 node,参数 n 指向开始查找的位置,src 指向查找的 NODEMASK. 函数通过调用 find_next_bit() 函数从 NDOEMASK 中的指定位置开始查找第一个置位的 node,然后将查找的结果与 MAX_NUMNODES 进行比较,以确保查找的结果没有越界。函数在 BiscuitOS 的使用如下:

cd BiscuitOS
make menuconfig

  [*] Package  --->
      [*] nodemask  --->
          [*] next_node  --->

开发者可以参考文档进行使用:

独立内核模块代码 – 独立程序开发办法

测试代码
/*
 * Nodemask:next_node
 *
 * (C) 2021.01.10 BuddyZhang1 <buddy.zhang@aliyun.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */

#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>

/* Module initialize entry */
static int __init BiscuitOS_init(void)
{
        nodemask_t node_a;

        /* Clear all bits */
        nodes_clear(node_a);

        /* Set special bits */
        node_set(12, node_a);
        node_set(16, node_a);
        node_set(17, node_a);

        /* next lowest set bit */
        printk("The next bit for 13th: %d\n", next_node(13, node_a));

        printk("Hello modules on BiscuitOS\n");

        return 0;
}

/* Module exit entry */
static void __exit BiscuitOS_exit(void)
{
}

module_init(BiscuitOS_init);
module_exit(BiscuitOS_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("BiscuitOS <buddy.zhang@aliyun.com>");
MODULE_DESCRIPTION("Common Device driver on BiscuitOS");
BiscuitOS 运行结果
/lib/modules/5.0.0/extra # insmod next_node-default.ko 
next_node_default: loading out-of-tree module taints kernel.
The next bit for 13th: 16
Hello modules on BiscuitOS
/lib/modules/5.0.0/extra #

find_next_bit


first_node/__first_node

first_node/__first_node 函数用于获得 NODEMASK 从最低位开始第一个置位的 node。 参数 src 指向指定的 NODEMASK. 函数通过调用 find_first_bit() 函数实现查找逻辑,并在 MAX_NUMNODES 和找到的 node 中取最小值,确保查找不越界. 函数在 BiscuitOS 的使用如下:

cd BiscuitOS
make menuconfig

  [*] Package  --->
      [*] nodemask  --->
          [*] first_node  --->

开发者可以参考文档进行使用:

独立内核模块代码 – 独立程序开发办法

测试代码
/*
 * Nodemask:first_node
 *
 * (C) 2021.01.10 BuddyZhang1 <buddy.zhang@aliyun.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */

#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>

/* Module initialize entry */
static int __init BiscuitOS_init(void)
{
        nodemask_t node_a;

        /* Clear all bits */
        nodes_clear(node_a);

        /* Set special bits */
        node_set(12, node_a);
        node_set(14, node_a);

        /* first lowest set bit */
        printk("The first lowest set bit: %d\n", first_node(node_a));

        printk("Hello modules on BiscuitOS\n");

        return 0;
}

/* Module exit entry */
static void __exit BiscuitOS_exit(void)
{
}

module_init(BiscuitOS_init);
module_exit(BiscuitOS_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("BiscuitOS <buddy.zhang@aliyun.com>");
MODULE_DESCRIPTION("Common Device driver on BiscuitOS");
BiscuitOS 运行结果
/lib/modules/5.0.0/extra # insmod first_node-default.ko 
first_node_default: loading out-of-tree module taints kernel.
The first lowest set bit: 12
Hello modules on BiscuitOS
/lib/modules/5.0.0/extra # 

find_first_bit


nodes_shift_left/__nodes_shift_left

nodes_shift_left/__nodes_shift_left 函数的作用是将指定的 NODEMASK 的所有 node 向左移动指定的位数,并将左移的结果存储在指定的 NODEMASK 中。参数 dst 用于存储左移之后的结果,src 参数用于指向需要左移的 NODEMASK,参数 n 指明需要左移的位数. 函数在 BiscuitOS 的使用如下:

cd BiscuitOS
make menuconfig

  [*] Package  --->
      [*] nodemask  --->
          [*] nodes_shift_left  --->

开发者可以参考文档进行使用:

独立内核模块代码 – 独立程序开发办法

测试代码
/*
 * Nodemask: nodes_shift_left
 *
 * (C) 2021.01.10 BuddyZhang1 <buddy.zhang@aliyun.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */

#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>

/* Module initialize entry */
static int __init BiscuitOS_init(void)
{
        nodemask_t node_a;
        nodemask_t node_b;
        int i;

        /* Clear all bits */
        nodes_clear(node_a);

        /* Set special bits */
        node_set(12, node_a);

        /* Shift left */
        nodes_shift_left(node_b, node_a, 2);

        /* iterate all node */
        for_each_node_mask(i, node_b)
                printk("Online-node: %d\n", i);

        printk("Hello modules on BiscuitOS\n");

        return 0;
}

/* Module exit entry */
static void __exit BiscuitOS_exit(void)
{
}

module_init(BiscuitOS_init);
module_exit(BiscuitOS_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("BiscuitOS <buddy.zhang@aliyun.com>");
MODULE_DESCRIPTION("Common Device driver on BiscuitOS");
BiscuitOS 运行结果
/lib/modules/5.0.0/extra # insmod nodes_shift_left-default.ko 
nodes_shift_left_default: loading out-of-tree module taints kernel.
Online-node: 14
Hello modules on BiscuitOS
/lib/modules/5.0.0/extra #

bitmap_shift_left


nodes_shift_right/__node_shift_right

nodes_shift_right/__node_shift_right 函数用于将指定的 NODEMASK 中所有 node 右移指定的位数,并将结果存储在指定的 NODEMASK. 参数 dst 用于存储右移之后的结果,src 参数用于指向需要右移的 NODEMASK,参数 n 指明右移的位数. 函数在 BiscuitOS 的使用如下:

cd BiscuitOS
make menuconfig

  [*] Package  --->
      [*] nodemask  --->
          [*] nodes_shift_right  --->

开发者可以参考文档进行使用:

独立内核模块代码 – 独立程序开发办法

测试代码
/*
 * Nodemask: nodes_shift_right
 *
 * (C) 2021.01.10 BuddyZhang1 <buddy.zhang@aliyun.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */

#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>

/* Module initialize entry */
static int __init BiscuitOS_init(void)
{
        nodemask_t node_a;
        nodemask_t node_b;
        int i;

        /* Clear all bits */
        nodes_clear(node_a);

        /* Set special bits */
        node_set(12, node_a);

        /* Shift right */
        nodes_shift_right(node_b, node_a, 2);

        /* iterate all node */
        for_each_node_mask(i, node_b)
                printk("Online-node: %d\n", i);

        printk("Hello modules on BiscuitOS\n");

        return 0;
}

/* Module exit entry */
static void __exit BiscuitOS_exit(void)
{
}

module_init(BiscuitOS_init);
module_exit(BiscuitOS_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("BiscuitOS <buddy.zhang@aliyun.com>");
MODULE_DESCRIPTION("Common Device driver on BiscuitOS")
BiscuitOS 运行结果
/lib/modules/5.0.0/extra # insmod nodes_shift_right-default.ko 
nodes_shift_right_default: loading out-of-tree module taints kernel.
Online-node: 10
Hello modules on BiscuitOS
/lib/modules/5.0.0/extra # 

bitmap_shift_right


nodes_weight/__nodes_weight

nodes_weight/__nodes_weight 函数用于获得 NODEMASK 中置位 node 的数量。参数 nodemask 用于指向需要检测的 NODEMASK. 函数在 BiscuitOS 的使用如下:

cd BiscuitOS
make menuconfig

  [*] Package  --->
      [*] nodemask  --->
          [*] nodes_weight  --->

开发者可以参考文档进行使用:

独立内核模块代码 – 独立程序开发办法

测试代码
/*
 * Nodemask: nodes_weight
 *
 * (C) 2021.01.10 BuddyZhang1 <buddy.zhang@aliyun.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */

#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>

/* Module initialize entry */
static int __init BiscuitOS_init(void)
{
        nodemask_t node_a;
        int weight;

        /* Clear all bits */
        nodes_clear(node_a);

        /* Set special bits */
        node_set(2, node_a);
        node_set(4, node_a);

        weight = nodes_weight(node_a);
        printk("NODE A weight %d\n", weight);

        printk("Hello modules on BiscuitOS\n");

        return 0;
}

/* Module exit entry */
static void __exit BiscuitOS_exit(void)
{
}

module_init(BiscuitOS_init);
module_exit(BiscuitOS_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("BiscuitOS <buddy.zhang@aliyun.com>");
MODULE_DESCRIPTION("Common Device driver on BiscuitOS");
BiscuitOS 运行结果
/lib/modules/5.0.0/extra # insmod nodes_weight-default.ko 
nodes_weight_default: loading out-of-tree module taints kernel.
NODE A weight 2
Hello modules on BiscuitOS
/lib/modules/5.0.0/extra #


nodes_full/__nodes_full

nodes_full/__nodes_full 函数用于判断 NODEMASK 的所有 node 都已经置位,如果都置位,那么返回真,反之为假。参数 src 指向需要检测的 NODEMASK. 函数在 BiscuitOS 的使用如下:

cd BiscuitOS
make menuconfig

  [*] Package  --->
      [*] nodemask  --->
          [*] nodes_full  --->

开发者可以参考文档进行使用:

独立内核模块代码 – 独立程序开发办法

测试代码
/*
 * Nodemask: nodes_full
 *
 * (C) 2021.01.10 BuddyZhang1 <buddy.zhang@aliyun.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */

#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>

/* Module initialize entry */
static int __init BiscuitOS_init(void)
{
        nodemask_t node_a;
        nodemask_t node_b;

        /* Clear all bits */
        nodes_clear(node_a);
        nodes_setall(node_b);

        /* Set special bits */
        node_set(2, node_a);

        if (nodes_full(node_b))
                printk("Node b is full.\n");

        if (!nodes_full(node_a))
                printk("Node a is not full.\n");

        printk("Hello modules on BiscuitOS\n");

        return 0;
}

/* Module exit entry */
static void __exit BiscuitOS_exit(void)
{
}

module_init(BiscuitOS_init);
module_exit(BiscuitOS_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("BiscuitOS <buddy.zhang@aliyun.com>");
MODULE_DESCRIPTION("Common Device driver on BiscuitOS");
BiscuitOS 运行结果
/lib/modules/5.0.0/extra # insmod nodes_full-default.ko 
nodes_full_default: loading out-of-tree module taints kernel.
Node b is full.
Node a is not full.
Hello modules on BiscuitOS
/lib/modules/5.0.0/extra #


nodes_empty/__nodes_empty

nodes_empty/__nodes_empty 函数用于判断 NODEMASK 为空,即 NODEMASK 里面所有 node 都清零。参数 src 指向特定的 NODEMASK. 函数在 BiscuitOS 的使用如下:

cd BiscuitOS
make menuconfig

  [*] Package  --->
      [*] nodemask  --->
          [*] nodes_empty  --->

开发者可以参考文档进行使用:

独立内核模块代码 – 独立程序开发办法

测试代码
/*
 * Nodemask: nodes_empty
 *
 * (C) 2021.01.10 BuddyZhang1 <buddy.zhang@aliyun.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */

#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>

/* Module initialize entry */
static int __init BiscuitOS_init(void)
{
        nodemask_t node_a;
        nodemask_t node_b;

        /* Clear all bits */
        nodes_clear(node_a);
        nodes_clear(node_b);

        /* Set special bits */
        node_set(2, node_a);

        if (!nodes_empty(node_a))
                printk("NODEMASK A is not emtpy.\n");

        if (nodes_empty(node_b))
                printk("NODEMASK B is empty.\n");

        printk("Hello modules on BiscuitOS\n");

        return 0;
}

/* Module exit entry */
static void __exit BiscuitOS_exit(void)
{
}

module_init(BiscuitOS_init);
module_exit(BiscuitOS_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("BiscuitOS <buddy.zhang@aliyun.com>");
MODULE_DESCRIPTION("Common Device driver on BiscuitOS");
BiscuitOS 运行结果
/lib/modules/5.0.0/extra # insmod nodes_empty-default.ko 
nodes_empty_default: loading out-of-tree module taints kernel.
NODEMASK A is not emtpy.
NODEMASK B is empty.
Hello modules on BiscuitOS
/lib/modules/5.0.0/extra # 


nodes_subset/__nodes_subset

nodes_subset/__nodes_subset 函数用于判断两个 NODEMASK 之间存在子集关系。参数 src1 用于判断是否为参数 src2 的子集。函数在 BiscuitOS 的使用如下:

cd BiscuitOS
make menuconfig

  [*] Package  --->
      [*] nodemask  --->
          [*] nodes_subset  --->

开发者可以参考文档进行使用:

独立内核模块代码 – 独立程序开发办法

测试代码
/*
 * Nodemask: nodes_subset
 *
 * (C) 2021.01.10 BuddyZhang1 <buddy.zhang@aliyun.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */

#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>

/* Module initialize entry */
static int __init BiscuitOS_init(void)
{
        nodemask_t node_a;
        nodemask_t node_b;
        nodemask_t node_c;

        /* Clear all bits */
        nodes_clear(node_a);
        nodes_clear(node_b);
        nodes_clear(node_c);

        /* Set special bits */
        node_set(2, node_a);
        node_set(4, node_a);
        node_set(2, node_b);
        node_set(1, node_c);

        if (nodes_subset(node_b, node_a))
                printk("B is subset of A.\n");

        if (!nodes_subset(node_c, node_a))
                printk("C is not subset of A\n");

        printk("Hello modules on BiscuitOS\n");

        return 0;
}

/* Module exit entry */
static void __exit BiscuitOS_exit(void)
{
}

module_init(BiscuitOS_init);
module_exit(BiscuitOS_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("BiscuitOS <buddy.zhang@aliyun.com>");
MODULE_DESCRIPTION("Common Device driver on BiscuitOS");
BiscuitOS 运行结果
/lib/modules/5.0.0/extra # insmod nodes_subset-default.ko 
nodes_subset_default: loading out-of-tree module taints kernel.
B is subset of A.
C is not subset of A
Hello modules on BiscuitOS
/lib/modules/5.0.0/extra #


nodes_intersects/__nodes_intersects_

nodes_intersects/__nodes_intersects 函数用于判断两个 NODEMASK 之间是否存在交集,也就是是否用相同置位的 node。参数 src1 和 src2 分别指向对比的 NODEMASK. 函数在 BiscuitOS 的使用如下:

cd BiscuitOS
make menuconfig

  [*] Package  --->
      [*] nodemask  --->
          [*] nodes_intersects  --->

开发者可以参考文档进行使用:

独立内核模块代码 – 独立程序开发办法

测试代码
/*
 * Nodemask: nodes_intersects
 *
 * (C) 2021.01.10 BuddyZhang1 <buddy.zhang@aliyun.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */

#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>

/* Module initialize entry */
static int __init BiscuitOS_init(void)
{
        nodemask_t node_a;
        nodemask_t node_b;

        /* Clear all bits */
        nodes_clear(node_a);
        nodes_clear(node_b);

        /* Set special bits */
        node_set(2, node_a);
        node_set(4, node_a);
        node_set(2, node_b);

        if (nodes_intersects(node_a, node_b))
                printk("Intersect between a and b.\n");

        printk("Hello modules on BiscuitOS\n");

        return 0;
}

/* Module exit entry */
static void __exit BiscuitOS_exit(void)
{
}

module_init(BiscuitOS_init);
module_exit(BiscuitOS_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("BiscuitOS <buddy.zhang@aliyun.com>");
MODULE_DESCRIPTION("Common Device driver on BiscuitOS");
BiscuitOS 运行结果
/lib/modules/5.0.0/extra # insmod nodes_intersects-default.ko 
nodes_intersects_default: loading out-of-tree module taints kernel.
Intersect between a and b.
Hello modules on BiscuitOS
/lib/modules/5.0.0/extra #


nodes_equal/__nodes_equal

nodes_equal/__nodes_equal 函数用于对比两个 NDOEMASK 是否相等,如果相等,则返回 true, 反之返回 false. 参数 src1 和 src2 用于指向对比的两个 NODEMASK. 函数在 BiscuitOS 的使用如下:

cd BiscuitOS
make menuconfig

  [*] Package  --->
      [*] nodemask  --->
          [*] nodes_equal  --->

开发者可以参考文档进行使用:

独立内核模块代码 – 独立程序开发办法

测试代码
/*
 * Nodemask: nodes_equal
 *
 * (C) 2021.01.10 BuddyZhang1 <buddy.zhang@aliyun.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */

#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>

/* Module initialize entry */
static int __init BiscuitOS_init(void)
{
        nodemask_t node_a;
        nodemask_t node_b;
        nodemask_t node_c;
        int i;

        /* Clear all bits */
        nodes_clear(node_a);
        nodes_clear(node_b);
        nodes_clear(node_c);

        /* Set special bits */
        node_set(2, node_a);
        node_set(4, node_a);
        node_set(2, node_b);
        node_set(2, node_c);

        if (!nodes_equal(node_a, node_b))
                printk("node_a doesn't equal node_b\n");

        if (nodes_equal(node_b, node_c))
                printk("node_b equal node_c\n");

        printk("Hello modules on BiscuitOS\n");

        return 0;
}

/* Module exit entry */
static void __exit BiscuitOS_exit(void)
{
}

module_init(BiscuitOS_init);
module_exit(BiscuitOS_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("BiscuitOS <buddy.zhang@aliyun.com>");
MODULE_DESCRIPTION("Common Device driver on BiscuitOS");
BiscuitOS 运行结果
/lib/modules/5.0.0/extra # insmod nodes_equal-default.ko 
nodes_equal_default: loading out-of-tree module taints kernel.
node_a doesn't equal node_b
node_b equal node_c
Hello modules on BiscuitOS
/lib/modules/5.0.0/extra #


nodes_complement/__nodes_complement

nodes_complement/__nodes_complement 函数用于获得指定 NODEMASK 所有 node 取反值。参数 dst 用于存储取反之后的结果,src 用于取反的 NODEMASK. 函数在 BiscuitOS 的使用如下:

cd BiscuitOS
make menuconfig

  [*] Package  --->
      [*] nodemask  --->
          [*] nodes_complement  --->

开发者可以参考文档进行使用:

独立内核模块代码 – 独立程序开发办法

测试代码
/*
 * Nodemask: nodes_complement
 *
 * (C) 2021.01.10 BuddyZhang1 <buddy.zhang@aliyun.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */

#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>

/* Module initialize entry */
static int __init BiscuitOS_init(void)
{
        nodemask_t node_a;
        nodemask_t node_b;
        int i;

        /* Clear all bits */
        nodes_clear(node_a);

        /* Set special bits */
        node_set(2, node_a);

        nodes_complement(node_b, node_a);

        /* Iterate set bits */
        for_each_node_mask(i, node_b)
                printk("Online-node: %d\n", i);

        printk("Hello modules on BiscuitOS\n");

        return 0;
}

/* Module exit entry */
static void __exit BiscuitOS_exit(void)
{
}

module_init(BiscuitOS_init);
module_exit(BiscuitOS_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("BiscuitOS <buddy.zhang@aliyun.com>");
MODULE_DESCRIPTION("Common Device driver on BiscuitOS");
BiscuitOS 运行结果
/lib/modules/5.0.0/extra # insmod nodes_complement-default.ko 
nodes_complement_default: loading out-of-tree module taints kernel.
Online-node: 0
Online-node: 1
Online-node: 3
Online-node: 4
Online-node: 5
Online-node: 6
Online-node: 7
Online-node: 8
Online-node: 9
Online-node: 10
Online-node: 11
Online-node: 12
Online-node: 13
Online-node: 14
Online-node: 15
Online-node: 16
Online-node: 17
Online-node: 18
Online-node: 19
Online-node: 20
Online-node: 21
Online-node: 22
Online-node: 23
Online-node: 24
Online-node: 25
Online-node: 26
Online-node: 27
Online-node: 28
Online-node: 29
Online-node: 30
Online-node: 31
Online-node: 32
Online-node: 33
Online-node: 34
Online-node: 35
Online-node: 36
Online-node: 37
Online-node: 38
Online-node: 39
Online-node: 40
Online-node: 41
Online-node: 42
Online-node: 43
Online-node: 44
Online-node: 45
Online-node: 46
Online-node: 47
Online-node: 48
Online-node: 49
Online-node: 50
Online-node: 51
Online-node: 52
Online-node: 53
Online-node: 54
Online-node: 55
Online-node: 56
Online-node: 57
Online-node: 58
Online-node: 59
Online-node: 60
Online-node: 61
Online-node: 62
Online-node: 63
Hello modules on BiscuitOS
/lib/modules/5.0.0/extra #


nodes_andnot/__nodes_andnot

nodes_andnot/__nodes_andnot 函数的作用是将一个 NODEMASK 与另外一个 NODEMASK 所有 node 取反之后的值相与,并将结果存储在指定的 NODEMASK。参数 dst 用于存储结果的 NODEMASK, 参数 src1 指定第一个 NODEMASK, 参数 src2 指定第二个用于取反操作的 NODEMASK,函数在 BiscuitOS 的使用如下:

cd BiscuitOS
make menuconfig

  [*] Package  --->
      [*] nodemask  --->
          [*] nodes_andnot  --->

开发者可以参考文档进行使用:

独立内核模块代码 – 独立程序开发办法

测试代码
/*
 * Nodemask: nodes_andnot
 *
 * (C) 2021.01.10 BuddyZhang1 <buddy.zhang@aliyun.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */

#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>

/* Module initialize entry */
static int __init BiscuitOS_init(void)
{
        nodemask_t node_a;
        nodemask_t node_b;
        nodemask_t node_c;
        int i;

        /* Clear all bits */
        nodes_clear(node_a);
        nodes_clear(node_b);

        /* Set special bits */
        node_set(2, node_a);
        node_set(3, node_b);

        /* NODEMASK intersection */
        nodes_andnot(node_c, node_a, node_b);

        /* Iterate set bits */
        for_each_node_mask(i, node_c)
                printk("Online-node: %d\n", i);

        printk("Hello modules on BiscuitOS\n");

        return 0;
}

/* Module exit entry */
static void __exit BiscuitOS_exit(void)
{
}

module_init(BiscuitOS_init);
module_exit(BiscuitOS_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("BiscuitOS <buddy.zhang@aliyun.com>");
MODULE_DESCRIPTION("Common Device driver on BiscuitOS");
BiscuitOS 运行结果
/lib/modules/5.0.0/extra # insmod nodes_andnot-default.ko 
nodes_andnot_default: loading out-of-tree module taints kernel.
Online-node: 2
Hello modules on BiscuitOS
/lib/modules/5.0.0/extra #


nodes_xor/__nodes_xor

nodes_xor/__nodes_xor 函数用于将两个 NODEMASK 的每个 node 异或的结果存储在指定的 NODEMASK 中。参数 dst 用于存储结果的 NODEMASK, 参数 src1 和 src2 指定参与异或的 NODEMASK. 函数在 BiscuitOS 的使用如下:

cd BiscuitOS
make menuconfig

  [*] Package  --->
      [*] nodemask  --->
          [*] nodes_xor  --->

开发者可以参考文档进行使用:

独立内核模块代码 – 独立程序开发办法

测试代码
/*
 * Nodemask: nodes_xor
 *
 * (C) 2021.01.10 BuddyZhang1 <buddy.zhang@aliyun.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */

#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>

/* Module initialize entry */
static int __init BiscuitOS_init(void)
{
        nodemask_t node_a;
        nodemask_t node_b;
        nodemask_t node_c;
        int i;

        /* Clear all bits */
        nodes_clear(node_a);
        nodes_clear(node_b);

        /* Set special bits */
        node_set(2, node_a);
        node_set(3, node_b);

        /* NODEMASK intersection */
        nodes_xor(node_c, node_a, node_b);

        /* Iterate set bits */
        for_each_node_mask(i, node_c)
                printk("Online-node: %d\n", i);

        printk("Hello modules on BiscuitOS\n");

        return 0;
}

/* Module exit entry */
static void __exit BiscuitOS_exit(void)
{
}

module_init(BiscuitOS_init);
module_exit(BiscuitOS_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("BiscuitOS <buddy.zhang@aliyun.com>");
MODULE_DESCRIPTION("Common Device driver on BiscuitOS");
BiscuitOS 运行结果
/lib/modules/5.0.0/extra # insmod nodes_xor-default.ko 
nodes_xor_default: loading out-of-tree module taints kernel.
Online-node: 2
Online-node: 3
Hello modules on BiscuitOS
/lib/modules/5.0.0/extra # 


nodes_or/__nodes_or

nodes_or/__nodes_or 函数用于将两个 NODEMASK 的每个 node 相或的结果存储在指定的 NODEMASK 中。参数 dst 指向存储结果的 NODEMASK,参数 src1 和 src2 指向相与的两个 NODEMASK. 函数在 BiscuitOS 的使用如下:

cd BiscuitOS
make menuconfig

  [*] Package  --->
      [*] nodemask  --->
          [*] nodes_or  --->

开发者可以参考文档进行使用:

独立内核模块代码 – 独立程序开发办法

测试代码
/*
 * Nodemask: nodes_or
 *
 * (C) 2021.01.10 BuddyZhang1 <buddy.zhang@aliyun.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */

#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>

/* Module initialize entry */
static int __init BiscuitOS_init(void)
{
        nodemask_t node_a;
        nodemask_t node_b;
        nodemask_t node_c;
        int i;

        /* Clear all bits */
        nodes_clear(node_a);
        nodes_clear(node_b);

        /* Set special bits */
        node_set(2, node_a);
        node_set(3, node_b);

        /* NODEMASK intersection */
        nodes_or(node_c, node_a, node_b);

        /* Iterate set bits */
        for_each_node_mask(i, node_c)
                printk("Online-node: %d\n", i);

        printk("Hello modules on BiscuitOS\n");

        return 0;
}

/* Module exit entry */
static void __exit BiscuitOS_exit(void)
{
}

module_init(BiscuitOS_init);
module_exit(BiscuitOS_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("BiscuitOS <buddy.zhang@aliyun.com>");
MODULE_DESCRIPTION("Common Device driver on BiscuitOS");
BiscuitOS 运行结果
/lib/modules/5.0.0/extra # insmod nodes_or-default.ko 
nodes_or_default: loading out-of-tree module taints kernel.
Online-node: 2
Online-node: 3
Hello modules on BiscuitOS
/lib/modules/5.0.0/extra #


nodes_and/__nodes_and

nodes_and/__nodes_and 函数的作用是将两个 NODEMASK 相与之后的结果存储在指定的 NODEMASK. 该操作会将 NODEMASK 中每个 node 进行与操作。参数 dst 指向存储结果的 NODEMASK, 参数 src1 和 src2 为相与的两个 NODEMASK. 函数在 BiscuitOS 的使用如下:

cd BiscuitOS
make menuconfig

  [*] Package  --->
      [*] nodemask  --->
          [*] node_set  --->

开发者可以参考文档进行使用:

独立内核模块代码 – 独立程序开发办法

测试代码
/*
 * Nodemask: nodes_and
 *
 * (C) 2021.01.10 BuddyZhang1 <buddy.zhang@aliyun.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */

#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>

/* Module initialize entry */
static int __init BiscuitOS_init(void)
{
        nodemask_t node_a;
        nodemask_t node_b;
        nodemask_t node_c;
        int i;

        /* Clear all bits */
        nodes_clear(node_a);
        nodes_clear(node_b);

        /* Set special bits */
        node_set(2, node_a);
        node_set(3, node_a);
        node_set(2, node_b);

        /* NODEMASK intersection */
        nodes_and(node_c, node_a, node_b);

        /* Iterate set bits */
        for_each_node_mask(i, node_c)
                printk("Online-node: %d\n", i);

        printk("Hello modules on BiscuitOS\n");

        return 0;
}

/* Module exit entry */
static void __exit BiscuitOS_exit(void)
{
}

module_init(BiscuitOS_init);
module_exit(BiscuitOS_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("BiscuitOS <buddy.zhang@aliyun.com>");
MODULE_DESCRIPTION("Common Device driver on BiscuitOS");
BiscuitOS 运行结果
/lib/modules/5.0.0/extra # insmod nodes_and-default.ko 
nodes_and_default: loading out-of-tree module taints kernel.
Online-node: 2
Hello modules on BiscuitOS
/lib/modules/5.0.0/extra #


node_test_and_set/__node_test_and_set

node_test_and_set/__node_test_and_set 函数用于检测 NODEMASK 指定 NODE 是否置位,如果是返回 true,反之返回 false,并且将指定的 NODE 置位。参数 node 只用指定需要检测的 NODE, 参数 nodemask 指向指定的 NODEMASK. 函数在 BiscuitOS 的使用如下:

cd BiscuitOS
make menuconfig

  [*] Package  --->
      [*] nodemask  --->
          [*] node_set  --->

开发者可以参考文档进行使用:

独立内核模块代码 – 独立程序开发办法

测试代码
/*
 * Nodemask: node_test_and_set
 *
 * (C) 2021.01.10 BuddyZhang1 <buddy.zhang@aliyun.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */

#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>

/* Module initialize entry */
static int __init BiscuitOS_init(void)
{
        nodemask_t node;

        /* Clear all bits */
        nodes_clear(node);

        if (!node_test_and_set(2, node))
                printk("NODE 2 is clear.\n");

        if (node_isset(2, node))
                printk("NODE 2 is set.\n");

        if (node_test_and_set(2, node))
                printk("NODE 2 has set.\n");

        printk("Hello modules on BiscuitOS\n");

        return 0;
}

/* Module exit entry */
static void __exit BiscuitOS_exit(void)
{
}

module_init(BiscuitOS_init);
module_exit(BiscuitOS_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("BiscuitOS <buddy.zhang@aliyun.com>");
MODULE_DESCRIPTION("Common Device driver on BiscuitOS");
BiscuitOS 运行结果
/lib/modules/5.0.0/extra # insmod node_test_and_set-default.ko 
node_test_and_set_default: loading out-of-tree module taints kernel.
NODE 2 is clear.
NODE 2 is set.
NODE 2 has set.
Hello modules on BiscuitOS


node_isset

node_isset() 函数用于检测 NODEMASK 中指定 NODE 是否置位,如果置位返回 true,反之返回 false. 参数 node 只用指定需要检测的 NODE, 参数 nodemask 指向指定的 NODEMASK, 函数在 BiscuitOS 的使用如下:

cd BiscuitOS
make menuconfig

  [*] Package  --->
      [*] nodemask  --->
          [*] node_isset  --->

开发者可以参考文档进行使用:

独立内核模块代码 – 独立程序开发办法

测试代码
/*
 * Nodemask: node_isset
 *
 * (C) 2021.01.10 BuddyZhang1 <buddy.zhang@aliyun.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */

#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>

/* Module initialize entry */
static int __init BiscuitOS_init(void)
{
        nodemask_t node;

        /* Clear all bits */
        nodes_clear(node);

        /* Set special bits */
        node_set(2, node);

        if (node_isset(2, node))
                printk("Node 2 is set.\n");

        if (!node_isset(3, node))
                printk("Node 3 is clear.\n");

        printk("Hello modules on BiscuitOS\n");

        return 0;
}

/* Module exit entry */
static void __exit BiscuitOS_exit(void)
{
}

module_init(BiscuitOS_init);
module_exit(BiscuitOS_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("BiscuitOS <buddy.zhang@aliyun.com>");
MODULE_DESCRIPTION("Common Device driver on BiscuitOS");
BiscuitOS 运行结果
/lib/modules/5.0.0/extra # insmod node_isset-default.ko 
node_isset_default: loading out-of-tree module taints kernel.
Node 2 is set.
Node 3 is clear.
Hello modules on BiscuitOS
/lib/modules/5.0.0/extra #


nodes_clear/__nodes_clear

nodes_clear()/__nodes_clear() 函数用于将 NODEMASK 中的所有 node 全部清零. 参数 nodemask 指向指定的 NODEMASK 函数在 BiscuitOS 的使用如下:

cd BiscuitOS
make menuconfig

  [*] Package  --->
      [*] nodemask  --->
          [*] nodes_clear  --->

开发者可以参考文档进行使用:

独立内核模块代码 – 独立程序开发办法

测试代码
/*
 * Nodemask: nodes_clear
 *
 * (C) 2021.01.10 BuddyZhang1 <buddy.zhang@aliyun.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */

#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>

/* Module initialize entry */
static int __init BiscuitOS_init(void)
{
        nodemask_t node;
        int i;

        /* Clear all bits */
        nodes_clear(node);

        if (!node_test_and_set(2, node))
                printk("Node 2 is clear.\n");

        if (node_test_and_set(2, node))
                printk("Node 2 is set before.\n");

        printk("Hello modules on BiscuitOS\n");

        return 0;
}

/* Module exit entry */
static void __exit BiscuitOS_exit(void)
{
}

module_init(BiscuitOS_init);
module_exit(BiscuitOS_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("BiscuitOS <buddy.zhang@aliyun.com>");
MODULE_DESCRIPTION("Common Device driver on BiscuitOS");
BiscuitOS 运行结果
/lib/modules/5.0.0/extra # insmod nodes_clear-default.ko 
nodes_clear_default: loading out-of-tree module taints kernel.
Node 2 is clear.
Node 2 is set before.
Hello modules on BiscuitOS
/lib/modules/5.0.0/extra #


nodes_setall/__nodes_setall

nodes_setall()/__nodes_setall() 函数用于将 NODEMASK 中所有 node 都置位. 参数 nodemask 指向指定的 NODEMASK 函数在 BiscuitOS 的使用如下:

cd BiscuitOS
make menuconfig

  [*] Package  --->
      [*] nodemask  --->
          [*] nodes_setall  --->

开发者可以参考文档进行使用:

独立内核模块代码 – 独立程序开发办法

测试代码
/*
 * Nodemask: nodes_setall
 *
 * (C) 2021.01.10 BuddyZhang1 <buddy.zhang@aliyun.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */

#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>

/* Module initialize entry */
static int __init BiscuitOS_init(void)
{
        nodemask_t node;
        int i;

        /* set all bits */
        nodes_setall(node);

        /* Clear special bits */
        node_clear(2, node);

        /* Iterate set bits */
        for_each_node_mask(i, node)
                printk("Online-node: %d\n", i);

        printk("Hello modules on BiscuitOS\n");

        return 0;
}

/* Module exit entry */
static void __exit BiscuitOS_exit(void)
{
}

module_init(BiscuitOS_init);
module_exit(BiscuitOS_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("BiscuitOS <buddy.zhang@aliyun.com>");
MODULE_DESCRIPTION("Common Device driver on BiscuitOS");
BiscuitOS 运行结果
/lib/modules/5.0.0/extra # insmod nodes_setall-default.ko 
nodes_setall_default: loading out-of-tree module taints kernel.
Online-node: 0
Online-node: 1
Online-node: 3
Online-node: 4
Online-node: 5
Online-node: 6
Online-node: 7
Online-node: 8
Online-node: 9
Online-node: 10
Online-node: 11
Online-node: 12
Online-node: 13
Online-node: 14
Online-node: 15
Online-node: 16
Online-node: 17
Online-node: 18
Online-node: 19
Online-node: 20
Online-node: 21
Online-node: 22
Online-node: 23
Online-node: 24
Online-node: 25
Online-node: 26
Online-node: 27
Online-node: 28
Online-node: 29
Online-node: 30
Online-node: 31
Online-node: 32
Online-node: 33
Online-node: 34
Online-node: 35
Online-node: 36
Online-node: 37
Online-node: 38
Online-node: 39
Online-node: 40
Online-node: 41
Online-node: 42
Online-node: 43
Online-node: 44
Online-node: 45
Online-node: 46
Online-node: 47
Online-node: 48
Online-node: 49
Online-node: 50
Online-node: 51
Online-node: 52
Online-node: 53
Online-node: 54
Online-node: 55
Online-node: 56
Online-node: 57
Online-node: 58
Online-node: 59
Online-node: 60
Online-node: 61
Online-node: 62
Online-node: 63
Hello modules on BiscuitOS
/lib/modules/5.0.0/extra #


node_clear/__node_clear

node_clear()/__node_clear() 函数用于将指定的 NODEMASK 指定 NODE 清零。参数 node 只用指定 NODE, 参数 nodemask 指向指定的 NODEMASK。函数在 BiscuitOS 的使用如下:

cd BiscuitOS
make menuconfig

  [*] Package  --->
      [*] nodemask  --->
          [*] node_clear  --->

开发者可以参考文档进行使用:

独立内核模块代码 – 独立程序开发办法

测试代码
/*
 * Nodemask: node_clear
 *
 * (C) 2021.01.10 BuddyZhang1 <buddy.zhang@aliyun.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */

#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>

/* Module initialize entry */
static int __init BiscuitOS_init(void)
{
        nodemask_t node;
        int i;

        /* Clear all bits */
        nodes_clear(node);

        /* Set special bits */
        node_set(2, node);

        /* Iterate set bits */
        for_each_node_mask(i, node)
                printk("Online-node: %d\n", i);

        printk("Hello modules on BiscuitOS\n");

        return 0;
}

/* Module exit entry */
static void __exit BiscuitOS_exit(void)
{
}

module_init(BiscuitOS_init);
module_exit(BiscuitOS_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("BiscuitOS <buddy.zhang@aliyun.com>");
MODULE_DESCRIPTION("Common Device driver on BiscuitOS");
BiscuitOS 运行结果
/lib/modules/5.0.0/extra # insmod node_clear-default.ko 
node_clear_default: loading out-of-tree module taints kernel.
Online-node: 2
Hello modules on BiscuitOS
/lib/modules/5.0.0/extra #


node_set/__node_set

node_set() 函数用于置位 NODEMASK 指定 node. 参数 node 指向需要设置的 NODE ID,参数 dst 指向 NODEMASK. 在函数中,dstp 包含一个 bitmap,函数调用 set_bit() 函数设置了该 bitmap 的指定 bit。node_set() 在 BiscuitOS 的使用如下:

cd BiscuitOS
make menuconfig

  [*] Package  --->
      [*] nodemask  --->
          [*] node_set  --->

开发者可以参考文档进行使用:

独立内核模块代码 – 独立程序开发办法

测试代码
/*
 * Nodemask: node_set
 *
 * (C) 2021.01.10 BuddyZhang1 <buddy.zhang@aliyun.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */

#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>

/* Module initialize entry */
static int __init BiscuitOS_init(void)
{
        nodemask_t node;
        int i;

        /* Clear all bits */
        nodes_clear(node);

        /* Set special bits */
        node_set(2, node);

        /* Iterate set bits */
        for_each_node_mask(i, node)
                printk("Online-node: %d\n", i);

        printk("Hello modules on BiscuitOS\n");

        return 0;
}

/* Module exit entry */
static void __exit BiscuitOS_exit(void)
{
}

module_init(BiscuitOS_init);
module_exit(BiscuitOS_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("BiscuitOS <buddy.zhang@aliyun.com>");
MODULE_DESCRIPTION("Common Device driver on BiscuitOS");
BiscuitOS 运行结果
/lib/modules/5.0.0/extra # insmod node_set-default.ko 
node_set_default: loading out-of-tree module taints kernel.
Online-node: 2
Hello modules on BiscuitOS
/lib/modules/5.0.0/extra #


附录

BiscuitOS Home

BiscuitOS Blog 2.0

Linux Kernel

Bootlin: Elixir Cross Referencer

捐赠一下吧 🙂

MMU