解决 redefinition of ‘struct sched_attr’错误的完整指南

解决 redefinition of ‘struct sched_attr’错误的完整指南


一、错误原因

该错误是由于 ​代码中重复定义了 struct sched_attr结构体​ 导致的。在 Linux 系统中,sched_attr是用于调度属性的系统调用接口结构体,其定义原本位于 glibc(GNU C Library)中。当以下两种情况同时发生时,会触发此错误:

  1. glibc 版本 ≥ 2.41​:从 glibc 2.41 开始,struct sched_attr被引入到标准头文件(如 <linux/sched/types.h>)中。 

  2. 代码中手动定义了该结构体​:例如内核模块、用户态工具(如 qemurt-tests)或第三方库中直接定义了 struct sched_attr,导致与 glibc 的定义冲突。


二、解决方案

1. 条件编译避免重复定义

在代码中添加条件编译,仅在 glibc 未定义 sched_attr时才定义该结构体。

修改前(冲突代码)​​:

c
下载
复制
运行
 
 
struct sched_attr {  // 直接定义
    uint32_t size;
    uint32_t sched_policy;
    // ... 其他字段
};

修改后(安全代码)​​:

c
下载
复制
运行
 
 
#ifndef SCHED_ATTR_SIZE_VER0  // 检查 glibc 是否已定义
struct sched_attr {
    uint32_t size;
    uint32_t sched_policy;
    // ... 其他字段
};
#endif /* SCHED_ATTR_SIZE_VER0 */
  • 原理​:glibc 2.41+ 会定义 SCHED_ATTR_SIZE_VER0宏,通过条件编译避免重复定义。 

2. 更新代码以使用 glibc 的定义

若代码需要兼容新版 glibc,应直接使用 glibc 提供的 sched_attr定义,而非手动定义。

步骤​:

  1. 移除代码中手动定义的 struct sched_attr

  2. 包含 glibc 头文件:

    #include <linux/sched/types.h>  // 包含 sched_attr 的官方定义
  3. 使用 syscall调用接口时,直接传递 struct sched_attr变量。

3. 降级 glibc 版本(不推荐)​

若无法修改代码,可临时降级 glibc 到 2.40 或更低版本。

风险提示​:此方法可能导致其他依赖 glibc 新特性的程序异常,仅建议在隔离环境中使用。


三、实际案例修复

qemu编译为例(参考搜索结果

):

 

  1. 定位冲突文件​:

    找到 linux-user/syscall.c中定义 sched_attr的位置(如第 363 行)。

  2. 添加条件编译​:

    修改代码如下:

    c
    下载
    复制
    运行
     
     
    /* From GLIBC 2.41 it is defined! */
    #ifndef SCHED_ATTR_SIZE_VER0
    struct sched_attr {
        uint32_t size;
        uint32_t sched_policy;
        uint64_t sched_flags;
        int32_t sched_nice;
        uint32_t sched_priority;
        uint64_t sched_runtime;
        uint64_t sched_deadline;
        uint64_t sched_period;
        uint32_t sched_util_min;
        uint32_t sched_util_max;
    };
    #endif
  3. 重新编译​:

    bash
    复制
     
     
    meson setup .. && ninja

四、其他相关修复

1. 重命名冲突函数

若代码中同时定义了与 glibc 同名的函数(如 sched_setattr),需重命名函数:

c
下载
复制
运行
 
 
// 原函数名(冲突)
int sched_setattr(pid_t pid, const struct sched_attr *attr, unsigned int flags);

// 修改后(避免冲突)
int syscall_sched_setattr(pid_t pid, const struct sched_attr *attr, unsigned int flags);
2. 使用 #pragma GCC diagnostic忽略警告

临时忽略重复定义警告(不推荐,仅用于调试):

c
下载
复制
运行
 
 
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wredefinition"
struct sched_attr { ... };
#pragma GCC diagnostic pop

五、验证修复

  1. 清理构建缓存​:

    bash
    复制
     
     
    rm -rf build/ && mkdir build && cd build
  2. 重新编译​:

    bash
    复制
     
     
    meson setup .. && ninja
  3. 检查日志​:确认编译日志中不再出现 redefinition of 'struct sched_attr'错误。


六、总结

场景

解决方案

内核模块或工具开发

添加条件编译 #ifndef SCHED_ATTR_SIZE_VER0,或使用 glibc 官方定义

 

第三方库兼容性问题

提交补丁给维护者,或联系供应商获取支持

临时调试环境

降级 glibc 或使用 #pragma GCC diagnostic忽略警告(不推荐)

通过条件编译或适配 glibc 的定义,可有效解决此问题。建议优先采用条件编译方案以保持代码兼容性。

posted on 2025-09-30 18:44  ENGINEER-F  阅读(14)  评论(0)    收藏  举报