linux0.12 复制页目录项和页表

系统 1895 0

复制页目录项和页表的函数是

      
         1
      
      
        int
      
       copy_page_tables(unsigned 
      
        long
      
      
        from
      
      ,unsigned 
      
        long
      
       to,
      
        long
      
      
         size)


      
      
         2
      
      
        {


      
      
         3
      
           unsigned 
      
        long
      
       *
      
         from_page_table;


      
      
         4
      
           unsigned 
      
        long
      
       *
      
         to_page_table;


      
      
         5
      
           unsigned 
      
        long
      
      
         this_page;


      
      
         6
      
           unsigned 
      
        long
      
       * from_dir, *
      
         to_dir;


      
      
         7
      
           unsigned 
      
        long
      
      
         new_page;


      
      
         8
      
           unsigned 
      
        long
      
      
         nr;


      
      
         9
      
      
        10
      
      
        if
      
       ((
      
        from
      
      &
      
        0x3fffff
      
      ) || (to&
      
        0x3fffff
      
      
        ))


      
      
        11
      
               panic(
      
        "
      
      
        copy_page_tables called with wrong alignment
      
      
        "
      
      
        );


      
      
        12
      
           from_dir = (unsigned 
      
        long
      
       *) ((
      
        from
      
      >>
      
        20
      
      ) & 
      
        0xffc
      
      ); 
      
        /*
      
      
         _pg_dir = 0 
      
      
        */
      
      
        13
      
           to_dir = (unsigned 
      
        long
      
       *) ((to>>
      
        20
      
      ) & 
      
        0xffc
      
      
        );


      
      
        14
      
           size = ((unsigned) (size+
      
        0x3fffff
      
      )) >> 
      
        22
      
      
        ;


      
      
        15
      
      
        for
      
      ( ; size-->
      
        0
      
       ; from_dir++,to_dir++
      
        ) {


      
      
        16
      
      
        if
      
       (
      
        1
      
       & *
      
        to_dir)


      
      
        17
      
                   panic(
      
        "
      
      
        copy_page_tables: already exist
      
      
        "
      
      
        );


      
      
        18
      
      
        if
      
       (!(
      
        1
      
       & *
      
        from_dir))


      
      
        19
      
      
        continue
      
      
        ;


      
      
        20
      
               from_page_table = (unsigned 
      
        long
      
       *) (
      
        0xfffff000
      
       & *
      
        from_dir);


      
      
        21
      
      
        if
      
       (!(to_page_table = (unsigned 
      
        long
      
       *
      
        ) get_free_page()))


      
      
        22
      
      
        return
      
       -
      
        1
      
      ;    
      
        /*
      
      
         Out of memory, see freeing 
      
      
        */
      
      
        23
      
               *to_dir = ((unsigned 
      
        long
      
      ) to_page_table) | 
      
        7
      
      
        ;


      
      
        24
      
               nr = (
      
        from
      
      ==
      
        0
      
      )?
      
        0xA0
      
      :
      
        1024
      
      
        ;


      
      
        25
      
      
        for
      
       ( ; nr-- > 
      
        0
      
       ; from_page_table++,to_page_table++
      
        ) {


      
      
        26
      
                   this_page = *
      
        from_page_table;


      
      
        27
      
      
        if
      
       (!
      
        this_page)


      
      
        28
      
      
        continue
      
      
        ;


      
      
        29
      
      
        if
      
       (!(
      
        1
      
       &
      
         this_page)) {


      
      
        30
      
      
        if
      
       (!(new_page =
      
         get_free_page()))


      
      
        31
      
      
        return
      
       -
      
        1
      
      
        ;


      
      
        32
      
                       read_swap_page(this_page>>
      
        1
      
      , (
      
        char
      
       *
      
        ) new_page);


      
      
        33
      
                       *to_page_table =
      
         this_page;


      
      
        34
      
                       *from_page_table = new_page | (PAGE_DIRTY | 
      
        7
      
      
        );


      
      
        35
      
      
        continue
      
      
        ;


      
      
        36
      
      
                    }


      
      
        37
      
                   this_page &= ~
      
        2
      
      
        ;


      
      
        38
      
                   *to_page_table =
      
         this_page;


      
      
        39
      
      
        if
      
       (this_page >
      
         LOW_MEM) {


      
      
        40
      
                       *from_page_table =
      
         this_page;


      
      
        41
      
                       this_page -=
      
         LOW_MEM;


      
      
        42
      
                       this_page >>= 
      
        12
      
      
        ;


      
      
        43
      
                       mem_map[this_page]++
      
        ;


      
      
        44
      
      
                    }


      
      
        45
      
      
                }


      
      
        46
      
      
            }


      
      
        47
      
      
            invalidate();


      
      
        48
      
      
        return
      
      
        0
      
      
        ;


      
      
        49
      
       }
    

