自定义Linux系统中自定义init进程启动失败(错误码-8)原因排查
自定义Linux init进程启动报SIGFPE(错误码-8)问题解决
问题背景
为瘦客户端构建自定义Linux系统,通过Qemu模拟运行。使用以下命令编译init进程:
$ gcc -fpic -static -nostdlib init.c -o init
将可执行文件放置到/bin/目录后,系统启动失败,报错如下:
Run /bin/init as init process Kernel panic - not syncing: Requested init /bin/init failed (error -8). Kernel Offset: disabled
错误码-8对应信号SIGFPE,但检查代码及汇编后未发现除零等数学异常操作,且任意源码编译后均出现此问题。示例代码如下:
size_t strlen(const char* s) { for(unsigned i = 0; ; ++i) if(s[i] == 0) return i; } void puts(char* s) { asm("mov %0, %%r11" :: "r"(s)); asm("mov %0, %%r14" :: "r"(strlen(s))); asm("mov $1, %rax" "mov %r11, %rsi" "mov %r14, %rdx" "mov $1, %rdi" "syscall"); } int _start() { puts("test"); asm volatile( "mov $60, %rax" "push %r11" "mov %r11, %rdi" "pop %r11" "syscall" ); return 0; }
原因分析
问题出在编译选项-fpic与-static的结合上。x86_64架构下,静态编译的二进制不需要生成位置无关代码(PIC),强制添加-fpic会导致ELF文件的PLT/GOT结构异常,内核加载执行时触发非法内存访问或指令错误,最终被内核映射为SIGFPE信号返回。
解决方案
- 修改编译命令:移除
-fpic选项,静态编译无需位置无关代码,命令改为:
$ gcc -static -nostdlib init.c -o init
- 可选:优化汇编代码:确保系统调用的寄存器使用符合x86_64规范,比如精简_exit系统调用的冗余操作:
int _start() { puts("test"); asm volatile( "mov $60, %rax" "mov $0, %rdi" "syscall" ); return 0; }
验证
重新编译init并替换到系统/bin/目录,启动Qemu后应该能正常输出"test"并完成退出流程,不再触发内核panic。
内容的提问来源于stack exchange,提问作者drk1
相关产品推荐
相关产品推荐

