将结构传递给xv6系统调用

ojsjcaue  于 2022-10-17  发布在  Unix
关注(0)|答案(3)|浏览(183)

我知道我们不能直接将参数传递给xv6系统调用,我们被迫使用它的内置方法。
但是这个站点上的所有例子和问题都是关于如何将整数发送到系统调用。它的答案是使用argint()方法。
但我的问题是,有没有办法将“struct”传递给xv6系统调用?为了这个目的,也有什么巩固的方法吗?
如果有的话,你能举个简单的例子吗?

jvidinwx

jvidinwx1#

可以通过系统调用传递结构。
虽然不能将结构本身作为系统调用参数传递,但传递指向它的指针是可能的,并且允许将其用作输入或输出参数。
允许使用数据本身作为参数,而不是指向它的指针将破坏系统调用机制的要求-因为传递数据必须以通用的方式实现,以允许使用所有数据类型(以及未来的结构)。
让我们来看看系统调用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指针是一个用户空间指针(位于虚拟空间的下半部分),但内核在这里使用它是安全的,因为当内核为进程的系统调用提供服务时,它使用进程自己的分页表。

3wabscal

3wabscal2#

虽然上面的答案是正确的,但我更喜欢编写自己的解决方案,使其更适用于其他Viwers。
我使用argptr将指向结构的指针传递给系统调用。
在sysproc.c中:

int sys_counts (void){

    struct countTable *ct;
    argptr (0 , (void*)&ct ,sizeof(*ct));
    return counts(ct);
    }

在pro.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();
    }
col17t5w

col17t5w3#

虽然其中一个答案是可以接受的,但我写的答案是清楚和完整的。

请注意,直接将参数传递给系统调用是不可能的。我们将使用argptr来实现这一点。
在用户空间中,我们定义了一个我们想要使用的结构。在像test.c这样的用户级文件中


# include "types.h"

# include "stat.h"

# include "user.h"

struct Data
{
    ...
    int id; // some fields
    ...
};

int main(int argc, char *argv[])
{
    struct Data *data = malloc(sizeof(struct Data));

    // call the systemcall
    doSomeWork((void *)data);

    exit();

}

在syspro.c中,我们定义了系统调用并使用argptr获取参数:

int sys_doSomeWork(void){

   struct Data *data;
   argptr(0, (void *)&data, sizeof(*data));
   return doSomeWork((void *)data);

}

在pro.c中,我们可以编写系统调用的功能:

int doSomeWork(void *data){
   // cast to (struct Data *)
   struct Data *my_data = (struct Data *)data;

   ...
   // work with my_data
   ...

   return 0;
}

为了使数据结构可以在syspro.c和pro.c中访问,我们在Defs.h中定义了数据结构:

struct Data
{
    ...
    int id; // some fields
    ...
};

相关问题