创建线程时指定线程属性,调整线程优先级

--------------------------------------------------
author: hjjdebug
date: 2024年 03月 12日 星期二 12:43:38 CST
decription: 创建线程时指定线程属性,调整线程优先级
--------------------------------------------------
普通线程,根本没有优先级,最多只能调整一下nice值,想把线程
调整为实时线程,并设定线程优先级,需要先把线程策略调整为
FIFO(first in firt out)或RR(rotate robin), 然后可设置优先级值
完整代码如下,注意点都在代码注释中.

$ cat main.cpp

#include <stdio.h>                          // for printf, perror, NULL
#include <unistd.h>                         // for getpid, gettid, sleep
#include <pthread.h>                        // for pthread_attr_getschedparam
#include <sched.h>                          // for SCHED_FIFO, sched_priority
void *thread_func(void *arg) {
    (void) arg;
    printf("I'm a new thread.,threadID:%d\n",gettid());
    while(1)
    {
        //这里子线程不退出,方便我们用命令查看其优先A级
        //其命令为ps -p <pid> -T -o tid,comm,rtprio
        // rtprio 中 - 表示非实时线程, 有值表示实时线程
        sleep(1); 
    }
    pthread_exit(NULL);
}
int main() {
    printf("I'm parent thread, pid is %d\n",getpid());
    // 初始化线程属性
    pthread_attr_t attr;
    pthread_attr_init(&attr);
    // 设置继承调度策略
    pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED);
    // 设置线程调度策略为SCHED_FIFO,其优先级范围为(1-99)
    pthread_attr_setschedpolicy(&attr, SCHED_FIFO);
    // 设置线程调度参数,优先级设为80
    struct sched_param param;
    param.sched_priority = 80;
    pthread_attr_setschedparam(&attr, &param);
    // 创建新线程并运行
    pthread_t thread_id;
    int ret;
    //用attr 来创建thread
    if ((ret=pthread_create(&thread_id, &attr, thread_func, NULL)) != 0) {
        printf("ret:%d\n",ret); //非root 用户会返回1(EPERM), 权限不够
        perror("pthread_create error");
        return 1;
    }
    // 获取线程调度策略和参数, 下面代码只是查看一下我们的attr 是否设置对了
    int policy;
    //用来检查attr 是否是实时的,SCHED_FIFO,SCHED_RR都是实时的
    ret=pthread_attr_getschedpolicy(&attr, &policy);
    if(ret!=0) printf("error get policy\n");
    // 输出线程调度策略和参数
    printf("Thread policy: ");
    switch (policy) {
        case SCHED_FIFO:
            printf("FIFO\n");
            break;
        case SCHED_RR:
            printf("RR\n");
            break;
        case SCHED_OTHER:
            printf("OTHER\n");
            break;
        default:
            printf("UNKNOWN\n");
    }
    // 检查attr 设定的优先级
    ret=pthread_attr_getschedparam(&attr, &param);
    if(ret!=0) printf("error get parameter\n");
    printf("Thread priority: %d\n", param.sched_priority);
    // 等待子线程结束
    if (pthread_join(thread_id, NULL) != 0) { //子线程没有退出,主线程也不会退,方便我们观察线程属性!!
        perror("pthread_join error");
        return 1;
    }
    return 0;
}

执行结果: 需要超级用户权限, 请用root 或sudo 命令.
 ./thread_attr 
I'm parent thread, pid is 8996
Thread policy: FIFO
Thread priority: 80
I'm a new thread.,threadID:8997

程序按我们的要求在运行, 此时我们用命令行查询其线程优先级.
$ ps -p 8996 -T -o tid,comm,rtprio
    TID COMMAND         RTPRIO
   8996 thread_attr          -
   8997 thread_attr         80

可见线程8997 确实是实时线程, 优先级80

如果你想查看当前所有的实时线程.用下面命令: 只看rtprio有值的即可.
$ ps -e -T -o tid,comm,rtprio | grep -v -
 

补充:
代码在centos7 上运行失败,虽然是root, 但创建线程还是返回1, EPERM, ubuntu 上可以,没有出错!!
进一步查原因, 在stackoverflow 上找到答案.
可参考以下连接
https://stackoverflow.com/questions/9313428/getting-eperm-when-calling-pthread-create-for-sched-fifo-thread-as-root-on-lino

它说,
kernel/sched/core.c 中返回的错误
if (user) {
if (rt_bandwidth_enabled() && rt_policy(policy) && task_group(p)->rt_bandwidth.rt_runtime == 0 && !task_group_is_autogroup(task_group(p)))
{
task_rq_unlock(rq, p, &flags);
return -EPERM;
}

解决办法:
在centos 上, 需要把执行shell 的 pid 值加入到 /sys/fs/cgroup/cpu/tasks
即在你的shell 下执行
# echo $$ > /sys/fs/cgroup/cpu/tasks
再执行就不报错了.
实验成功了,确实这样可以解决问题.
但手工把shell 的pid 加入到一个控制组中的tasks 中,也太变态了, 干脆不用了!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值