首页 > 其他分享 >QNX-19—QNX绑核优先级-1-理论

QNX-19—QNX绑核优先级-1-理论

时间:2024-06-04 15:23:13浏览次数:14  
标签:优先级 thread 19 QNX 线程 掩码 runmask 运行 size

一、Thread affinity翻译

翻译:
QNX Software Development Platform --> Programming --> Programmer's Guide --> Multicore Processing --> The impact of multicore
https://www.qnx.com/developers/docs/7.1/index.html#com.qnx.doc.neutrino.prog/topic/multicore_thread_affinity.html

多核环境中经常出现的一个问题可以这样表述:“我可以让一个处理器处理 GUI,另一个处理器处理数据库,另外两个处理器处理实时功能吗?”

答案是:“当然可以。”

这是通过线程亲和性实现的,线程亲和性是指将某些程序(甚至是程序中的线程)与特定处理器或处理器相关联的能力。

线程亲和性的工作原理如下。当线程启动时,其亲和性掩码(或运行掩码)被设置为允许它在所有处理器上运行。这意味着线程亲和性掩码没有继承,因此由线程使用带有 _NTO_TCTL_RUNMASK 控制标志的 ThreadCtl() 来设置其运行掩码:

if (ThreadCtl( _NTO_TCTL_RUNMASK, (void *)my_runmask) == -1) {
    /* An error occurred. */
}

运行掩码只是一个位图;每个位位置表示一个特定的处理器。例如,运行掩码 0x05(二进制 00000101)允许线程在处理器 0(0x01 位)和 2(0x04 位)上运行。

如果您使用 _NTO_TCTL_RUNMASK,则运行掩码的大小限制为 int(当前为 32 位)。默认被创建的线程不会继承运行掩码。#######
如果您想要支持比 int 中容纳的更多的处理器,或者想要设置继承掩码,则需要使用下面描述的 _NTO_TCTL_RUNMASK_GET_AND_SET_INHERIT 命令。

<sys/neutrino.h> 文件定义了一些可用于处理运行掩码的宏:

RMSK_SET(cpu, p)   //在 p 指向的掩码中设置 cpu 的位。
RMSK_CLR(cpu, p)   //清除 p 指向的掩码中 cpu 的位。
RMSK_ISSET(cpu, p) //确定 p 指向的掩码中 cpu 的位是否已设置。

CPU 从 0 开始编号。这些宏适用于任意长度的运行掩码。

绑定多处理 (BMP) 是 SMP 的一种变体,可让您指定进程或线程及其子进程可以在哪些处理器上运行。要指定这一点,请使用继承掩码。

要设置线程的继承掩码,请使用带有 _NTO_TCTL_RUNMASK_GET_AND_SET_INHERIT 控制标志的 ThreadCtl()。从概念上讲,使用此命令传递的结构如下:

struct _thread_runmask {
    int size;
    unsigned runmask[size];
    unsigned inherit_mask[size];
};

如果将 runmask 成员设置为非零值,ThreadCtl() 会将调用线程的运行掩码设置为指定值。如果将 runmask 成员设置为零,则调用线程的运行掩码不会改变。#######

如果将 inherit_mask 成员设置为非零值,ThreadCtl() 会将调用线程的继承掩码设置为指定值;如果调用线程通过调用 pthread_create()、fork()、posix_spawn()、spawn() 或 exec() 创建任何子线程,则子线程会继承此掩码。####### 如果将 inherit_mask 成员设置为零,则调用线程的继承掩码不会改变。//TODO: 子线程创建的子线程会不会继承此掩码?

如果查看 <sys/neutrino.h> 中 _thread_runmask 的定义,您会发现它实际上是这样声明的:

struct _thread_runmask {
    int         size;
/*  unsigned    runmask[size];      */
/*  unsigned    inherit_mask[size]; */
};

这是因为 runmask 和 inherit_mask 数组中的元素数量取决于多核系统中处理器的数量。您可以使用 RMSK_SIZE() 宏来确定掩码需要多少个无符号整数;将 CPU 数量(可在系统页面中找到)传递给此宏。

以下是一段代码片段,展示了如何设置 runmask 和 inherit mask:

unsigned    num_elements = 0;
int         *rsizep, masksize_bytes, size;
unsigned    *rmaskp, *imaskp;
void        *my_data;

/* Determine the number of array elements required to hold the runmasks, based on the number of CPUs in the system. */
num_elements = RMSK_SIZE(_syspage_ptr->num_cpu); //TODO: 看是CPU个数,还是CPU个数对应的bit位对应的字节数? #########

