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

Pintos中exec系统调用参数未出现在用户栈的问题排查

Pintos系统调用exec参数获取异常问题

场景复现

我正在测试一个经过小幅修改的Pintos项目,用户程序通过以下代码创建子进程:

void
test_main (void) 
{
  msg ("wait(exec()) = %d", wait (exec ("child-simple")));
}

其中wait()和exec()是在userprog/syscall.c中实现的系统调用。根据Pintos的lib/user/syscall.h定义,调用系统调用时会先将参数压入用户栈,再压入系统调用号,相关宏定义如下:

#define syscall1(NUMBER, ARG0)                                           
        ({                                                               
          int retval;                                                    
          asm volatile                                                   
            ("pushl %[arg0]; pushl %[number]; int $0x30; addl $8, %%esp" 
               : "=a" (retval)                                           
               : [number] "i" (NUMBER),                                  
                 [arg0] "g" (ARG0)                                       
               : "memory");                                              
          retval;                                                        
        })

按宏逻辑,调用exec("child-simple")时,应先压入文件名的地址,再压入SYS_EXEC对应的系统调用号2,之后触发int $0x30进入系统调用处理。

当前问题

在syscall_handler()中能正常提取到系统调用号2,但在处理分支中尝试从f->esp +4获取文件名地址时,并未找到预期值:

case SYS_EXEC:{             // f-> esp + 4 doesn't have file address???
      is_valid_vaddr(f->esp + 4);
      f->eax = exec((char*)(f->esp+4));
      break;
    }

通过hex_dump()查看内存的结果如下:

esp position : 0xbfffff74
syscall number : 2
bfffff70              02 00 00 00-79 b2 04 08 01 81 04 08 |    ....y.......|
bfffff80  79 b2 04 08 a7 88 04 08-b8 ff ff 0e c8 c6 04 08 |y...............|
bfffff90  00 00 00 00                                     |....            |

系统调用号02 00 00 00位于地址0xbfffff74,但后续位置未出现文件名地址,导致exec()无法创建子进程。

问题分析与解决

  1. 参数位置判断错误
    宏定义中是先pushl %[arg0](参数),再pushl %[number](系统调用号),因此用户栈在触发中断前的布局是:

    地址: 0xbfffff70 → 参数(文件名地址:0x0804b279,对应dump中的`79 b2 04 08`)
    地址: 0xbfffff74 → 系统调用号2(`02 00 00 00`)
    

    你当前用f->esp +4查找参数,但实际f->esp指向的是系统调用号的位置0xbfffff74,参数应该在f->esp -4的位置,也就是0xbfffff70处的地址。

  2. 修正方案
    将处理代码中的参数获取位置改为f->esp -4,修改后的代码如下:

    case SYS_EXEC:{
          is_valid_vaddr(f->esp - 4);
          f->eax = exec((char*)(f->esp - 4));
          break;
        }
    

    同时可以验证0x0804b279地址是否确实指向用户空间中的"child-simple"字符串,确认参数的正确性。

  3. 额外检查点

    • 确认is_valid_vaddr函数能正确验证用户空间地址,避免因地址校验失败导致后续操作异常;
    • 检查syscall_handler()中f->esp的来源,确保它是用户态触发中断时的原始栈指针,未被内核代码意外修改。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 09:06:01