Linux 线程调度管理函数
Linux 线程优先级+线程调度策略
1.1. 线程的创建
#include <pthread.h>
int pthread_create(pthread_t *restrict tidp, // 新建的线程ID指向的内存单元const pthread_attr_t *restrict attr, // 线程属性,默认为NULLvoid *(*start_rtn)(void *), // 新创建的线程运行的函数void *restrict arg // 线程运行函数参数,默认为NULL)
- 线程的属性
typedef struct
{
int etachstate; // 线程的分离状态
int schedpolicy; // 线程的调度策略
struct sched_param schedparam; // 线程的调度参数
int inheritsched; // 线程的继承性
int scope; // 线程的作用域
size_t guardsize; // 线程栈末尾的境界缓冲区大小
int stackaddr_set; // 线程的栈设置
void* stackaddr; // 线程栈的位置
size_t stacksize; // 线程栈的大小
} pthread_attr_t;
1.2. 线程调度策略的设置
// policy 参数一般由3种 SCHED_OTHER, SCHED_FIFO, SCHED_RR.
int pthread_attr_setschedpolicy(pthread_attr_*, int policy)
// 获取线程属性,将属性值赋给policy
int pthread_attr_getschedpolicy(const pthread_attr_t *, int * policy)
参数:
attr
: 线程属性指针policy
:
SCHED_FIFO: 先进先出调度
SCHED_RR: 时间片轮转
SCHED_OTHER: 分时调度
线程优先级的设置
//线程优先级设置和获取函数
int pthread_attr_setschedparam(pthread_attr_t *,const struct sched_param *);
int pthread_attr_getschedparam(const pthread_attr_t *,struct sched_param *);
attr
: 线程属性结构体指针(pthread_attr_init初始化)
param
: 调度参数结构体
pthread_attr_t attr;
struct sched_param param;pthread_attr_init(&attr);
pthread_attr_setschedpolicy(&attr, SCHED_FIFO); // 设置调度策略(FIFO/RR/OTHER)
param.sched_priority = 50; // 设置优先级(1~99,取决于策略)
pthread_attr_setschedparam(&attr, ¶m);pthread_t thread;
pthread_create(&thread, &attr, thread_func, NULL);pthread_attr_destroy(&attr); // 销毁属性对象
1.3. 线程的继承性设置
int pthread_attr_getinheritsched(const pthread_attr_t * attr,int *inheritsched);
int pthread_attr_setinheritsched(pthread_attr_t * attr,int inheritsched);
参数:
-
attr: 线程属性结构体指针
-
inheritsched:
PTHREAD_INHEARIT_SCHED: 继承创建者的调度属性(默认)
新线程继承创建者线程的调度策略和参数
忽略设置属性,适用需要保持线程组调度一致性的场景,无需精细控制PTHREAD_EXPLICIT_SCHED: 使用attr中显式设置的调度属性
使用属性中显式设置的调度策略和参数
需要为不同线程设置不同调度策略,实时应用精细控制,复杂多线程调度需求
1.4. 线程的栈大小设置
int pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize);
int pthread_attr_getstacksize(const pthread_attr_t *attr, size_t *stacksize);
参数:
- attr: 线程属性结构体指针
- stacksize: 要设置/获取的栈大小(字节)
默认栈大小: Linux中,线程栈默认大小为8MB(x86_64架构), 可用ulimit -s查看
需设置的情况: 线程需要处理大量局部变量或深度递归调用,内存受限的嵌入式系统,需要创建大量线程时
1.5. 线程的分离状态
设置/获取线程的分离状态
int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate);
int pthread_attr_getdetachstate(const pthread_attr_t *attr, int *detachstate);
参数:
-
attr: 线程属性结构体指针
-
detachstate:
PTHREAD_CREATE_JOINABLE
:可连接状态(默认)- 系统在线程终止时自动回收其资源
- 不能使用pthread_join()等待或获取线程返回值
- 适用于,不需要知道线程何时结束或结果的场景,简单的后台任务,不需要与其他线程同步的任务。
PTHREAD_CREATE_DETACHED
:分离状态- 线程终止后资源不会自动释放
- 必须调用pthread_join()来回收资源并获取返回值
- 适用于,需要获取线程执行结果的场景,需要知道线程确切结束时间的场景,需要线程间同步的场景。
1.6. 绑定CPU
//设置和获取当前线程绑定的CPU ID
int pthread_setaffinity_np(pthread_t thread, size_t cpusetsize,const cpu_set_t *cpuset);
int pthread_getaffinity_np(pthread_t thread, size_t cpusetsize, cpu_set_t *cpuset);
//从函数名以及参数名都很明了,唯一需要点解释下的可能就是cpu_set_t这个结构体了。这个结构体的理解类似于select中的fd_set,可以理解为cpu集,也是通过约定好的宏来进行清除、设置以及判断:
//初始化,设为空
void CPU_ZERO (cpu_set_t *set);
//将某个cpu加入cpu集中
void CPU_SET (int cpu, cpu_set_t *set);
//将某个cpu从cpu集中移出
void CPU_CLR (int cpu, cpu_set_t *set);
//判断某个cpu是否已在cpu集中设置了
int CPU_ISSET (int cpu, const cpu_set_t *set);
二、函数总结
2.1 线程属性设置函数
创建线程前需要初始化属性对象,使用后销毁以释放对象
int pthread_attr_init(pthread_attr_t *attr); // 初始化线程属性对象
int pthread_attr_destroy(pthread_attr_t *attr); // 销毁线程属性对象
设置/获取线程调度策略
int pthread_attr_setschedpolicy(pthread_attr_t *attr, int policy);
int pthread_attr_getschedpolicy(const pthread_attr_t *attr, int *policy);
设置/获取线程优先级参数
int pthread_attr_setschedparam(pthread_attr_t *attr, const struct sched_param *param);
int pthread_attr_getschedparam(const pthread_attr_t *attr, struct sched_param *param);
struct sched_param {int sched_priority; // 优先级值(1-99 用于实时调度,0 用于分时调度)
};
设置/获取线程是否继承创建者的调度属性
int pthread_attr_setinheritsched(pthread_attr_t *attr, int inheritsched);
int pthread_attr_getinheritsched(const pthread_attr_t *attr, int *inheritsched);
inheritsched 可选值:
PTHREAD_INHERIT_SCHED:继承创建者的调度属性
PTHREAD_EXPLICIT_SCHED:使用 attr 中显式设置的调度属性
2.2 线程创建与调度控制函数
创建线程
int pthread_create(pthread_t *thread,const pthread_attr_t *attr,void *(*start_routine) (void *),void *arg);
动态修改/获取线程的调度参数(运行时调整)
int pthread_setschedparam(pthread_t thread, int policy, const struct sched_param *param);
int pthread_getschedparam(pthread_t thread, int *policy, struct sched_param *param);
struct sched_param param;
param.sched_priority = 70;
pthread_setschedparam(pthread_self(), SCHED_FIFO, ¶m);
系统级调度参数查询函数
int sched_get_priority_max(int policy);
int sched_get_priority_min(int policy);
SCHED_FIFO/SCHED_RR:1(最小)- 99(最大)
SCHED_OTHER:0(唯一有效值)
获取/设置当前进程的调度策略和参数(进程级)
int sched_getscheduler(pid_t pid);
int sched_setscheduler(pid_t pid, int policy, const struct sched_param *param);
2.3 系统级调度参数查询函数
获取指定调度策略的最大/最小优先级值
int sched_get_priority_max(int policy);
int sched_get_priority_min(int policy);
获取/设置当前进程的调度策略和参数(进程级)
int sched_getscheduler(pid_t pid);
int sched_setscheduler(pid_t pid, int policy, const struct sched_param *param);
pid:0 表示当前进程
policy 和 param 含义同上
主动让出CPU, 将当前线程放入就绪队列尾部
int sched_yield(void);
2.4 资源限制与亲和性设置
设置/获取线程的CPU亲和性(绑定到特定CPU核心)
int sched_setaffinity(pid_t pid, size_t cpusetsize, const cpu_set_t *mask);
int sched_getaffinity(pid_t pid, size_t cpusetsize, cpu_set_t *mask);
// 示例: 将线程绑定到CPU0
cpu_set_t cpuset;
CPU_ZERO(&cpuset); // 清空CPU集
CPU_SET(0, &cpuset); // 添加CPU核心0
sched_setaffinity(0, sizeof(cpu_set_t), &cpuset); // 应用到当前线程
设置线程竞争范围(Linux通常忽略此设置)
int pthread_attr_setscope(pthread_attr_t *attr, int scope);
scope 可选值:
PTHREAD_SCOPE_SYSTEM:与系统中所有线程竞争 CPU
PTHREAD_SCOPE_PROCESS:仅与同一进程内的线程竞争(Linux 不支持)
2.5 权限与错误处理
实时调度权限:设置实时调度策略(SCHED_FIFO/SCHED_RR)需要 root 权限,否则会返回 EPERM 错误。
常见错误码:
EINVAL:参数无效(如优先级超出范围)
EPERM:权限不足
ESRCH:找不到指定线程
if (pthread_setschedparam(thread, SCHED_FIFO, ¶m) != 0) {perror("Failed to set thread scheduling parameters");exit(EXIT_FAILURE);
}