/* Determine the size of the runmask, in bytes. */
masksize_bytes = num_elements * sizeof(unsigned);

/* Allocate memory for the data structure that we'll pass
 * to ThreadCtl(). We need space for an integer (the number
 * of elements in each mask array) and the two masks
 * (runmask and inherit mask).
 */
size = sizeof(int) + 2 * masksize_bytes;
if ((my_data = malloc(size)) == NULL) {
    /* Not enough memory. */
    …
} else {
    memset(my_data, 0x00, size);

    /* Set up pointers to the "members" of the structure. */
    rsizep = (int *)my_data;
    rmaskp = rsizep + 1;
    imaskp = rmaskp + num_elements;

    /* Set the size. */
    *rsizep = num_elements;

    /* Set the runmask. Call this macro once for each processor the thread can run on. */
    RMSK_SET(cpu1, rmaskp);

    /* Set the inherit mask. Call this macro once for each processor the thread's children can run on. */
    RMSK_SET(cpu1, imaskp);

    if ( ThreadCtl( _NTO_TCTL_RUNMASK_GET_AND_SET_INHERIT, my_data) == -1) {
        /* Something went wrong. */
        …
    }
}

如果您要启动一个新进程,您可以通过以下方式指定其运行掩码:

(1) 调用 posix_spawnattr_setrunmask(),使用 posix_spawnattr_setxflags() 设置 POSIX_SPAWN_EXPLICIT_CPU 扩展标志,然后调用 posix_spawn()

或者:

(2) 设置 inheritance 结构的运行掩码成员并在调用 spawn() 时指定 SPAWN_EXPLICIT_CPU 标志。

您还可以使用 on 命令的 -C 和 -R 选项启动带有运行掩码的进程(假设它们没有以编程方式设置运行掩码);例如,使用 on -C 1 io-pkt-v4-hc 启动 io-pkt-v4-hc 并将所有线程锁定到 CPU 1。此命令同时设置运行掩码和继承掩码。

您还可以使用 slay 命令的相同选项来修改正在运行的进程或线程的运行掩码。例如,slay -C 0 io-pkt-v4-hc 将 io-pkt-v4-hc 的所有线程移动到 CPU 0 上运行。如果您使用 -C 和 -R 选项,slay 会设置运行掩码;如果您还使用 -i 选项,slay 还会将进程或线程的继承掩码设置为与运行掩码相同。


二、设置优先级

A few examples 翻译:
https://www.qnx.com/developers/docs/7.1/index.html#com.qnx.doc.neutrino.getting_started/topic/s1_procs_Examples.html
QNX Software Development Platform --> Programming --> Getting Started with QNX Neutrino --> Processes and ThreadsThreads and processes --> Starting a thread

让我们看一些例子。我们假设已经包含了正确的包含文件(<pthread.h> 和 <sched.h>),并且要创建的线程名为 new_thread(),并且已正确原型化和定义。

创建线程的最常见方法是简单地让其保持默认值:

pthread_create (NULL, NULL, new_thread, NULL);

在上面的例子中,我们使用默认值创建了新线程,并向其传递了一个 NULL 作为其唯一参数(这是上面 pthread_create() 调用中的第三个 NULL)。

通常,您可以将任何您想要的内容(通过 arg 字段)传递给新线程。这里我们传递的是数字 123:

pthread_create (NULL, NULL, new_thread, (void *) 123);

一个更复杂的例子是创建一个优先级为 15 的循环调度的不可连接线程:

pthread_attr_t attr;

// initialize the attribute structure
pthread_attr_init (&attr);

// set the detach state to "detached"
pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);

// override the default of INHERIT_SCHED
pthread_attr_setinheritsched (&attr, PTHREAD_EXPLICIT_SCHED);
pthread_attr_setschedpolicy (&attr, SCHED_RR);
attr.param.sched_priority = 15; //实测这个是不行的

// finally, create the thread
pthread_create (NULL, &attr, new_thread, NULL);

这里创建线程并指定其优先级。

要查看多线程程序“是什么样子”,可以从 shell 运行 pidin 命令。假设我们的程序名为 spud。如果我们在 spud 创建线程之前运行一次 pidin,在 spud 创建另外两个线程(总共三个)之后运行一次 pidin,则输出将如下所示(我已缩短 pidin 输出以仅显示 spud):

# pidin
pid    tid name               prio STATE       Blocked
 12301   1 spud                10r READY

# pidin
pid    tid name               prio STATE       Blocked
 12301   1 spud                10r READY
 12301   2 spud                10r READY
 12301   3 spud                10r READY

如您所见,进程 spud(进程 ID 12301)有三个线程(在“tid”列下)。这三个线程以优先级 10 运行,调度算法为循环(由 10 后面的“r”表示)。所有三个线程都处于 READY 状态,这意味着它们可以使用 CPU,但当前未在 CPU 上运行(另一个优先级更高的线程当前正在运行)。

现在我们已经了解了有关创建线程的所有信息,让我们看看如何以及在何处使用它们。

 

标签:优先级,thread,19,QNX,线程,掩码,runmask,运行,size
From: https://www.cnblogs.com/hellokitty2/p/18230864

相关文章

  • NCHU-软件学院-232019班-23201125-罗伊鑫-第二次Blog
    前言本次Blog总结三次题目集的7-1题目的知识点、题量、难度等情况,以及写完后的错误总结和自我思考。1.知识点三次题目集都对于类的设计的提前规划好有着必要的需求,还有就是对于继承与多态的合理的使用。接着就是对于正则表达式的使用的检测,然后就是要有清晰的逻辑编程表达。2.......
  • 适合小白学习的项目1901java体育馆管理系统Myeclipse开发mysql数据库web结构java编程
    一、源码特点java体育馆管理系统是一套完善的web设计系统,对理解JSPjava编程开发语言有帮助采用了java设计,系统具有完整的源代码和数据库,系统采用web模式,系统主要采用B/S模式开发。开发环境为TOMCAT7.0,Myeclipse8.5开发,数据库为Mysql,使用java语言开发。java体育馆管理系......
  • C语言 恼人的结合性和优先级和副作用
    结合性和优先级和副作用1.优先级2.结合性3.副作用4.简单区分i++,++i,i+=1;i=i+1;i=i++1.优先级优先级指的是,如果⼀个表达式包含多个运算符,哪个运算符应该优先执⾏。各种运算符的优先级是不⼀样的。在C语言中,优先性和结合性规则是非常重要的。然而C语言有几乎50中运算符......
  • visual studio 2019 c++与汇编混合代码
    1、visualstudio2019下x64架构的CPU配置不支持内联汇编代码的嵌入,即不支持__asm{}语句。2、通过创建.asm汇编代码文件封装汇编函数的方式实现c++代码调用汇编函数:第一步:修改工程的生成依赖项第二步:创建.asm汇编代码文件第三步:编写汇编代码的函数第四步:在c++文件调用汇编函......
  • 【NOIP2019普及组复赛】题3:纪念品
    题3:纪念品【题目描述】小伟突然获得一种超能力,他知道未来T天N种纪念品每天的价格。某个纪念品的价格是指购买一个该纪念品所需的金币数量,以及卖出一个该纪念品换回的金币数量。每天,小伟可以进行以下两种交易无限次:1.任选一个纪念品,若手上有足够金币,以当日价格购买该......
  • 【NOIP2019普及组复赛】题1:数字游戏
    题1:数字游戏【题目描述】小K同学向小PPP同学发送了一个长度为88......
  • 学习笔记19:图像定位
    转自:https://www.cnblogs.com/miraclepbc/p/14385623.html图像定位的直观理解不仅需要我们知道图片中的对象是什么,还要在对象的附近画一个边框,确定该对象所处的位置。也就是最终输出的是一个四元组,表示边框的位置图像定位网络架构可以将图像定位任务看作是一个回归问题!数据......
  • 我见我思之hvv偷师学艺——Vmware vcenter未授权任意文件上传(CVE-2021-21972)
    本文为个人整理内容,大部分东西都是参考其它师傅的文章,具体如下:https://blog.csdn.net/qq_37602797/article/details/114109428https://blog.csdn.net/tigerman20201/article/details/129098137常见告警特征:漏洞类型:文件上传。poc利用接口为:/ui/vropspluginui/rest/servic......
  • CF1971F Circle Perimeter
    题目Givenaninteger\(r\),findthenumberoflatticepointsthathaveaEuclideandistancefrom\((0,0)\)greaterthanorequalto\(r\)butstrictlylessthan\(r+1\).Alatticepointisapointwithintegercoordinates.TheEuclideandistance......
  • 【计算机毕业设计】ssm719精品课程在线学习系统+jsp
    如今社会上各行各业,都喜欢用自己行业的专属软件工作,互联网发展到这个时候,人们已经发现离不开了互联网。新技术的产生,往往能解决一些老技术的弊端问题。因为传统精品课程学习信息管理难度大,容错率低,管理人员处理数据费工费时,所以专门为解决这个难题开发了一个精品课程在线学......