当前位置: 首页 > news >正文

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, &param);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:可连接状态(默认)

    1. 系统在线程终止时自动回收其资源
    2. 不能使用pthread_join()等待或获取线程返回值
    3. 适用于,不需要知道线程何时结束或结果的场景,简单的后台任务,不需要与其他线程同步的任务。

    PTHREAD_CREATE_DETACHED:分离状态

    1. 线程终止后资源不会自动释放
    2. 必须调用pthread_join()来回收资源并获取返回值
    3. 适用于,需要获取线程执行结果的场景,需要知道线程确切结束时间的场景,需要线程间同步的场景。

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, &param);

系统级调度参数查询函数

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, &param) != 0) {perror("Failed to set thread scheduling parameters");exit(EXIT_FAILURE);
}

相关文章:

  • leetcode:21. 合并两个有序链表
  • 华为云Flexus+DeepSeek征文|基于Dify构建解析网页写入Notion笔记工作流
  • 【C++】C++枚举、const、static的用法
  • LLM存储优化:大量长对话解决方案
  • C++ - 标准库之 <string> npos(npos 概述、npos 的作用)
  • 开发云数据库
  • 数据库索引结构 B 树、B + 树与哈希索引在不同数据查询场景下的适用性分析
  • 深入剖析Flink内存管理:架构、调优与实战指南
  • 透视618:头部主播隐退、购物氛围变淡,新秩序正在建立
  • AAudio:Android 低延迟音频处理的核心组件
  • 基于SpringBoot的RestTemplate
  • Linux——6.检测磁盘空间、处理数据文件
  • Docker Desktop + Kubernetes 使用 hostPath 持久化挂载“坑点”全解析
  • selinux
  • 开源 python 应用 开发(一)python、pip、pyAutogui、python opencv安装
  • 云创智城YunCharge充电桩施工安装与项目落地标准及施工所需准备
  • 【PyTorch革命】机器学习系统编程模型的演进之路
  • 《高等数学》(同济大学·第7版)第五章 定积分 第二节微积分基本公式
  • 65-Oracle Undo机制
  • 无锡哲讯科技:助力纺织业搭乘 SAP 数字化快车
  • 做网站的升级人/高质量关键词搜索排名
  • h5网站建设公司/找客户的软件有哪些
  • 汽车之家官网首页/简述如何优化网站的方法
  • 哪里培训网页设计/上海站群优化
  • 深圳的网站建设公司那家好/百度识图在线识图
  • 网站优化培训中心/收录网站的平台有哪些