是否在Ubuntu 16.04中正式支持SCHED_DEADLINE?

时间:2018-04-29 00:35:36

标签: c linux linux-kernel ubuntu-16.04 sched-deadline

目前我正在使用Linux内核版本运行Ubuntu 16.04为4.16。我编写了一个虚拟程序,将其调度程序更改为SCHED_DEADLINE。但是当我尝试编译它时,它找不到SCHED_DEADLINE所需的结构和宏的定义。大多数代码段都来自here(第24页)。以下是测试程序:

#define _GNU_SOURCE
#include <pthread.h>
#include <stdlib.h> 
#include <stdio.h> 
#include <string.h> 
#include <sched.h> 


int main(int argc, char* argv[]) {

    struct sched_attr attr;
    attr.size = sizeof(attr);
    attr.sched_policy = SCHED_DEADLINE;
    attr.sched_runtime = 30000000;
    attr.sched_period = 100000000;
    attr.sched_deadline = attr.sched_period;
    if (sched_setattr(gettid(), &attr, 0))
        perror("sched_setattr()");

    return 0;
}

这是编译的输出:

sched_deadline.c: In function ‘main’:
sched_deadline.c:11:20: error: storage size of ‘attr’ isn’t known
  struct sched_attr attr;
                    ^
sched_deadline.c:12:21: error: invalid application of ‘sizeof’ to incomplete type ‘struct attr’
  attr.size = sizeof(struct attr);
                     ^
sched_deadline.c:13:22: error: ‘SCHED_DEADLINE’ undeclared (first use in this function)
  attr.sched_policy = SCHED_DEADLINE;

我的gcc版本:

gcc version 5.4.0 20160609 (Ubuntu 5.4.0-6ubuntu1~16.04.9)

但是,official website中发布的示例代码适用于我,但示例代码手动定义了程序中所需的所有宏和系统调用。我的目标是编译应用程序而不添加那些应该已经包含在最新内核版本中的定义。我见过各种各样的地方说在Linux 3.14.10之后正式支持SCHED_DEADLINE,升级内核会自动解决这个问题。

我尝试过的事情:

  • 重新编译4.16内核。以前我认为我需要在配置文件中打开一个开关,但我无法找到它。
  • 查看/usr/include/linux/sched.h。很明显,宏是在这个头文件中定义的,但不知怎的,我的编译器找不到它。

我也查看了社区中的其他帖子,但所有这些问题都是针对较旧的Linux(3.14.10之前的版本)。

1 个答案:

答案 0 :(得分:4)

您需要加入#include <linux/sched.h>

但是对于sched_setattr()gettid()的定义,请参阅@CraigEstey发布的链接

原因是,glibc不会添加linux特定系统调用的函数包装器。 例如gettid(),在手册中我们可以读到:

  

注意:此系统调用没有glibc包装器;见注意事项。

     

Glibc不为此系统调用提供包装器;用它来称呼它   系统调用(2)。   此调用返回的线程ID与POSIX线程ID

不同

看一下这篇文章:https://lwn.net/Articles/711058/

#define _GNU_SOURCE
#include <stdint.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/syscall.h>
#include <sched.h>
#include <linux/sched.h>
#include <sys/types.h>

struct sched_attr {
    uint32_t size;

    uint32_t sched_policy;
    uint64_t sched_flags;

    /* SCHED_NORMAL, SCHED_BATCH */
    int32_t sched_nice;

    /* SCHED_FIFO, SCHED_RR */
    uint32_t sched_priority;

    /* SCHED_DEADLINE (nsec) */
    uint64_t sched_runtime;
    uint64_t sched_deadline;
    uint64_t sched_period;
};

int sched_setattr(pid_t pid, const struct sched_attr *attr, unsigned int flags)
{
   return syscall(__NR_sched_setattr, pid, attr, flags);
}

int main(int argc, char* argv[]) {

    struct sched_attr attr = {
        .size = sizeof(attr),
        .sched_policy = SCHED_DEADLINE,
        .sched_runtime = 30000000,
        .sched_period = 100000000,
        .sched_deadline = 100000000
    };

    pid_t tid = syscall(SYS_gettid);

    if (sched_setattr(tid, &attr, 0))
        perror("sched_setattr()");

    return 0;
}

或更短的代码,无需重新定义struct sched_attr

#define _GNU_SOURCE
#include <stdint.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/syscall.h>
#include <linux/sched/types.h>
#include <linux/sched.h>
#include <sys/types.h>

int sched_setattr(pid_t pid, const struct sched_attr *attr, unsigned int flags)
{
   return syscall(__NR_sched_setattr, pid, attr, flags);
}

int main(int argc, char* argv[]) {

    struct sched_attr attr = {
        .size = sizeof(attr),
        .sched_policy = SCHED_DEADLINE,
        .sched_runtime = 30000000,
        .sched_period = 100000000,
        .sched_deadline = 100000000
    };

    pid_t tid = syscall(SYS_gettid);

    if (sched_setattr(tid, &attr, 0))
        perror("sched_setattr()");

    return 0;
}

但是这需要以root身份执行,否则我得到sched_setattr(): Operation not permitted 或者应用程序需要具备正确的Linux功能。