segfault的原因是什么,如何修改下面的代码来修复它?
我想在破解内核模块之前解决这个问题,因为我不希望这个段错误炸毁我的内核.
更新:我在Intel(R)Xeon(R)cpu X3470上运行.
#define _GNU_SOURCE#include <stdio.h>#include <stdlib.h>#include <inttypes.h>#include <sched.h>#include <assert.h>uint64_tread_msr(int ecx){ unsigned int a,d; __asm __volatile("rdmsr" : "=a"(a),"=d"(d) : "c"(ecx)); return ((uint64_t)a) | (((uint64_t)d) << 32);}int main(int ac,char **av){ uint64_t start,end; cpu_set_t cpuset; unsigned int c = 0x186; int i = 0; cpu_ZERO(&cpuset); cpu_SET(i,&cpuset); assert(sched_setaffinity(0,sizeof(cpuset),&cpuset) == 0); printf("%lu\n",read_msr(c)); return 0;}解决方法 我将尝试回答的问题:为什么上面的代码导致SIGSEGV而不是SIGILL,虽然代码没有内存错误,但是非法指令(从非特权用户速度调用的特权指令)?
我希望得到一个带有si_code ILL_PRVOPC而不是段错误的SIGILL.你的问题目前是3岁,今天我偶然发现了同样的行为.我也很失望:-(
What is the cause of the segfault
原因似乎是linux内核代码决定发送SIGSEGV.这是负责任的职能:
http://elixir.free-electrons.com/linux/v4.9/source/arch/x86/kernel/traps.c#L487
看看函数的最后一行.
在your follow up question中,您获得了其他汇编指令的列表,这些汇编指令作为SIGSEGV传播到用户空间,尽管它们实际上是一般性保护错误.我找到了你的问题,因为我用cli触发了这个行为.
and how can I modify the code below to fix it?
从linux内核4.9开始,我不知道有任何可靠的方法可以区分内存错误(我希望是SIGSEGV)和来自用户空间的特权指令错误.
可能有非常黑客和不可移植的方式来解决这些案件.当特权指令导致SIGSEGV时,siginfo_t si_code被设置为一个值,该值不直接列在man 2 sigaction的SIGSEGV部分中.记录的值是SEGV_MAPERR,SEGV_ACCERR,SEGV_PKUERR,但我的系统上得到了SI_KERNEL(0x80).根据手册页,SI_KERNEL是一个代码“可以放在任何信号的si_code中”.在strace中,您会看到SIGSEGV {si_signo = SIGSEGV,si_code = SI_KERNEL,si_addr = 0}.负责的内核代码是here.
也可以为this字符串grep dmesg.
请永远不要使用这两种方法来区分生产系统上的GPF和内存错误.
代码的特定解决方案:只是不要从用户空间运行rdmsr.但是,如果您正在寻找一种通用的方法来弄清楚程序收到SIGSEGV的原因,那么这个答案实在令人不满意.
总结以上是内存溢出为你收集整理的linux – 为什么segfault而不是特权指令错误?全部内容,希望文章能够帮你解决linux – 为什么segfault而不是特权指令错误?所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)