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


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

     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)

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

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

     
  • 相关阅读:
    ES6获取页面所有页面标签名
    改变this对象的指向
    构造函数及原型
    全局对象this转为局部对象
    节点注意的问题
    Spark研究笔记17:设置 CVT
    Spark研究笔记15:资源 CVT
    Spark研究笔记13:Swing 组件类 CVT
    Spark研究笔记16:搜索 CVT
    Spark研究笔记19:插件体系开发 CVT
  • 原文地址:https://www.cnblogs.com/cdwodm/p/2942405.html
Copyright © 2020-2023  润新知