【问题标题】:How to get number of the system calls after the kernel boot in xv6?如何在 xv6 内核启动后获取系统调用的数量?
【发布时间】:2013-09-16 05:45:31
【问题描述】:

我想编写一个简单的“C”程序来查找操作系统启动后的系统调用次数。我正在关注其他系统调用,如 fork() 或 getpid() 并且基本上复制了他们的大部分内容。我不确定应该在哪里/何时增加我的计数器?有什么例子吗?

在 kernel/syscall.c 中定义计数器并相应地递增它是个好主意吗?

void
syscall(void)
{
  int num;
  counter++; //mona
  num = proc->tf->eax;
  if(num > 0 && num < NELEM(syscalls) && syscalls[num] != NULL) {
    proc->tf->eax = syscalls[num]();
  } else {
    cprintf("%d %s: unknown sys call %d\n",
            proc->pid, proc->name, num);
    proc->tf->eax = -1;
  }
}

这也是我目前在 kernel/sysproc.c 中为我的微不足道的系统调用获得的代码:

sys_getsyscallinfo(void)
{

 return counter;  //mona
}

但是我收到此错误:

kernel/sysproc.c: In function ‘sys_getsyscallinfo’:
kernel/sysproc.c:48: error: ‘counter’ undeclared (first use in this function)
kernel/sysproc.c:48: error: (Each undeclared identifier is reported only once
kernel/sysproc.c:48: error: for each function it appears in.)
make: *** [kernel/sysproc.o] Error 1

【问题讨论】:

  • 你是什么意思 - “我正在关注其他系统调用,如 fork() 或 getpid() 并且基本上复制了他们的大部分内容”?如果你有一些代码,请发布它。
  • @VivekS 遵循pdos.csail.mit.edu/6.828/2012/xv6.html 中的 xv6 代码,您可以为简单的系统调用编写所有必要的(基本)代码。例如,我使用“grep -irn getid *”命令跟踪 getpid,并尝试跟踪它的定义/使用位置,并对我自己的系统调用执行相同操作。但是我不确定当我们调用系统陷阱时是否应该简单地调用一个计数器。或者我们应该如何在启动后实现系统调用次数。
  • 您打算在哪里增加计数器?在你的代码里面?陷阱是操作系统的软件中断,用于更改上下文并执行内核中存在的功能以完成某些工作。因此,每个系统调用都会发出一个陷阱,这些函数分布在许多文件中,包括 glibc 以及其他文件。如果我不理解您的问题,请纠正我。
  • sys_getsyscallinfo 中的计数器在哪里定义? counter 是在 syscall 中定义的局部变量,当您从用户空间调用系统调用时,它会调用 sys_getsyscallinfo(假设这是您的系统调用)。你知道系统调用是如何在操作系统中处理的吗?

标签: c linux operating-system posix fork


【解决方案1】:

我在kernel/defs.h 中将计数器变量定义为extern int,并在系统调用定义中使用它作为kernel/sysproc.c 中的返回值,并在kernel/syscall.c 中完成所有陷阱处理的地方增加了它。希望对你有帮助。

【讨论】:

    【解决方案2】:

    这需要编辑 entry.S 文件。上次我使用内核时,它位于.../arch/kernel/ 目录中。在该文件中,它首先验证系统调用,调用它使用call 指令。您必须在此验证之后和实际执行系统调用之前执行操作。

    您不必担心如何访问用户空间中的变量,该条目中有基本指针。S。

    顺便说一下,这是调用系统调用的“新”方式(感谢 P II+ 处理器).. 最初曾经有软件中断int 0x80。因此,还要检查您正在使用的内核版本。

    我在这里可能是错的。我只是根据一些知识解释一种方式(这可能是最糟糕的和/或错误的)。如果 You/someone_else 实现了这个,请用最少的代码发布成功/失败。

    一旦我从 Windows 中抽出时间(机会较少),我将自己编写这段代码。

    【讨论】:

    • 我将我的系统调用添加到 user/usys.S 系统调用,如下所示:paste.ubuntu.com/6113766 我正在为 xv6 操作系统编写此代码。
    • 内核有主函数吗?如果我实现了两个系统调用,一个使用 sysenter,另一个使用 syscall,这两种方法最终都在同一个入口点函数中吗?如果我使用 0x80 并实现另一个系统调用会怎样?你的意思是说操作系统只支持一种调用系统来执行特权操作的方法吗?
    • 感谢您的具体说明 1--> 这取决于您所谈论的内核。 Unix 有一个 main 函数,其他人可能命名不同,但他们有一些或另一个入口点函数,通常由 bootloader 调用。
    • 2&3 --> 无论你如何实现系统调用,它永远不会调用内核的主/入口点函数。你看,内核为用户空间程序提供服务,但它仍然是一个程序,调用了几个例程,从系统启动开始就一直在运行,所以在处理系统调用时不需要调用内核的入口点
    • 4 --> 不会。操作系统会提供几种机制,但它们都必须遵循一套规则,比如保存当前运行进程的上下文,然后只进入内核模式。机制可以分为中断、异常、系统调用。
    猜你喜欢
    • 2022-01-13
    • 2014-12-20
    • 2011-08-02
    • 2012-02-04
    • 2017-02-14
    • 2017-08-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多