多线程调度
- 包含5种线程调度:
- SCHED_OTHER:
- SCHED_FIFO:
- SCHED_RR:
- SCHED_BATCH:
- SCHED_IDLE:
如何设置调度策略
在Linux系统中,线程调度策略可以通过sched_setscheduler()函数来设置,它是标准C库的一部分,定义在<sched.h>头文件中。线程调度策略决定了线程的调度行为,例如,是按照轮询方式(round-robin)还是根据线程的优先级来调度。
以下是如何设置线程调度策略的基本步骤:
包含头文件:
c
#include <sched.h>
选择调度策略:
你可以为线程选择不同的调度策略,如SCHED_FIFO或SCHED_RR。SCHED_FIFO是先入先出策略,而SCHED_RR是轮询策略,适用于时间片轮转。
设置优先级:
设置线程的优先级。对于SCHED_FIFO和SCHED_RR,优先级范围通常是1到99,数值越小,优先级越高。
创建调度参数结构体:
创建一个struct sched_param实例,并设置所需的调度策略和优先级。
调用sched_setscheduler():
使用当前线程的ID(可以通过gettid()获得)和填充好的sched_param结构体调用sched_setscheduler()函数。
示例代码如下:
c
#include <stdio.h>
#include <stdlib.h>
#include <sched.h>
#include <unistd.h>
int main() {
// 创建调度参数结构体
struct sched_param param;
param.sched_priority = 10; // 设置优先级
// 设置调度策略为轮询(round-robin)
if (sched_setscheduler(0, SCHED_RR, ¶m) != 0) {
perror("sched_setscheduler failed");
exit(EXIT_FAILURE);
}
// 打印新的调度策略和优先级
printf("Thread with PID %d is running with SCHED_RR and priority %d\n",
getpid(), param.sched_priority);
// 线程将按照设置的调度策略运行
while (1) {
// 线程的工作内容
}
return 0;
}
在Linux系统中,除了使用sched_setscheduler()函数外,还可以使用以下方法来设置线程或进程的调度策略:
Nice值:
通过nice命令或setpriority系统调用来改变进程的nice值,这会影响其在SCHED_OTHER调度策略下的相对优先级。
bash
nice -n 10 command
或者在C程序中使用:
c
#include <sys/resource.h>
setpriority(PRIO_PROCESS, getpid(), 10);
renice命令:
使用renice命令来改变正在运行的进程的nice值。
bash
renice 10 -p pid
cgroups:
控制组(cgroups)是一种Linux内核功能,它可以对进程进行分组,并为每个组设置不同的资源限制和调度策略。
chrt命令:
chrt命令是一个用于设置实时调度策略的命令行工具。
bash
chrt -f -p 50 pid
其中-f选项表示使用fifo实时策略,-p后跟的数字是优先级。
Systemd服务配置:
如果你使用systemd作为初始化系统,可以在服务单元文件中设置调度策略和nice值。
示例服务单元文件中的设置:
ini
[Service]
ExecStart=/usr/bin/my_application
Nice=10
IOSchedulingClass=1
IOSchedulingPriority=0
/proc文件系统:
直接通过写入/proc文件系统来改变调度策略和优先级。
bash
echo '10' > /proc/[pid]/nice
taskset命令:
taskset可以用来限制进程在特定的CPU上运行,虽然它不直接设置调度策略,但可以影响进程的执行。
bash
taskset -c 2 command
内核参数:
通过修改内核的启动参数(如使用GRUB配置),可以设置一些调度相关的全局选项。
使用sched_getscheduler()和sched_setparam():
sched_getscheduler()可以用来获取当前线程的调度策略,而sched_setparam()可以用来设置线程的调度参数,但不会改变调度策略。
Linux系统中定义了几种不同的线程(或进程)调度策略,每种策略都有其特定的行为和用途。以下是这些策略的简要说明和区别:
SCHED_OTHER:
这是默认的调度策略,适用于大多数普通进程和线程。它使用完全公平调度(CFS)算法,也称为动态优先级调度。CFS旨在为每个任务提供平等的处理时间份额,适合多任务环境。
SCHED_FIFO:
这是一个实时调度策略,使用先进先出(FIFO)队列。在这个策略下,最高优先级的就绪线程将立即运行,直到它阻塞或被更高优先级的线程抢占。SCHED_FIFO不会老化(aging),即低优先级的线程可能永远不会运行如果高优先级的线程一直在运行。
SCHED_RR:
SCHED_RR也是实时调度策略,类似于SCHED_FIFO,但它使用轮询调度。每个线程在运行时会分配一个时间片(量子),当时间片用完后,线程会被放到就绪队列的末尾。如果线程在其时间片内阻塞,它将放弃其位置并重新排队。
SCHED_IDLE:
这个策略适用于非常低优先级的线程,它们只在系统没有其他线程运行时才会运行。这可以用于后台任务,这些任务不应该干扰任何其他运行中的进程。
SCHED_BATCH:
这个策略适用于批量处理任务,它类似于SCHED_OTHER,但具有较低的优先级。这有助于避免批量任务影响交互式或时间敏感的任务。
区别主要在于它们适用的场景和对实时性的要求:
SCHED_OTHER:适合大多数通用任务,优先级动态调整,适合多任务环境。
SCHED_FIFO 和 SCHED_RR:适合需要保证服务时间或实时性的高优先级任务。它们需要适当配置优先级,以避免饿死其他低优先级任务。
SCHED_IDLE:适合几乎不需要优先级考虑的任务,它们仅在系统空闲时运行。
SCHED_BATCH:适合批量任务,这些任务不应该干扰更高优先级的任务。
Reference
- kimi GPT