RT-Thread相同优先级线程

RT-Thread相同优先级线程

在RT-Thread中,如果有两个相同优先级的线程同时就绪,调度器会按照先进先出(FIFO)的原则来选择执行哪个线程。也就是说,先被加入就绪队列的线程会先被执行。

当然,如果你想要改变这种行为,可以通过修改调度器的代码来实现不同的调度策略。例如,你可以实现一个简单的轮询调度算法,让每个线程依次执行一定的时间片,从而避免某些线程长时间得不到执行的情况。不过,这样做需要注意平衡不同线程之间的公平性和响应速度之间的关系。

对于相同优先级rtthread调度算法怎么写的

在RT-Thread中,相同优先级的线程采用先进先出(FIFO)调度算法。如果两个或多个线程的优先级相同且同时处于就绪状态,那么它们将按照入队的顺序被调度执行。

如果你想要实现不同于默认的调度算法来处理相同优先级的线程,可以编写自己的调度器代码并将其替换为默认的调度器。以下是一个简单的轮询调度算法的示例,每个线程都会被分配一个时间片:

#include <rtthread.h>

static void round_robin_scheduler(struct rt_thread *thread) {
    /* 原来的线程放到末尾 */
    rt_list_move_tail(&thread->tlist, &rt_thread_priority_table[thread->current_priority]);
    /* 获取新的线程 */
    thread = rt_list_entry(rt_thread_priority_table[thread->current_priority].next,
                           struct rt_thread, tlist);
    /* 切换至新的线程 */
    rt_schedule_thread(thread);
}

int rt_system_scheduler_init(void) {
    rt_thread_idle_sethook(round_robin_scheduler);
    return 0;
}

这段代码将round_robin_scheduler()函数作为空闲线程钩子函数,并将默认的调度器替换为这个钩子函数。当没有其他优先级更高的线程需要运行时,该函数负责切换当前运行的线程。在上述代码中,我们使用一个简单的轮询调度算法,通过将当前线程放到队列末尾,并选择下一个就绪的线程来实现时间片轮转。

需要注意的是,调度器的修改可能会影响系统的稳定性和实时性,因此在修改之前应该进行充分的测试和评估。

具体的优先级位图算法

在RT-Thread中,用于实现调度器的优先级位图算法是一种高效的数据结构。其基本思想是将所有线程按照优先级分组,并使用一个位图来记录每个优先级组是否存在就绪的线程。这种算法可以在常数时间内快速查找最高优先级的就绪线程,并且具有较小的空间占用和高效的操作速度。

下面是一个简单的优先级位图算法的实现:

#define RT_THREAD_PRIORITY_MAX 32

/* 定义一个位图类型 */
typedef rt_uint32_t rt_bitmap_t;
/* 定义一个优先级队列类型 */
struct rt_thread_priority {
    rt_bitmap_t bitmap;             /* 位图 */
    struct rt_list thread_list;     /* 线程列表 */
};

static struct rt_thread_priority rt_thread_priority_table[RT_THREAD_PRIORITY_MAX];

/* 获取最高优先级的就绪线程 */
static struct rt_thread *rt_next_ready_thread(void) {
    rt_uint32_t highest_priority;
    struct rt_thread *thread;

    /* 遍历所有优先级组,从高到低寻找第一个就绪的线程 */
    for (highest_priority = RT_THREAD_PRIORITY_MAX - 1; highest_priority > 0; highest_priority--) {
        if (rt_thread_priority_table[highest_priority].bitmap != 0) {
            /* 找到了就绪的线程,从队列中获取第一个线程并返回 */
            thread = rt_list_entry(rt_thread_priority_table[highest_priority].thread_list.next,
                                   struct rt_thread, tlist);
            return thread;
        }
    }

    /* 找不到就绪的线程,返回空指针 */
    return RT_NULL;
}

/* 设置线程就绪状态 */
void rt_thread_ready(struct rt_thread *thread) {
    rt_uint8_t priority;

    /* 获取线程优先级 */
    priority = thread->current_priority;

    /* 将线程加入相应优先级组的队列中,并设置位图对应位为1 */
    rt_list_insert_after(&rt_thread_priority_table[priority].thread_list,
                         &thread->tlist);
    rt_thread_priority_table[priority].bitmap |= (1UL << priority);
}

