【Linux】实时线程的优先级设置、调度和抢占

前言

看了一些关于Linux多线程编程的书籍和网络资料,发现关于对实时线程调度和抢占的主题的代码和文章比较少(也可能是我还没找到)。而对于一些系统,例如机器人控制系统,对于任务的实时性要求是比较高的,所以需要了解一下实时线程的编程方法。
Linux虽然是一个非实时操作系统,但是其线程也有实时和分时之分,具体的调度策略可以分为3种:
实时线程:SCHED_FIFO(先来先服务策略调度);
实时线程:SCHED_RR(时间片轮转);
普通线程:Linux中称为SCHED_MORMAL;POSIX称为SCHED_OTHER,是一种分时调度策略。
我们创建线程的时候可以指定调度策略,默认的调度策略为SCHED_OTHER。

示例代码

下边给出一个Linux实时线程抢占的编程示例,我认为尤其需要注意的两点是:
(1)必须在sudo模式下运行程序;
(2)需要将实时线程绑定到同一个CPU核上;

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <sched.h>

#define __USE_GNU

long long a = 0;
long long b = 0;

// 获取调度策略的函数
static int get_thread_policy(pthread_attr_t *attr)
{
    int policy;
    int rs = pthread_attr_getschedpolicy(attr, &policy);
    // assert(rs == 0);
    switch (policy)
    {
    case SCHED_FIFO:
        printf("policy= SCHED_FIFO\n");
        break;
    case SCHED_RR:
        printf("policy= SCHED_RR");
        break;
    case SCHED_OTHER:
        printf("policy=SCHED_OTHER\n");
        break;
    default:
        printf("policy=UNKNOWN\n");
        break;
    }
    return policy;
}

// 将线程绑定到某个cpu核上
int attach_cpu(int cpu_index)
{
    int cpu_num = sysconf(_SC_NPROCESSORS_CONF);
    if (cpu_index < 0 || cpu_index >= cpu_num)
    {
        printf("cpu index ERROR!\n");
        return -1;
    }
    
    cpu_set_t mask;
    CPU_ZERO(&mask);
    CPU_SET(cpu_index, &mask);

    if (pthread_setaffinity_np(pthread_self(), sizeof(mask), &mask) < 0)
    {
        printf("set affinity np ERROR!\n");
        return -1;
    }

    return 0;
}

// 线程函数1
void *thread1(void *param)
{
    attach_cpu(0);

    long long i;
    for (i = 0; i < 10000000000; i++)
    {
        a++;
    }
}

// 线程函数2
void *thread2(void *param)
{
    attach_cpu(0);

    long long i;
    for (i = 0; i < 10000000000; i++)
    {
        b++;
    }
}

int main()
{
    pthread_t t1;
    pthread_t t2;
    pthread_attr_t attr1;
    pthread_attr_t attr2;
    struct sched_param param1;
    struct sched_param param2;

    //1、初始化
    pthread_attr_init(&attr1);
    pthread_attr_init(&attr2);

    //2、自己决定调度策略
    pthread_attr_setinheritsched(&attr1, PTHREAD_EXPLICIT_SCHED);
    pthread_attr_setinheritsched(&attr2, PTHREAD_EXPLICIT_SCHED);

    //3、设置调度策略
    pthread_attr_setschedpolicy(&attr1, SCHED_FIFO);
    pthread_attr_setschedpolicy(&attr2, SCHED_FIFO);
    // 获取调度策略
    get_thread_policy(&attr1);
    get_thread_policy(&attr2);

    //4、设置优先级
    param1.sched_priority = 10;// 线程1设置优先级为10
    param2.sched_priority = 12;// 线程2设置优先级为12
    pthread_attr_setschedparam(&attr1, &param1);
    pthread_attr_setschedparam(&attr2, &param2);

    //5、创建线程
    pthread_create(&t1, &attr1, thread1, NULL);
    sleep(1);
    pthread_create(&t2, &attr2, thread2, NULL);

    while (1)
    {
        printf("a=%lld, b=%lld\n", a, b);
        sleep(1);
    }

    pthread_join(t1, NULL);
    pthread_join(t2, NULL);

    return 0;
}

代码结果

这里线程2的优先级设置为12,大于线程1的优先级11,所以线程2一旦就绪,就会抢占CPU资源,进入运行态,而线程1进入就绪态。如下所示,线程函数1中的a累加到366407710后就不再累加,被线程函数2中的b累加抢占,持续运行下去。

[linux-xx@xxx]$ sudo ./test 
policy= SCHED_FIFO
policy= SCHED_FIFO
a=366407710, b=0
a=366407710, b=360397117
a=366407710, b=720418977
a=366407710, b=1080623671
a=366407710, b=1443246909
a=366407710, b=1802815022
a=366407710, b=2165877123
^C
  • 3
    点赞
  • 41
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
Linux中,可以使用nice命令来提高线程优先级。nice命令实际上是通过调用setpriority()系统调用来修改进程的优先级。通过在命令中指定较低的调整值,可以提高线程优先级。较低的调整值表示较高的优先级。需要注意的是,nice命令需要使用root权限才能够修改其他用户的进程优先级。此外,优先级的调整值只是一个相对值,即使设置了最高优先级,也不能保证程序一定能够立即响应。对于使用多核CPU的系统,nice命令只能够调整程序在一个CPU核心上的优先级,而不能够调整在多个CPU核心上的优先级。因此,提高线程优先级可以通过使用nice命令并指定较低的调整值来实现。 #### 引用[.reference_title] - *1* *2* [优化Linux系统性能的必杀技:调整进程优先级!学会使用nice命令,让你的系统飞一般的顺畅!](https://blog.csdn.net/wisdom_futrue/article/details/129302719)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [【Linux实时线程优先级设置调度抢占](https://blog.csdn.net/gpeng832/article/details/126809565)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值