Process in XV6


How does fork() behave in xv6?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
#include "kernel/types.h"
#include "user/user.h"

int main() {
  int pid = fork();
  if (pid == 0) {
    printf("Child: my pid is %d\n", getpid());
    exit(0);
  } else {
    printf("Parent: my pid is %d, child is %d\n", getpid(), pid);
  }
  exit(0);
}

<details class="details details--default" data-variant="default"><summary>Screenshot: creating p1.c inside xv6-riscv/user</summary>
<figure>
  <picture>
    <!-- Auto scaling with imagemagick -->
    <!--
      See https://www.debugbear.com/blog/responsive-images#w-descriptors-and-the-sizes-attribute and
      https://developer.mozilla.org/en-US/docs/Learn/HTML/Multimedia_and_embedding/Responsive_images for info on defining 'sizes' for responsive images
    -->
    
      
        <source class="responsive-img-srcset" srcset="/assets/img/courses/csc331/process-xv6/01-480.webp 480w,/assets/img/courses/csc331/process-xv6/01-800.webp 800w,/assets/img/courses/csc331/process-xv6/01-1400.webp 1400w," type="image/webp" sizes="95vw" />
      
    
    <img src="/assets/img/courses/csc331/process-xv6/01.png" width="50%" height="auto" data-zoomable="" loading="lazy" onerror="this.onerror=null; $('.responsive-img-srcset').remove();" />
  </picture>

  
</figure>

</details>
- In `Makefile` under `xv6-riscv`, find the section `UPROGS=` and edit to include the `$U/_p1\` line. 

<details class="details details--default" data-variant="default"><summary>Screenshot: Edit xv6-riscv/Makefile</summary>
<figure>
  <picture>
    <!-- Auto scaling with imagemagick -->
    <!--
      See https://www.debugbear.com/blog/responsive-images#w-descriptors-and-the-sizes-attribute and
      https://developer.mozilla.org/en-US/docs/Learn/HTML/Multimedia_and_embedding/Responsive_images for info on defining 'sizes' for responsive images
    -->
    
      
        <source class="responsive-img-srcset" srcset="/assets/img/courses/csc331/process-xv6/02-480.webp 480w,/assets/img/courses/csc331/process-xv6/02-800.webp 800w,/assets/img/courses/csc331/process-xv6/02-1400.webp 1400w," type="image/webp" sizes="95vw" />
      
    
    <img src="/assets/img/courses/csc331/process-xv6/02.png" width="50%" height="auto" data-zoomable="" loading="lazy" onerror="this.onerror=null; $('.responsive-img-srcset').remove();" />
  </picture>

  
</figure>

</details>
- Let's rebuild and relaunch xv6. In a terminal, run the followings

~~~bash
cd ~/xv6-riscv
make clean
make
make qemu
Screenshot: content of ls
What do you expect to see, and what do you have? Why?

What about wait()?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
#include "kernel/types.h"
#include "user/user.h"

int main() {
  int pid = fork();
  if (pid == 0) {
    printf("Child: my pid is %d\n", getpid());
    exit(0);
  } else {
    wait(0);
    printf("Parent: my pid is %d, child is %d\n", getpid(), pid);
  }
  exit(0);
}

<details class="details details--default" data-variant="default"><summary>Screenshot: creating p2.c inside xv6-riscv/user</summary>
<figure>
  <picture>
    <!-- Auto scaling with imagemagick -->
    <!--
      See https://www.debugbear.com/blog/responsive-images#w-descriptors-and-the-sizes-attribute and
      https://developer.mozilla.org/en-US/docs/Learn/HTML/Multimedia_and_embedding/Responsive_images for info on defining 'sizes' for responsive images
    -->
    
      
        <source class="responsive-img-srcset" srcset="/assets/img/courses/csc331/process-xv6/05-480.webp 480w,/assets/img/courses/csc331/process-xv6/05-800.webp 800w,/assets/img/courses/csc331/process-xv6/05-1400.webp 1400w," type="image/webp" sizes="95vw" />
      
    
    <img src="/assets/img/courses/csc331/process-xv6/05.png" width="50%" height="auto" data-zoomable="" loading="lazy" onerror="this.onerror=null; $('.responsive-img-srcset').remove();" />
  </picture>

  
</figure>

</details>
- In `Makefile` under `xv6-riscv`, find the section `UPROGS=` and edit to include the `$U/_p2\` line. 

<details class="details details--default" data-variant="default"><summary>Screenshot: Edit xv6-riscv/Makefile</summary>
<figure>
  <picture>
    <!-- Auto scaling with imagemagick -->
    <!--
      See https://www.debugbear.com/blog/responsive-images#w-descriptors-and-the-sizes-attribute and
      https://developer.mozilla.org/en-US/docs/Learn/HTML/Multimedia_and_embedding/Responsive_images for info on defining 'sizes' for responsive images
    -->
    
      
        <source class="responsive-img-srcset" srcset="/assets/img/courses/csc331/process-xv6/06-480.webp 480w,/assets/img/courses/csc331/process-xv6/06-800.webp 800w,/assets/img/courses/csc331/process-xv6/06-1400.webp 1400w," type="image/webp" sizes="95vw" />
      
    
    <img src="/assets/img/courses/csc331/process-xv6/06.png" width="50%" height="auto" data-zoomable="" loading="lazy" onerror="this.onerror=null; $('.responsive-img-srcset').remove();" />
  </picture>

  
</figure>

</details>
- Let's rebuild and relaunch xv6. In a terminal, run the followings

~~~bash
cd ~/xv6-riscv
make clean
make
make qemu

The implementation of fork() in xv6

Details
1
2
3
int i, pid;
struct proc *np;
struct proc *p = myproc();
Details
1
2
3
4
// Allocate process.
if((np = allocproc()) == 0){
    return -1;
}
Details
1
2
3
4
5
6
7
// Copy user memory from parent to child.
if(uvmcopy(p->pagetable, np->pagetable, p->sz) < 0){
    freeproc(np);
    release(&np->lock);
    return -1;
}
np->sz = p->sz;
Details
1
2
// copy saved user registers.
*(np->trapframe) = *(p->trapframe);
Details
1
2
// Cause fork to return 0 in the child.
np->trapframe->a0 = 0;
Details
1
2
3
4
// increment reference counts on open file descriptors.
for(i = 0; i < NOFILE; i++)
    if(p->ofile[i])
    np->ofile[i] = filedup(p->ofile[i]);
Details
1
np->cwd = idup(p->cwd);
Details
1
safestrcpy(np->name, p->name, sizeof(p->name));
Details
1
pid = np->pid;
Details
1
release(&np->lock);

Details
1
2
3
acquire(&wait_lock);
np->parent = p;
release(&wait_lock);
Details
1
2
3
acquire(&np->lock);
np->state = RUNNABLE;
release(&np->lock);
Details
1
return pid;
Summary of key structures and calls
Symbol Description File
struct proc Per-process control block kernel/proc.h
myproc() Get current process kernel/proc.c
allocproc() Allocate and initialize new proc kernel/proc.c
uvmcopy() Copy address space (page tables) kernel/vm.c
trapframe Saved user-space CPU registers kernel/riscv.h
filedup() Increment file descriptor refcount kernel/file.c
idup() Increment inode refcount kernel/fs.c
safestrcpy() Safe string copy kernel/string.c
wait_lock Lock for parent/child relationships kernel/proc.c