/* 设置线程非就绪状态 */
void rt_thread_unready(struct rt_thread *thread) {
    rt_uint8_t priority;
    struct rt_list_node *node;

    /* 获取线程优先级 */
    priority = thread->current_priority;

    /* 从队列中移除线程 */
    node = &thread->tlist;
    rt_list_remove(node);

    /* 如果队列为空,将位图对应位置为0 */
    if (rt_list_isempty(&rt_thread_priority_table[priority].thread_list)) {
        rt_thread_priority_table[priority].bitmap &= ~(1UL << priority);
    }
}

在这个实现中,我们使用一个长度为32的rt_bitmap_t类型表示所有线程的就绪状态。每个位表示对应的优先级是否有就绪的线程。当一个线程变成就绪状态时,我们将其插入到相应优先级组的线程列表中,并将对应的位图位设置为1;当一个线程变成非就绪状态时,我们将其从队列中移除,并检查相应的位图位是否需要清零。

当调度器需要寻找下一个就绪的线程时,它会遍历所有优先级组,并从高到低依次查看位图,找到第一个非空的位图并返回其中的第一个线程。通过这种方法,可以在常数时间内快速查找到最高优先级的就绪线程。

这个算法中怎么处理优先级相同的线程

在优先级位图算法中,对于优先级相同的线程,它们会被放入同一个优先级组的队列中。当调度器需要寻找下一个就绪的线程时,它会按照优先级从高到低的顺序遍历所有优先级组,并从每个优先级组的队列中选择第一个线程作为下一个就绪的线程。

如果有多个优先级相同的线程同时处于就绪状态,那么它们会按照先进先出(FIFO)的原则被调度执行。这是因为,在默认情况下,RT-Thread的调度器采用的是基于时间片和FIFO的调度算法。也就是说,每个线程都会被分配一定的时间片,当时间片用完或者线程主动让出CPU时,它才会被放回就绪队列的末尾,等待下次调度执行。

如果你想要实现不同于默认的调度算法来处理优先级相同的线程,可以编写自己的调度器代码并将其替换为默认的调度器。例如,你可以实现一个简单的轮询调度算法,让每个线程依次执行一定的时间片,从而避免某些线程长时间得不到执行的情况。但是,需要注意平衡不同线程之间的公平性和响应速度之间的关系。

给出优先级组的数据结构

在RT-Thread中,优先级组的数据结构通常是一个结构体类型,可以定义如下:

 
struct rt_thread_priority {
    rt_bitmap_t bitmap;             /* 位图 */
    struct rt_list thread_list;     /* 线程列表 */
};

其中,rt_bitmap_t是一个整数类型,用于表示所有线程的就绪状态。每个位表示对应的优先级是否有就绪的线程。struct rt_list则是一个双向链表类型,用于存储同一优先级组内的所有线程。

在优先级位图算法中,系统会根据线程的优先级将其分配到不同的优先级组中,并使用一个数组来存储所有优先级组的信息。例如,在默认情况下,RT-Thread支持32个不同的优先级,那么我们可以定义一个全局数组来存储所有优先级组的信息:

#define RT_THREAD_PRIORITY_MAX 32

static struct rt_thread_priority rt_thread_priority_table[RT_THREAD_PRIORITY_MAX];

通过这样的方式,我们就可以方便地管理所有线程的优先级和就绪状态,并实现高效的调度器算法。

怎么在优先级数组中插入线程

在RT-Thread中,可以使用rt_thread_ready()函数将一个线程插入到优先级数组中的相应优先级组中。具体来说,该函数会将线程插入到优先级组的线程列表中,并设置位图对应位为1,以标记该优先级组存在就绪的线程。

以下是一个简单的rt_thread_ready()函数的实现:


void rt_thread_ready(struct rt_thread *thread) {
    rt_uint8_t priority;

    /* 获取线程优先级 */
    priority = thread->current_priority;

    /* 将线程加入相应优先级组的队列中,并设置位图对应位为1 */
    rt_list_insert_after(&rt_thread_priority_table[priority].thread_list,
                         &thread->tlist);
    rt_thread_priority_table[priority].bitmap |= (1UL << priority);
} 

在这个实现中,我们首先获取了线程的当前优先级,并将其用于访问优先级数组中的相应优先级组。然后,我们将线程插入到该优先级组的线程列表中,并将位图对应位设置为1,以标记该优先级组存在就绪的线程。

需要注意的是,如果你想要更改线程的优先级,或者让线程变得非就绪状态,可以使用相应的API函数:rt_thread_set_priority()和rt_thread_unready()。这些函数都会在必要时更新线程的优先级和就绪状态,并正确地将线程从优先级数组中的相应优先级组中移除。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值