在XV6/C中获取并打印进程名称的实现问题咨询
XV6 打印进程名称的实现方案
XV6的进程控制块(PCB)proc结构体中同时存储了进程ID(pid字段)和进程名称(name字段),你提到的通过PID查询进程名的思路完全可行,直接遍历全局进程表匹配PID即可获取对应名称,以下是分场景的具体实现步骤:
场景1:内核态直接打印
如果只需在内核代码中调用该功能,不需要新增系统调用,直接操作内核进程表即可:
- 引入头文件
#include "proc.h" - 遍历全局进程表匹配PID,找到后直接打印
name字段,示例代码如下:
void print_proc_name(int target_pid) { struct proc *p; // 遍历全局进程表 for(p = proc; p < &proc[NPROC]; p++) { // 跳过未使用的进程槽位 if(p->state == UNUSED) continue; if(p->pid == target_pid) { cprintf("PID %d 对应的进程名称:%s\n", target_pid, p->name); return; } } cprintf("未找到PID为 %d 的进程\n", target_pid); }
场景2:用户态调用打印功能
如果需要在用户程序中实现打印逻辑,需要新增对应系统调用,步骤如下:
- 新增系统调用号:在
kernel/syscall.h中添加定义#define SYS_getprocname 22 - 添加系统调用入口:在
kernel/syscall.c中先声明函数extern uint64 sys_getprocname(void);
再在syscalls函数指针数组中新增条目[SYS_getprocname] sys_getprocname, - 实现系统调用逻辑:在
kernel/proc.c中编写函数
uint64 sys_getprocname(void) { int pid; char *buf; int buf_size; // 读取用户态传入的参数:目标PID、缓冲区地址、缓冲区大小 if(argint(0, &pid) < 0 || argaddr(1, (uint64*)&buf) < 0 || argint(2, &buf_size) < 0) return -1; struct proc *p; for(p = proc; p < &proc[NPROC]; p++) { if(p->state != UNUSED && p->pid == pid) { // 把进程名拷贝到用户态缓冲区 if(copyout(p->pagetable, (uint64)buf, p->name, buf_size) < 0) return -1; return 0; } } return -1; // 未找到对应进程 }
- 添加用户态声明:在
user/user.h中新增函数定义int getprocname(int pid, char *buf, int n); - 新增系统调用存根:在
user/usys.pl中添加条目entry("getprocname"); - 编写用户测试程序,示例
user/test_procname.c如下:
#include "user.h" int main(int argc, char *argv[]) { if(argc < 2) { printf("用法:test_procname <pid>\n"); exit(1); } int pid = atoi(argv[1]); char name_buf[16]; // XV6进程名最长15字节+结束符,分配16字节足够 if(getprocname(pid, name_buf, sizeof(name_buf)) == 0) { printf("PID %d 进程名称:%s\n", pid, name_buf); } else { printf("未找到PID为%d的进程\n", pid); } exit(0); }
- 修改Makefile,在
UPROGS配置项中添加$U/_test_procname\,重新编译XV6即可运行测试。
内容的提问来源于stack exchange,提问作者Danielle Marshall
相关产品推荐
相关产品推荐

