找回密码
 立即注册
首页 业界区 业界 Linux调度分析(2)调度用户态API介绍

Linux调度分析(2)调度用户态API介绍

芮梦月 3 天前
Linux调度的实现在内核中,但用户态可以通过调度相关的systemcall可以进行调度相关的设置。这些设置包括:

  • 设置调度策略
    设置调度策略通过系统调用函数sched_setscheduler()实现,它的函数定义如下:
    SYSCALL_DEFINE3(sched_setscheduler, pid_t, pid, int, policy, struct sched_param __user *, param)
    pid为需要设置的线程pid,policy为需要设置的调度策略,param为设置参数
    Linux调度policy包括:


  • SCHED_NORMAL:普通调度
  • SCHED_FIFO:先进先出调度
  • SCHED_RR:Round-robin调度
  • SCHED_BATCH: ?
  • SCHED_IDLE:idle调度
  • SCHED_DEADLINE: DL调度
  • SCHED_EXT:EBPF调度

  • 获取调度策略
    获取调度策略通过系统调用函数sched_getscheduler()实现,它的函数定义如下:
    SYSCALL_DEFINE1(sched_getscheduler, pid_t, pid)
  • 设置亲和性
    设置线程的亲和性,可以让线程运行在指定的CPU上,它是通过系统调用sched_setaffinity()实现,它的函数定义如下:
    SYSCALL_DEFINE3(sched_setaffinity, pid_t, pid, unsigned int, len, unsigned long __user *, user_mask_ptr)
  • 获取亲和性
    获取线程的亲和性可以通过系统调用sched_getaffinity()实现,它的函数定义如下:
    SYSCALL_DEFINE3(sched_getaffinity, pid_t, pid, unsigned int, len, unsigned long __user *, user_mask_ptr)
  • 放弃当前CPU运行
    系统调用sched_yield()可以让当前运行的线程放弃在当前CPU的运行,切换其他线程运行
    SYSCALL_DEFINE0(sched_yield)
  • 其他的系统调用
    除了上述系统调用外,还有其他系统调用如:


  • sched_get_priority_max()获取某个调度策略的最大priority值
  • sched_get_priority_min()获取某个调度策略的最小priority值
  • nice()修改当前线程的priority值
  • sched_setparam()/sched_getparam设置/获取线程的priority
  • sched_setattr()/sched_getattr()设置/获取线程的扩展属性
  • sched_rr_get_interval()返回线程默认的slice即调度时间片

  • 隐式的调度相关的操作
    上述系统调用明确调用了调度相关的系统调用,其实在用户态调用sleep()等函数时隐含着schedule()让当前线程主动让出CPU的调度操作。
下面代码是设置pid为10000的线程调度相关的设置:将其设置为SCHED_FIFO调度策略,获取SCHED_FIFO的最大和最小优先级,设置线程的亲和性(将其绑定到CPU 0),在做了一些循环操作后放弃当前CPU。
`...
static void die(const char *msg)
{
perror(msg);
exit(EXIT_FAILURE);
}
int main(void)
{
int ret;
pid_t pid = 100000;  // 100000 means "this process"
  1. /* -----------------------------
  2. * 1. Set scheduling policy
  3. * ----------------------------- */
  4. struct sched_param sp;
  5. memset(&sp, 0, sizeof(sp));
  6. // Choose a real-time policy, e.g., SCHED_FIFO or SCHED_RR.
  7. // NOTE: This usually requires root privileges.
  8. int policy = SCHED_FIFO;
  9. // Get allowed priority range for this policy
  10. int max_prio = sched_get_priority_max(policy);
  11. int min_prio = sched_get_priority_min(policy);
  12. if (max_prio == -1 || min_prio == -1) {
  13.     die("sched_get_priority_*");
  14. }
  15. // Use some priority in the valid range; here we just pick the max.
  16. sp.sched_priority = max_prio;
  17. ret = sched_setscheduler(pid, policy, &sp);
  18. if (ret == -1) {
  19.     // If you see EPERM, you likely need to run as root.
  20.     fprintf(stderr,
  21.             "sched_setscheduler failed: %s (need CAP_SYS_NICE/root for RT)\n",
  22.             strerror(errno));
  23.     // Not fatal for demonstration, continue with default policy.
  24. } else {
  25.     printf("Scheduler set to policy %d, priority %d\n", policy,
  26.            sp.sched_priority);
  27. }
  28. /* -----------------------------
  29. * 2. Set CPU affinity (pin to CPU 0)
  30. * ----------------------------- */
  31. cpu_set_t set;
  32. CPU_ZERO(&set);
  33. CPU_SET(0, &set);  // bind to CPU 0
  34. ret = sched_setaffinity(pid, sizeof(set), &set);
  35. if (ret == -1) {
  36.     die("sched_setaffinity");
  37. } else {
  38.     printf("Affinity set to CPU 0\n");
  39. }
  40. /* -----------------------------
  41. * 3. Do some work and yield
  42. * ----------------------------- */
  43. for (int i = 0; i < 5; ++i) {
  44.     printf("Iteration %d on CPU %d\n", i, sched_getcpu());
  45.     // Do some dummy work
  46.     for (volatile long j = 0; j < 100000000L; ++j)
  47.         ;  // busy loop
  48.     printf("Yielding CPU...\n");
  49.     ret = sched_yield();  // Let other runnable tasks run
  50.     if (ret == -1) {
  51.         die("sched_yield");
  52.     }
  53. }
  54. printf("Done.\n");
  55. return 0;
复制代码
}`

来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

相关推荐

您需要登录后才可以回帖 登录 | 立即注册