You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

32位Linux内核下init进程调用syscall被终止的解决方法

问题排查与解决

核心错误分析

你的代码主要问题出在系统调用的汇编实现上,导致内核无法正确处理调用,进而终止init进程:

  • 系统调用号赋值错误:汇编第一行mov %0, %%eax逻辑错误,%0对应未初始化的输出变量ret,正确做法是将系统调用号nr(对应%1)放入%eax。
  • 寄存器约束遗漏:代码修改了%ebp寄存器,但未在clobber列表中声明,编译器无法感知该寄存器被修改,会引发寄存器状态混乱。

修正后的代码

start.S(可保留,补充halt避免意外返回崩溃)

.globl _start
.text
_start:
    call main
    hlt

修正后的init.c

int syscall(int nr, void *a0, void *a1, void *a2, void *a3, void *a4, void *a5) {
    int ret;
    __asm__ __volatile__ (
        "mov %1, %%eax\n\t"  // 正确将系统调用号传入eax
        "mov %2, %%ebx\n\t"
        "mov %3, %%ecx\n\t"
        "mov %4, %%edx\n\t"
        "mov %5, %%esi\n\t"
        "mov %6, %%edi\n\t"
        "mov %7, %%ebp\n\t"
        "int $0x80\n\t"
        "mov %%eax, %0\n\t"
         : "g"(ret) 
         : "g"(nr), "g"(a0), "g"(a1), "g"(a2), "g"(a3), "g"(a4), "g"(a5) 
         : "%eax", "%ebx", "%ecx", "%edx", "%esi", "%edi", "%ebp");  // 添加ebp到被修改寄存器列表
    return ret;
}

int main(void) {
    // write系统调用(0x4)参数:fd=1,buf="Hello",count=5
    syscall(0x4, (void*)1, "Hello", (void*)5, 0, 0, 0);
    while(1) {}
    return 0;
}

额外注意事项

  • 编译链接参数:必须用32位目标编译,例如gcc -m32 -nostdlib start.S init.c -o /bin/init,避免64位编译的兼容性问题。
  • 内核启动配置:确认内核启动时指定了正确的init路径,且根文件系统挂载正常,保证/bin/init可被正确加载。
  • 系统调用匹配:32位Linux内核的系统调用号需与内核实现对应,0x4确实是write调用,但需确保内核已实现该系统调用。

内容的提问来源于stack exchange,提问作者CoderGodToRun

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 21:30:10