编译程序遇rdtscl隐式声明错误,新旧内核表现不同求助
rdtscl隐式声明的编译错误 老哥,你的问题本质是RHEL/CentOS 7内核版本升级后,rdtscl这个TSC读取宏的可见性发生了变化。咱们一步步拆解解决:
先搞懂
rdtscl是什么:它不是普通函数,是一个用来读取x86架构时间戳计数器(TSC)的内联宏。在旧版3.10.0-327.el7内核里,这个宏默认在某个公共头文件中定义,所以编译没问题;但到了3.10.0-957.el7,内核对TSC相关API做了调整,默认不再暴露这个宏了。为什么加
linux/proc_fs.h没用:找错头文件啦!rdtscl的定义根本不在这个头文件里,它属于架构相关的头文件,你需要包含这两个:#include <asm/msr.h> #include <asm/tsc.h>这两个头文件是x86架构下处理TSC和MSR寄存器的标准头文件,大部分内核版本里
rdtscl都在这里定义。加函数原型无效的原因:因为
rdtscl是宏不是函数,你声明函数原型后,编译器还是找不到对应的宏展开,反而会混淆后续的符号解析。自己定义函数出现重定义的问题:内核里可能已经通过宏的方式“实现”了
rdtscl(比如用内联汇编展开),你自己再写同名函数就会和宏展开后的代码冲突,或者内核本身有同名的静态符号,导致重定义错误。如果包含头文件还是不行?手动实现兼容版本:
直接用内联汇编写一个和原rdtscl行为一致的静态内联函数,这样既不会和内核符号冲突,也能实现功能:static inline void rdtscl(unsigned long *val) { unsigned int lo, hi; // 内联汇编读取TSC寄存器,lo存低32位,hi存高32位 __asm__ __volatile__ ("rdtsc" : "=a"(lo), "=d"(hi)); *val = ((unsigned long)hi << 32) | lo; }把这段代码放在你的
isr_demux.c文件开头(在使用rdtscl之前),就能替代原来的宏了。内核版本差异的本质:RHEL/CentOS的内核是红帽定制的长期支持版本,每个小版本都会修复安全漏洞、调整内部API。3.10.0-957相比327,大概率是把
rdtscl这类内部使用的宏从公共头文件移到了更隐蔽的位置,或者默认不再导出,所以需要显式处理。
内容的提问来源于stack exchange,提问作者Justin

