Ram*_*avi 4 c unix system-calls xv6
我知道我们不能直接将参数传递给 xv6 系统调用,我们被迫使用它的内置方法。
但是本站点中的所有示例和问题都是关于如何将整数发送到系统调用。它的答案是使用 argint() 方法。
但我的问题是,是否有将“struct”传递给 xv6 系统调用的方法?是否有任何内置方法用于此目的?
如果有的话,能否举个简单的例子?
小智 5
可以通过系统调用传递结构。
虽然不能将结构本身作为系统调用参数传递,但可以传递指向它的指针,并且允许将其用作输入或输出参数。
允许使用数据本身作为参数而不是指向它的指针将破坏系统调用机制的要求——因为必须以通用方式实现传递数据,以允许使用所有数据类型(以及未来的结构)。
让我们看看系统调用 fstat 的现有实现。
int fstat(int fd, struct stat *st);
Run Code Online (Sandbox Code Playgroud)
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
};
Run Code Online (Sandbox Code Playgroud)
尽管 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);
}
Run Code Online (Sandbox Code Playgroud)
这个函数首先得到一个对应的struct file与第一个fstat函数参数(使用argfd)接收到的文件描述符号对应。然后,使用 argptr 获取由第二个 fstat 函数参数接收的 struct stat 指针,并将给定的指针保存在本地(函数作用域)指针变量中。
此时,所有参数都已获取并可被内核实现使用。
注意:虽然 struct stat 指针是一个用户空间指针(位于虚拟空间的下半部分),但内核在这里使用它是安全的,因为当内核为进程的系统调用提供服务时,它使用进程自己的分页表。
虽然上面的答案是正确的,但我更喜欢编写自己的解决方案,以使其对其他查看者更有用。
我使用 argptr 将结构指针传递给我的系统调用。
在 sysproc.c 中:
int sys_counts (void){
struct countTable *ct;
argptr (0 , (void*)&ct ,sizeof(*ct));
return counts(ct);
}
Run Code Online (Sandbox Code Playgroud)
在 proc.c 中:
int counts (struct countTable *ct){
for (int i=0 ; i<22 ; i++){
(ct->system_calls)[i] = count_calls[i] ;
}
return 22;
}
Run Code Online (Sandbox Code Playgroud)
最后在我的用户空间程序中:
int main (){
struct countTable *ct = malloc (sizeof (struct countTable));
// call system call
counts(ct);
exit();
}
Run Code Online (Sandbox Code Playgroud)