Hi All, code flow of the fork() till dup_mm() do_fork () copy_process copy_mm dup_mm allocates memory to hold struct mm_struct memcpy(mm, current->oldmm, sizeof(*mm)); calls mm_init() mm_init () { mm_alloc_pgd() } My understanding is when a process does a fork 1. a new page table will be allocated to the process 2. it will be exactly same copy of the parent process 3. both the page tables (parent's and child's) will have entries marked as read-only So any write to them will be detected as page fault and page fault handler will treat the pages as COW and will essentially create a new page, update the faulted process's page table and returns. The question is dup_mem() is actually copying the current process's mm_struct to the new process mm_struct. So now new process's mm_struct->pgd will be pointing to pgd of parent process. Then it is calling mm_init() to allocate new pgd, why? My understanding is conflicting with the code, Is my understanding correct? Copying code flow asmlinkage int sys_fork(struct pt_regs regs) { return do_fork(SIGCHLD, regs.sp, ®s, 0, NULL, NULL); } long do_fork(unsigned long clone_flags, unsigned long stack_start, struct pt_regs *regs, unsigned long stack_size, int __user *parent_tidptr, int __user *child_tidptr) { struct task_struct *p; p = copy_process(clone_flags, stack_start, regs, stack_size, child_tidptr, NULL, trace); } static struct task_struct *copy_process(unsigned long clone_flags, unsigned long stack_start, struct pt_regs *regs, unsigned long stack_size, int __user *child_tidptr, struct pid *pid, int trace) { struct task_struct *p; ..... ..... p = dup_task_struct(current); if (!p) goto fork_out; ..... ..... if ((retval = copy_mm(clone_flags, p))) goto bad_fork_cleanup_signal; ..... ..... return p; } static struct task_struct *dup_task_struct(struct task_struct *orig) { struct task_struct *tsk; struct thread_info *ti; int err; tsk = alloc_task_struct(); ti = alloc_thread_info(tsk); err = arch_dup_task_struct(tsk, orig); which is ===> *tsk = *orig; setup_thread_stack(tsk, orig); } static int copy_mm(unsigned long clone_flags, struct task_struct * tsk) { struct mm_struct * mm, *oldmm; oldmm = current->mm; if (clone_flags & CLONE_VM) { atomic_inc(&oldmm->mm_users); mm = oldmm; goto good_mm; } mm = dup_mm(tsk); good_mm: tsk->mm = mm; tsk->active_mm = mm; return 0; } struct mm_struct *dup_mm(struct task_struct *tsk) { struct mm_struct *mm, *oldmm = current->mm; mm = allocate_mm(); memcpy(mm, oldmm, sizeof(*mm)); if (!mm_init(mm, tsk)) goto fail_nomem; err = dup_mmap(mm, oldmm); if (err) goto free_pt; return mm; } static struct mm_struct * mm_init(struct mm_struct * mm, struct task_struct *p) { if (likely(!mm_alloc_pgd(mm))) { return mm; } } static inline int mm_alloc_pgd(struct mm_struct * mm) { mm->pgd = pgd_alloc(mm); return 0; } Thanks and Regards, Prasad. -- To unsubscribe from this list: send an email with "unsubscribe kernelnewbies" to ecartis@xxxxxxxxxxxx Please read the FAQ at http://kernelnewbies.org/FAQ