调用这个函数是在

      
         1
      
      
        int
      
       copy_mem(
      
        int
      
       nr,
      
        struct
      
       task_struct *
      
         p)


      
      
         2
      
      
        {


      
      
         3
      
           unsigned 
      
        long
      
      
         old_data_base,new_data_base,data_limit;


      
      
         4
      
           unsigned 
      
        long
      
      
         old_code_base,new_code_base,code_limit;


      
      
         5
      
      
         6
      
           code_limit=get_limit(
      
        0x0f
      
      
        );


      
      
         7
      
           data_limit=get_limit(
      
        0x17
      
      
        );


      
      
         8
      
           old_code_base = get_base(current->ldt[
      
        1
      
      
        ]);


      
      
         9
      
           old_data_base = get_base(current->ldt[
      
        2
      
      
        ]);


      
      
        10
      
      
        if
      
       (old_data_base !=
      
         old_code_base)


      
      
        11
      
               panic(
      
        "
      
      
        We don't support separate I&D
      
      
        "
      
      
        );


      
      
        12
      
      
        if
      
       (data_limit <
      
         code_limit)


      
      
        13
      
               panic(
      
        "
      
      
        Bad data_limit
      
      
        "
      
      
        );


      
      
        14
      
           new_data_base = new_code_base = nr *
      
         TASK_SIZE;


      
      
        15
      
           p->start_code =
      
         new_code_base;


      
      
        16
      
           set_base(p->ldt[
      
        1
      
      
        ],new_code_base);


      
      
        17
      
           set_base(p->ldt[
      
        2
      
      
        ],new_data_base);


      
      
        18
      
      
        if
      
      
         (copy_page_tables(old_data_base,new_data_base,data_limit)) {


      
      
        19
      
      
                free_page_tables(new_data_base,data_limit);


      
      
        20
      
      
        return
      
       -
      
        ENOMEM;


      
      
        21
      
      
            }


      
      
        22
      
      
        return
      
      
        0
      
      
        ;


      
      
        23
      
       }
    

其中 old_data_base 是父进程ldt的基地址, new_data_base 是子进程ldt的基地址, data_limit 是ldt段的长度

copy_page_tables 的作用是复制由 old_data_base和 data_limit所决定内存空间所占用的页目录项和页表(个数由 data_limit决定 ),其实现是由线性地址找到页目录项,再找到页表,复制父进程页表的每一项到子进程的页表中(申请的)

