XV6:ptable 初始化

Posted

技术标签:

【中文标题】XV6:ptable 初始化【英文标题】:XV6: ptable initialization 【发布时间】:2015-06-09 11:43:22 【问题描述】:

我说的是:

struct 
struct spinlock lock;
struct proc proc[NPROC];
 ptable;

位于 proc.c 文件中。

有人能解释一下它是在哪里初始化的吗? 因为,在 proc.c 中,我从未见过向其中添加某些东西(进程)。

更准确地说,假设我正在查看调度程序代码:

void
scheduler(void)

 struct proc *p;
 for(;;)
 // Enable interrupts on this processor.
 sti();
 // Loop over process table looking for process to run.
 acquire(&ptable.lock);
 for(p = ptable.proc; p < &ptable.proc[NPROC]; p++)
  if(p−>state != RUNNABLE)
  continue;
  // Switch to chosen process. It is the process’s job
  // to release ptable.lock and then reacquire it
  // before jumping back to us.
  proc = p;
  switchuvm(p);
  p−>state = RUNNING;
  swtch(&cpu−>scheduler, proc−>context);
  switchkvm();
  // Process is done running for now.
  // It should have changed its p−>state before coming back.
  proc = 0;
  
 release(&ptable.lock);
 

在:

for(p = ptable.proc; p < &ptable.proc[NPROC]; p++)

你可以看到我们正在循环遍历 ptable 中的每个进程。我的问题是,他们是如何到达那里的? 谢谢!

【问题讨论】:

由于ptable 没有在您发布的代码中声明,并且它不是函数的参数,我不得不得出结论它是一个全局变量。它在哪里声明?也许它是静态初始化的?也许隐式初始化为零,作为一个全局变量? 这就是重点,我找不到初始化它的代码。我不确定它是否是全球性的,但我会听从您的建议并在其他文件中检查ptable 的初始化。谢谢。 【参考方案1】:

您不会在 xv6 的代码中找到初始化。原因如下。

C 将 proc 的 int 和 enum 变量初始化为 0。当ptable 实现时,struct proc proc[NPROC]; 创建一个包含 64 个进程的数组,其字段被语言初始化为 0。 0 恰好是 UNUSED 枚举的值。

allocproc 循环通过 ptable.proc 寻找 state=UNUSED,然后将它找到的第一个初始化为所有需要的值。所以不需要显式初始化数组中的结构。

【讨论】:

宏被声明为#define NPROC 64 // 最大进程数。源代码位于 [github.com/mit-pdos/xv6-public]【参考方案2】:

已初始化。

struct 
struct spinlock lock;
struct proc proc[NPROC];
 ptable;

上面的代码定义了一个结构体(没有名字)并将ptable初始化为这种类型的结构体。 也许你对这种语法感到困惑:

struct ptable 
struct spinlock lock;
struct proc proc[NPROC];
;

这里我们只定义了一个结构名ptable,并没有初始化。

【讨论】:

【参考方案3】:
struct 
    struct spinlock lock;
    struct proc proc[NPROC];
ptable;

它在堆栈上分配并自动初始化。这里的诀窍是它是用 GCC 方式编写的,也称为匿名结构。

【讨论】:

【参考方案4】:

ptable 结构体是一个全局变量,在 xv6 内核启动期间作为bootmain() 调用的一部分被加载到内存中。由于它是全局的,因此会初始化默认值。 现在来了解它们如何实际用于存储进程以及何时修改条目。

第一个进程由userinit() 创建,它选择一个未使用的条目并将其用于设置自己的 PCB。 在内核生成手工制作的 initproc 之后,会发生对调度程序的第一次调用,这就是您在此处所指的内容。 由于调度程序将选择一个 RUNNABLE 进程,而我们现在唯一的一个就是 initproc 本身,它就是开始运行的那个。 它调用fork() 以生成一个shell,该shell 在每次调用时调用allocproc() 从ptable 获取另一个未使用的条目并将其分配给进程。

这是在 fork 期间填充 ptable 的方式,并帮助 xv6 记录活动进程。

【讨论】:

以上是关于XV6:ptable 初始化的主要内容,如果未能解决你的问题,请参考以下文章

homework1:boot xv6

xv6/bootasm.S + xv6/bootmain.c

XV6锁

XV6- 循环调度器

XV6调度

运行xv6