相对于使用libc构建的新Linux标头进行构建 [英] Build against newer linux headers than libc is built using

查看:216
本文介绍了相对于使用libc构建的新Linux标头进行构建的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想使用新的 SCHED_DEADLINE 自Linux 3.14 起可用的调度策略.

我从一个简单的程序开始尝试使用sched_setattr函数.

#include <sched.h>

int main(void)
{
    // struct sched_attr attr;
    // attr.size = sizeof(struct sched_attr);
    // attr.sched_policy = SCHED_DEADLINE;
    sched_setattr(0, (void*)0, 0);

    return 0;
}

但是,编译时出现以下错误:

$gcc dead.c 
dead.c: In function ‘main’:
dead.c:8:2: warning: implicit declaration of function ‘sched_setattr’ [-Wimplicit-function-declaration]
  sched_setattr(0, (void*)0, 0);
  ^~~~~~~~~~~~~
/tmp/ccGxWxZE.o: In function `main':
dead.c:(.text+0x19): undefined reference to `sched_setattr'
collect2: error: ld returned 1 exit status

我的系统正在运行Ubuntu 16.10 Yakkety,其内核为4.8.0-59-generic.包含的sched.h文件可在/usr/include/sched.h中找到,并由软件包libc6-dev提供.该头文件不包含函数sched_setattr和我要使用的朋友.

但是,我安装的内核(和内核头文件)带有一个sched.h头文件,其中包含我需要的定义.它位于我系统上的/usr/src/linux-headers-4.8.0-58/include/linux/sched.h.

因此,我天真地认为让我们仅根据较新的linux头文件而不是libc6-dev提供的头文件进行构建.我的程序只能在此或更新的内核上运行,但这很好.

我将第一行修改为:#include <linux/sched.h>并执行:

gcc -I/usr/src/linux-headers-$(uname -r)/include -I/usr/src/linux-headers-$(unam -r)/arch/x86/include dead.c

现在我得到的是错误和警告的页面.这似乎不是要走的路.

针对比libc提供的Linux头更新的Linux头构建用户空间程序的正确方法是什么?

然后我该如何在上面构建程序?

解决方案

sched_setattr()是一个系统调用,似乎没有一对一的libc包装器.您可以自己进行包装,如下所示:

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

struct sched_attr {
    uint32_t size;              /* Size of this structure */
    uint32_t sched_policy;      /* Policy (SCHED_*) */
    uint64_t sched_flags;       /* Flags */
    int32_t sched_nice;         /* Nice value (SCHED_OTHER, SCHED_BATCH) */
    uint32_t sched_priority;    /* Static priority (SCHED_FIFO, SCHED_RR) */
    /* Remaining fields are for SCHED_DEADLINE */
    uint64_t sched_runtime;
    uint64_t sched_deadline;
    uint64_t sched_period;
};

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

int main (int argc, char *argv[])
{
    struct sched_attr attr;
    int res;

    memset (&attr, 0, sizeof (struct sched_attr));
    attr.size = sizeof (struct sched_attr);

    res = sched_setattr (getpid (), &attr, 0);
    if (res < 0) {
        perror ("sched_setattr");
        return 1;
    }

    return 0;
}

在尝试包含获取struct sched_attr定义所需的内核头文件并阅读谷歌搜索用户空间中的内核头"时发现的注释时,我发现确实不建议尝试包含内核头文件就是为此.

I want to write a program using the new SCHED_DEADLINE scheduling policy available since Linux 3.14.

I start out with a simple program trying to use the sched_setattr function.

#include <sched.h>

int main(void)
{
    // struct sched_attr attr;
    // attr.size = sizeof(struct sched_attr);
    // attr.sched_policy = SCHED_DEADLINE;
    sched_setattr(0, (void*)0, 0);

    return 0;
}

However when compiling I get the following error:

$gcc dead.c 
dead.c: In function ‘main’:
dead.c:8:2: warning: implicit declaration of function ‘sched_setattr’ [-Wimplicit-function-declaration]
  sched_setattr(0, (void*)0, 0);
  ^~~~~~~~~~~~~
/tmp/ccGxWxZE.o: In function `main':
dead.c:(.text+0x19): undefined reference to `sched_setattr'
collect2: error: ld returned 1 exit status

My system is running Ubuntu 16.10 Yakkety, with kernel 4.8.0-59-generic. The sched.h file included is found in /usr/include/sched.h and is provided by the package libc6-dev. This headerfile does not contain the function sched_setattr and friends that I am trying to use.

However the kernel (and kernel headers) I have installed comes with a sched.h header file containing the definitions I need. It is located at /usr/src/linux-headers-4.8.0-58/include/linux/sched.h, on my system.

So I naively think lets just build against the newer linux headers instead of the libc6-dev provided headers. My program will only run on this or newer kernels, but that is just fine.

I modify the first line to be: #include <linux/sched.h> and execute:

gcc -I/usr/src/linux-headers-$(uname -r)/include -I/usr/src/linux-headers-$(unam -r)/arch/x86/include dead.c

Now I am getting page after page of errors and warning. This does not seem the way to go.

What is the correct way to build a userspace program against a newer Linux headers than those that are provided by libc?

And subsequently how do I build the program above?

解决方案

sched_setattr() is a syscall and doesn't seem to have one-to-one libc wrapper. You could do the wrapper yourself, something like this:

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

struct sched_attr {
    uint32_t size;              /* Size of this structure */
    uint32_t sched_policy;      /* Policy (SCHED_*) */
    uint64_t sched_flags;       /* Flags */
    int32_t sched_nice;         /* Nice value (SCHED_OTHER, SCHED_BATCH) */
    uint32_t sched_priority;    /* Static priority (SCHED_FIFO, SCHED_RR) */
    /* Remaining fields are for SCHED_DEADLINE */
    uint64_t sched_runtime;
    uint64_t sched_deadline;
    uint64_t sched_period;
};

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

int main (int argc, char *argv[])
{
    struct sched_attr attr;
    int res;

    memset (&attr, 0, sizeof (struct sched_attr));
    attr.size = sizeof (struct sched_attr);

    res = sched_setattr (getpid (), &attr, 0);
    if (res < 0) {
        perror ("sched_setattr");
        return 1;
    }

    return 0;
}

Looking at the errors reported when trying to include kernel header files required to get the definition of struct sched_attr and reading the comments found by Googling "kernel headers in user space", I really can't suggest trying to include kernel header files just for this.

这篇关于相对于使用libc构建的新Linux标头进行构建的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