confused with child page table handling in fork().

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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, &regs, 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


[Index of Archives]     [Newbies FAQ]     [Linux Kernel Mentors]     [Linux Kernel Development]     [IETF Annouce]     [Git]     [Networking]     [Security]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux SCSI]     [Linux ACPI]

  Powered by Linux