为什么说是页目录项,因为页目录只有一个,各个进程共用统一个页目录,但是每个进程的页目录项是不同的,详见fork.c

      
         1
      
      
        int
      
       copy_process(
      
        int
      
       nr,
      
        long
      
       ebp,
      
        long
      
       edi,
      
        long
      
       esi,
      
        long
      
       gs,
      
        long
      
      
         none,


      
      
         2
      
      
        long
      
       ebx,
      
        long
      
       ecx,
      
        long
      
       edx, 
      
        long
      
      
         orig_eax, 


      
      
         3
      
      
        long
      
       fs,
      
        long
      
       es,
      
        long
      
      
         ds,


      
      
         4
      
      
        long
      
       eip,
      
        long
      
       cs,
      
        long
      
       eflags,
      
        long
      
       esp,
      
        long
      
      
         ss)


      
      
         5
      
      
        {


      
      
         6
      
      
        struct
      
       task_struct *
      
        p;


      
      
         7
      
      
        int
      
      
         i;


      
      
         8
      
      
        struct
      
       file *
      
        f;


      
      
         9
      
      
        10
      
           p = (
      
        struct
      
       task_struct *
      
        ) get_free_page();


      
      
        11
      
      
        if
      
       (!
      
        p)


      
      
        12
      
      
        return
      
       -
      
        EAGAIN;


      
      
        13
      
           task[nr] =
      
         p;


      
      
        14
      
           *p = *current;    
      
        /*
      
      
         NOTE! this doesn't copy the supervisor stack 
      
      
        */
      
      
        15
      
           p->state =
      
         TASK_UNINTERRUPTIBLE;


      
      
        16
      
           p->pid =
      
         last_pid;


      
      
        17
      
           p->counter = p->
      
        priority;


      
      
        18
      
           p->signal = 
      
        0
      
      
        ;


      
      
        19
      
           p->alarm = 
      
        0
      
      
        ;


      
      
        20
      
           p->leader = 
      
        0
      
      ;        
      
        /*
      
      
         process leadership doesn't inherit 
      
      
        */
      
      
        21
      
           p->utime = p->stime = 
      
        0
      
      
        ;


      
      
        22
      
           p->cutime = p->cstime = 
      
        0
      
      
        ;


      
      
        23
      
           p->start_time =
      
         jiffies;


      
      
        24
      
           p->tss.back_link = 
      
        0
      
      
        ;


      
      
        25
      
           p->tss.esp0 = PAGE_SIZE + (
      
        long
      
      
        ) p;


      
      
        26
      
           p->tss.ss0 = 
      
        0x10
      
      
        ;


      
      
        27
      
           p->tss.eip =
      
         eip;


      
      
        28
      
           p->tss.eflags =
      
         eflags;


      
      
        29
      
           p->tss.eax = 
      
        0
      
      
        ;


      
      
        30
      
           p->tss.ecx =
      
         ecx;


      
      
        31
      
           p->tss.edx =
      
         edx;


      
      
        32
      
           p->tss.ebx =
      
         ebx;


      
      
        33
      
           p->tss.esp =
      
         esp;


      
      
        34
      
           p->tss.ebp =
      
         ebp;


      
      
        35
      
           p->tss.esi =
      
         esi;


      
      
        36
      
           p->tss.edi =
      
         edi;


      
      
        37
      
           p->tss.es = es & 
      
        0xffff
      
      
        ;


      
      
        38
      
           p->tss.cs = cs & 
      
        0xffff
      
      
        ;


      
      
        39
      
           p->tss.ss = ss & 
      
        0xffff
      
      
        ;


      
      
        40
      
           p->tss.ds = ds & 
      
        0xffff
      
      
        ;


      
      
        41
      
           p->tss.fs = fs & 
      
        0xffff
      
      
        ;


      
      
        42
      
           p->tss.gs = gs & 
      
        0xffff
      
      
        ;


      
      
        43
      
           p->tss.ldt =
      
         _LDT(nr);


      
      
        44
      
           p->tss.trace_bitmap = 
      
        0x80000000
      
      
        ;


      
      
        45
      
      
        if
      
       (last_task_used_math ==
      
         current)


      
      
        46
      
               __asm__(
      
        "
      
      
        clts ; fnsave %0 ; frstor %0
      
      
        "
      
      ::
      
        "
      
      
        m
      
      
        "
      
       (p->
      
        tss.i387));


      
      
        47
      
      
        if
      
      
         (copy_mem(nr,p)) {


      
      
        48
      
               task[nr] =
      
         NULL;


      
      
        49
      
               free_page((
      
        long
      
      
        ) p);


      
      
        50
      
      
        return
      
       -
      
        EAGAIN;


      
      
        51
      
      
            }


      
      
        52
      
      
        for
      
       (i=
      
        0
      
      ; i<NR_OPEN;i++
      
        )


      
      
        53
      
      
        if
      
       (f=p->
      
        filp[i])


      
      
        54
      
                   f->f_count++
      
        ;


      
      
        55
      
      
        if
      
       (current->
      
        pwd)


      
      
        56
      
               current->pwd->i_count++
      
        ;


      
      
        57
      
      
        if
      
       (current->
      
        root)


      
      
        58
      
               current->root->i_count++
      
        ;


      
      
        59
      
      
        if
      
       (current->
      
        executable)


      
      
        60
      
               current->executable->i_count++
      
        ;


      
      
        61
      
      
        if
      
       (current->
      
        library)


      
      
        62
      
               current->library->i_count++
      
        ;


      
      
        63
      
           set_tss_desc(gdt+(nr<<
      
        1
      
      )+FIRST_TSS_ENTRY,&(p->
      
        tss));


      
      
        64
      
           set_ldt_desc(gdt+(nr<<
      
        1
      
      )+FIRST_LDT_ENTRY,&(p->
      
        ldt));


      
      
        65
      
           p->p_pptr =
      
         current;


      
      
        66
      
           p->p_cptr = 
      
        0
      
      
        ;


      
      
        67
      
           p->p_ysptr = 
      
        0
      
      
        ;


      
      
        68
      
           p->p_osptr = current->
      
        p_cptr;


      
      
        69
      
      
        if
      
       (p->
      
        p_osptr)


      
      
        70
      
               p->p_osptr->p_ysptr =
      
         p;


      
      
        71
      
           current->p_cptr =
      
         p;


      
      
        72
      
           p->state = TASK_RUNNING;    
      
        /*
      
      
         do this last, just in case 
      
      
        */
      
      
        73
      
      
        return
      
      
         last_pid;


      
      
        74
      
       }
    

其中复制父进程TSS中的PDBR(CR3)

另外注意哪些地址是物理地址,哪些地址是线性地址。

页目录项中的地址和页表项中的地址都是物理地址

    
       
    
  

linux0.12 复制页目录项和页表


更多文章、技术交流、商务合作、联系博主

微信扫码或搜索:z360901061

微信扫一扫加我为好友

QQ号联系: 360901061

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描下面二维码支持博主2元、5元、10元、20元等您想捐的金额吧,狠狠点击下面给点支持吧,站长非常感激您!手机微信长按不能支付解决办法:请将微信支付二维码保存到相册,切换到微信,然后点击微信右上角扫一扫功能,选择支付二维码完成支付。

【本文对您有帮助就好】

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描上面二维码支持博主2元、5元、10元、自定义金额等您想捐的金额吧,站长会非常 感谢您的哦!!!

发表我的评论
最新评论 总共0条评论