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

XV6中自定义getprocinfo系统调用报错,请求排查解决

XV6 自定义getprocinfo系统调用失败排查与修复

问题重现

在XV6中实现了返回当前进程PID、状态的系统调用getprocinfo,调用时始终返回-1,输出提示Error: Not able to access process information!。

内核态实现(sysproc.c)

uint64
sys_getprocinfo(struct proc* user_pi)
{
  struct proc *curproc = myproc();
  struct proc pi;

  acquire(&curproc->lock);
  pi.pid = curproc->pid;
  pi.state = curproc->state;
  release(&curproc->lock);

  if(copyout(curproc->pagetable, (uint64)user_pi, (char*)&pi, sizeof(pi)) < 0)
        return -1;

  return 0;
}

用户态代码(user/getproc.c)

#include "user.h"
//#include "kernel/types.h"


//blueprint for proc info strukturen
struct proc {
        int pid;
        int state;
        //evt annet?
};

//state nr tilsvarer nr i array her:
//enum procstate { UNUSED, USED, SLEEPING, RUNNABLE, RUNNING, ZOMBIE}

int main(void)

{
  //info blir av typen proc info over
  struct proc pi;
  //kaller syscallet med &info som argument
  int result = getprocinfo(&pi);

  if (result < 0) {
        printf("Error: Not able to access process information!
");
  } else {
        printf("Process ID: %d, Process state: %d
", pi.pid, pi.state);
  }

  exit(0);

}

问题排查

  1. 系统调用参数传递逻辑错误
    XV6的sys_*系列函数不能直接接收用户态指针作为参数,必须通过argaddr等内核API从用户态栈中读取参数地址。当前代码直接将用户指针传入sys_getprocinfo,内核无法正确解析用户态地址空间,导致后续copyout失败。

  2. 内核与用户态结构体大小不匹配
    内核中的struct proc包含大量额外字段(如页表、锁、上下文等),而用户态自定义的struct proc仅包含pid和state。copyout时使用sizeof(struct proc)(内核中完整结构体大小)进行拷贝,会导致越界访问用户态内存,触发错误。

  3. 字符串换行符未转义
    用户态代码中printf的字符串直接使用换行而不是\n,会导致编译错误或输出异常。


修复方案

修复后的内核态代码(sysproc.c)

uint64
sys_getprocinfo(void)
{
  struct proc *curproc = myproc();
  // 定义与用户态完全一致的结构体,避免大小不匹配
  struct {
    int pid;
    int state;
  } pi;
  uint64 user_buf;

  // 从用户态栈中读取第一个参数:用户态缓冲区地址
  if(argaddr(0, &user_buf) < 0)
    return -1;

  acquire(&curproc->lock);
  pi.pid = curproc->pid;
  pi.state = curproc->state;
  release(&curproc->lock);

  // 使用用户态结构体的大小进行拷贝
  if(copyout(curproc->pagetable, user_buf, (char*)&pi, sizeof(pi)) < 0)
    return -1;

  return 0;
}

修复后的用户态代码(user/getproc.c)

#include "user.h"

// 与内核中用于拷贝的结构体保持一致
struct proc_info {
    int pid;
    int state;
};

enum procstate { UNUSED, USED, SLEEPING, RUNNABLE, RUNNING, ZOMBIE};

int main(void)
{
  struct proc_info pi;
  int result = getprocinfo(&pi);

  if (result < 0) {
        printf("Error: Not able to access process information!\n");
  } else {
        printf("Process ID: %d, Process state: %d\n", pi.pid, pi.state);
  }

  exit(0);
}

额外必做配置

  • 在syscall.h中添加系统调用编号:#define SYS_getprocinfo 22(替换为未占用的编号)
  • 在syscall.c的syscalls数组中添加条目:[SYS_getprocinfo] sys_getprocinfo,
  • 在user.h中添加函数声明:int getprocinfo(struct proc_info*);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 07:58:40