【发布时间】:2019-04-22 08:41:32
【问题描述】:
我知道我们不能直接将参数传递给 xv6 系统调用,我们不得不使用它的内置方法。
但本网站中的所有示例和问题都是关于如何将整数发送到系统调用。它的答案是使用 argint() 方法。
但我的问题是,有没有办法将“struct”传递给 xv6 系统调用?是否也有为此目的的内置方法?
如果有,可以举个简单的例子吗?
【问题讨论】:
标签: c unix system-calls xv6
我知道我们不能直接将参数传递给 xv6 系统调用,我们不得不使用它的内置方法。
但本网站中的所有示例和问题都是关于如何将整数发送到系统调用。它的答案是使用 argint() 方法。
但我的问题是,有没有办法将“struct”传递给 xv6 系统调用?是否也有为此目的的内置方法?
如果有,可以举个简单的例子吗?
【问题讨论】:
标签: c unix system-calls xv6
可以通过系统调用传递结构体。
虽然不能将结构本身作为系统调用参数传递,但可以传递指向它的指针,并且允许将其用作输入或输出参数。
允许使用数据本身而不是指向它的指针作为参数将破坏系统调用机制的要求 - 因为传递数据必须以通用方式实现以允许所有数据类型(以及未来的结构)使用。
让我们看一下系统调用 fstat 的现有实现。
int fstat(int fd, struct stat *st);
fstat 需要一个文件描述符编号作为输入,并使用 struct stat 输出匹配的统计信息。
struct stat {
short type; // Type of file
int dev; // File system's disk device
uint ino; // Inode number
short nlink; // Number of links to file
uint size; // Size of file in bytes
};
虽然 fstat 使用结构指针作为输出参数,但使用它作为输入将是类似的。
内核代码中的函数sys_fstat启动fstat系统调用的实现(XV6的约定是通过sys_*函数从用户空间获取参数)。
int sys_fstat(void)
{
struct file *f;
struct stat *st;
if(argfd(0, 0, &f) < 0 || argptr(1, (void*)&st, sizeof(*st)) < 0)
return -1;
return filestat(f, st);
}
这个函数首先得到一个对应于第一个 fstat 函数参数(使用 argfd)接收到的文件描述符号的结构文件。然后,使用 argptr 获取第二个 fstat 函数参数接收到的 struct stat 指针,并将给定的指针保存在本地(函数范围)指针变量中。
此时,所有参数都已获取并可供内核实现使用。
注意: 虽然 struct stat 指针是一个用户空间指针(位于虚拟空间的下半部分),但内核在这里使用它是安全的,因为当内核处于服务进程的系统调用,它使用进程自己的分页表。
【讨论】:
虽然上面的答案是正确的,但我更喜欢编写自己的解决方案以使其对其他 viwers 更有用。
我使用 argptr 将指向结构的指针传递给我的系统调用。
在 sysproc.c 中:
int sys_counts (void){
struct countTable *ct;
argptr (0 , (void*)&ct ,sizeof(*ct));
return counts(ct);
}
在 proc.c 中:
int counts (struct countTable *ct){
for (int i=0 ; i<22 ; i++){
(ct->system_calls)[i] = count_calls[i] ;
}
return 22;
}
最后在我的用户空间程序中:
int main (){
struct countTable *ct = malloc (sizeof (struct countTable));
// call system call
counts(ct);
exit();
}
【讨论】: