# How fork() works

## Flow&#x20;

1\. Create new process&#x20;

2\. Copy user memory from parent to child&#x20;

3\. Set size, and parent.&#x20;

4\. Save user registers.&#x20;

5\. Increment reference counts on open file descriptors.&#x20;

6\. Set pid, change state to runnable&#x20;

7\. return 0

```c
// Create a new process, copying the parent.
// Sets up child kernel stack to return as if from fork() system call.
int
fork(void)
{
  int i, pid;
  struct proc *np;
  struct proc *p = myproc();

  // Allocate process.
  if((np = allocproc()) == 0){
    return -1;
  }

  // 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;

  np->parent = p;

  // copy saved user registers.
  *(np->tf) = *(p->tf);

  // Cause fork to return 0 in the child.
  np->tf->a0 = 0;

  // increment reference counts on open file descriptors.
  for(i = 0; i < NOFILE; i++)
    if(p->ofile[i])
      np->ofile[i] = filedup(p->ofile[i]);
  np->cwd = idup(p->cwd);

  safestrcpy(np->name, p->name, sizeof(p->name));

  pid = np->pid;

  np->state = RUNNABLE;

  release(&np->lock);

  return pid;
}
```

#### Copy memory from parent to child

Given a parent process's page table, copy its memory into a child’s page table.&#x20;

Copies both the page table and the physical memory. returns 0 on success, -1 on failure.&#x20;

Free any allocated pages on failure.

```c
int
uvmcopy(pagetable_t *old*, pagetable_t *new*, uint64 *sz*)
{
  pte_t *pte;
  uint64 pa, i;
  uint flags;

  for(i = 0; i < sz; i += PGSIZE){
    if((pte = walk(old, i, 0)) == 0)
      panic(“uvmcopy: pte should exist”);
    if((*pte & PTE_V) == 0)
      panic(“uvmcopy: page not present”);
    pa = PTE2PA(*pte);
    flags = PTE_FLAGS(*pte);
    flags = flags & ~PTE_W;

    // Clear parent and child PTE_W bit.
    *pte |= flags;
    if(mappages(new, i, PGSIZE, (uint64)pa, flags) != 0){
      goto err;
    }
  }
  return 0;

 err:
  uvmunmap(new, 0, i, 1);
  return -1;
}
```

We have the process current size sz, and for each page, we copy to child.&#x20;

Each i is the address of each page, calling walk() find out the Page Table Entry(pte).&#x20;

We can get flags and physical address from PTE.&#x20;

Allocate memory for child, copy the content, and flags.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://xiayingp.gitbook.io/build_a_os/traps-and-interrupts/how-fork-works.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
