【多线程编程】线程调度策略及优先级

通过之前的学习我知道了当前 Linux 系统下任务调度策略主要有三种:

1、SCHED_OTHER:普通任务调度策略。

2、SCHED_FIFO:实时任务调度策略,先到先服务。一旦占用cpu则一直运行,直到有更高优先级任务到达或自己放弃。

3、SCHED_RR:实时任务调度策略,时间片轮转。当任务的时间片用完,系统将重新分配时间片,并置于就绪队列尾。放在队列尾

保证了所有具有相同优先级的RR任务的调度公平。


Linux 提供的有关任务调度策略及优先级的接口函数:


1、


   
   
  1. // 首先了解 sched_param 结构体
  2. // In the current implementation, the structure contains only one field, sched_priority.
  3. // The interpretation of param depends on the selected policy
  4. struct sched_param
  5. {
  6. int sched_priority;
  7. };




2、


   
   
  1. int sched_setscheduler(pid_t pid, int policy, const struct sched_param *param);
  2. int sched_getscheduler(pid_t pid);


The sched_setscheduler() system call sets both the scheduling policy and parameters for the thread whose ID is specified in pid.  

If pid equals zero, the scheduling policy and parameters of the calling thread will be set.

The sched_getscheduler() returns the current scheduling policy of the thread identified by pid.  If pid equals zero, the policy of the 

calling thread will be retrieved.


与上面函数类似的还有:


   
   
  1. int sched_setparam(pid_t pid, const struct sched_param *param);
  2. int sched_getparam(pid_t pid, struct sched_param *param);



我们可以使用以下两个函数检测某个策略下优先级的取值范围。


   
   
  1. int sched_get_priority_max(int policy);
  2. int sched_get_priority_min(int policy);

对于 SCHED_OTHER 策略,sched_priority 只能为 0。对于 SCHED_FIFO,SCHED_RR 策略,sched_priority 从 1 到 99。



3、通过以下两个函数我们可以设置/查看线程的调度属性。


   
   
  1. //调度属性结构体
  2. struct sched_attr {
  3. u32 size; /* Size of this structure */
  4. u32 sched_policy; /* Policy (SCHED_*) */
  5. u64 sched_flags; /* Flags */
  6. s32 sched_nice; /* Nice value (SCHED_OTHER,
  7. SCHED_BATCH) */
  8. u32 sched_priority; /* Static priority (SCHED_FIFO,
  9. SCHED_RR) */
  10. /* Remaining fields are for SCHED_DEADLINE */
  11. u64 sched_runtime;
  12. u64 sched_deadline;
  13. u64 sched_period;
  14. };



   
   
  1. int sched_setattr(pid_t pid, struct sched_attr *attr, unsigned int flags);
  2. int sched_getattr(pid_t pid, struct sched_attr *attr, unsigned int size, unsigned int flags);




下面的 API 被更多使用:



4、初始化/销毁 struct pthread_attr_t 


   
   
  1. int pthread_attr_init(pthread_attr_t *attr);
  2. int pthread_attr_destroy(pthread_attr_t *attr);

初始化后的 attr 默认使用 SCHED_OTHER 策略,优先级为 0。




5、设置/查看调度策略到 attr 里


   
   
  1. int pthread_attr_setschedpolicy(pthread_attr_t *attr, int policy);
  2. int pthread_attr_getschedpolicy(const pthread_attr_t *attr, int *policy);



6、设置/查看调度优先级到 attr 里


   
   
  1. int pthread_attr_setschedparam(pthread_attr_t *attr, const struct sched_param *param);
  2. int pthread_attr_getschedparam(const pthread_attr_t *attr, struct sched_param *param);





7、继承调度属性 inheritsched。


   
   
  1. int pthread_attr_setinheritsched(pthread_attr_t *attr, int inheritsched);
  2. int pthread_attr_getinheritsched(pthread_attr_t *attr, int *inheritsched);

函数中inheritsched的取值为:PTHREAD_INHERIT_SCHED 或者 PTHREAD_EXPLICIT_SCHED。前者为继承创建线程的调度策

略和优先级,后者指定不继承调度策略和优先级,而是使用自己设置的调度策略和优先级。无论何时,当你需要控制一个线程的调

度策略或优先级时,必须将inheritsched属性设置为PTHREAD_EXPLICIT_SCHED。




8、动态设置/查看调度属性。


   
   
  1. <span style= "font-size:14px;"> int pthread_setschedparam( pthread_t thread, int policy, const struct sched_param *param);
  2. int pthread_getschedparam(pthread_t thread, int *policy, struct sched_param *param);</span>

