xv6系统调用字符串传递问题:argstr使用错误排查
解决xv6字符串系统调用的编译错误
错误原因
编译报错的核心问题是调用argstr时参数类型不匹配:
argstr的第二个参数要求是char**类型(用于接收内核缓冲区的地址),但你传了**str——这是对char**类型的str做两次解引用,最终得到的是一个char类型的单个字符,完全不符合函数要求,因此触发类型转换错误。- 另外,你对
argstr的用法理解有误:第一个参数是用户传入的参数索引(比如调用hello("itworks")时,字符串是第0个参数),不是字符串长度;而且xv6的系统调用处理函数不能直接接收用户空间的指针参数,必须通过argstr这类函数把用户空间的字符串复制到内核缓冲区。
修改后的代码
sysproc.c
int sys_hello(void) { char buf[16]; // 定义内核空间的缓冲区,大小足够容纳测试字符串+终止符 // 获取用户传入的第0个参数(即"itworks")到内核缓冲区 if (argstr(0, &buf) < 0) { return -1; // 参数获取失败时返回错误码 } // 遍历打印字符串的每个字符 for (int i = 0; buf[i] != '\0'; i++) { cprintf("%c testplzprint\n", buf[i]); } cprintf("Hello World\n"); return 0; }
关键修改点
- 修正系统调用函数原型:xv6的系统调用处理函数不能直接接收用户空间的指针参数,改为无参数的
int sys_hello(void),通过argstr从用户栈读取参数。 - 正确调用
argstr:- 第一个参数传
0,表示读取用户调用hello时传入的第0个参数(也就是字符串参数)。 - 第二个参数传内核缓冲区的地址的指针
&buf,符合char**的类型要求。
- 第一个参数传
- 遍历打印内核缓冲区:用内核缓冲区
buf代替原来的str,因为str的参数定义本身不符合xv6的系统调用规范。
额外注意事项
确保你已经完成系统调用的完整注册流程:
- 在
syscall.h中添加系统调用号(比如#define SYS_hello 22,根据现有编号调整)。 - 在
syscall.c的syscalls数组中添加[SYS_hello] sys_hello。 - 在
user.h中添加用户态函数声明void hello(char* s);。 - 在
usys.S中添加系统调用的汇编入口SYSCALL(hello)。
内容的提问来源于stack exchange,提问作者mattDavis
相关产品推荐
相关产品推荐