该方法下就不用调用函数来设置 inheritsched 属性了,因为                                                                               

pthread_attr_setinheritsched(&thread_attr, PTHREAD_EXPLICIT_SCHED) 函数设置的对象是pthread_attr_t !!!



注意使用 SCHED_RR 或 SCHED_FIFO 策略需要使用 sudo 权限运行程序才行。




注意:
1)调度策略和优先级是分开来描述的。前者使用预定义的SCHED_RR、SCHED_FIFO、SCHED_OTHER,后者是通过结果体

struct sched_param给出的。

2)这些设置调度策略和优先级的函数操作的对象是线程的属性pthread_attr_t(条款8除外),而不是直接来操作线程的调度策略和

优先级的。函数的第一个参数都是pthread_attr_t。



下面我们用代码检测下:


   
   
  1. #include <pthread.h>
  2. #include <unistd.h>
  3. #include <stdio.h>
  4. #include <assert.h>
  5. void display()
  6. {
  7. sched_param param;
  8. int policy;
  9. pthread_getschedparam(pthread_self(), &policy, &m);
  10. switch(policy)
  11. {
  12. case SCHED_RR:
  13. printf( "%X: policy:SCHED_RR priority:%d\n", pthread_self(), param.sched_priority);
  14. break;
  15. case SCHED_FIFO:
  16. printf( "%X: policy:SCHED_FIFO priority:%d\n", pthread_self(), param.sched_priority);
  17. break;
  18. case SCHED_OTHER:
  19. printf( "%X: policy:SCHED_OTHER priority:%d\n", pthread_self(), param.sched_priority);
  20. break;
  21. default:
  22. printf( "error\n");
  23. }
  24. }
  25. void* fun(void *p)
  26. {
  27. display();
  28. sched_param param;
  29. param.sched_priority = 20;
  30. //动态修改调度策略
  31. pthread_setschedparam(pthread_self(), SCHED_FIFO, &m);
  32. display();
  33. }
  34. int main()
  35. {
  36. pthread_t pid;
  37. sched_param param;
  38. int policy;
  39. pthread_attr_t attr;
  40. pthread_attr_init(&attr);
  41. param.sched_priority = 10;
  42. policy = SCHED_RR;
  43. assert(pthread_attr_setschedpolicy(&attr, policy) == 0);
  44. assert(pthread_attr_setschedparam(&attr, &m) == 0);
  45. assert(pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED) == 0);
  46. assert(pthread_create(&pid, &attr, fun, NULL) == 0);
  47. pthread_join(pid, NULL);
  48. pthread_attr_destroy(&attr);
  49. return 0;
  50. }


使用 sudo 运行后:


   
   
  1. B75E8B40: policy:SCHED_RR priority: 10
  2. B75E8B40: policy:SCHED_FIFO priority: 20


若我们不使用 sudo 运行,就会报错:

Assertion `pthread_create(&pid, &attr, fun, __null) == 0' failed.
   
   




  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
POSIX多线编程是一种基于UNIX操作系统的多线编程模型,也是一种符合POSIX线程标准的编程方式。POSIX多线编程可以帮助开发者更好地利用系统资源,并提高程序的性能和可扩展性。 POSIX多线编程涉及的主要内容包括线程的创建、同步和调度等。通过使用线程库提供的函数和数据结构,开发者可以方便地创建和管理多个线程。线程可以共享进程的资源,包括内存、文件描述符等,这样可以避免进程间的数据传输和同步开销,提高程序的效率。 在POSIX多线编程中,开发者可以使用同步机制来确保线程之间的正确协同工作。例如,互斥锁可以用来保护共享资源的访问,条件变量可以用来进行线程间的通信和等待。同时,开发者还可以使用信号量来进行线程间的同步和互斥操作。这些同步机制可以帮助开发者实现良好的线程互动,避免数据竞争和死锁等问题。 此外,POSIX多线编程还提供了一些线调度的接口,开发者可以通过调整线程的优先级和睡眠时间等参数来控制线程的执行顺序和时间片分配。这样可以更好地满足不同线程对系统资源的需求,提高程序的相应能力和性能。 综上所述,POSIX多线编程是一种强大且灵活的编程模型,它能帮助开发者充分发挥多核处理器的计算能力,优化程序的并发性能。通过合理使用线程的创建、同步和调度等技术,开发者可以编写出更高效、更可靠的多线程应用程序。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值