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 * 0x4000000;
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 }
1 /*
2 * Well, here is one of the most complicated functions in mm. It
3 * copies a range of linerar addresses by copying only the pages.
4 * Let's hope this is bug-free, 'cause this one I don't want to debug :-)
5 *
6 * Note! We don't copy just any chunks of memory - addresses have to
7 * be divisible by 4Mb (one page-directory entry), as this makes the
8 * function easier. It's used only by fork anyway.
9 *
10 * NOTE 2!! When from==0 we are copying kernel space for the first
11 * fork(). Then we DONT want to copy a full page-directory entry, as
12 * that would lead to some serious memory waste - we just copy the
13 * first 160 pages - 640kB. Even that is more than we need, but it
14 * doesn't take any more memory - we don't copy-on-write in the low
15 * 1 Mb-range, so the pages can be shared with the kernel. Thus the
16 * special case for nr=xxxx.
17 */
18 int copy_page_tables(unsigned long from,unsigned long to,long size) /* from和to都是线性地址,数据段基址*/
19 {
20 unsigned long * from_page_table;
21 unsigned long * to_page_table;
22 unsigned long this_page;
23 unsigned long * from_dir, * to_dir;
24 unsigned long nr;
25
26 if ((from&0x3fffff) || (to&0x3fffff))
27 panic("copy_page_tables called with wrong alignment");
28 from_dir = (unsigned long *) ((from>>20) & 0xffc); /* _pg_dir = 0 */ /* from_dir对应的页目录项物理地址,这样计算过来的话 */
29 to_dir = (unsigned long *) ((to>>20) & 0xffc); /* to_dir也对应的是物理地址 */
30 size = ((unsigned) (size+0x3fffff)) >> 22;
31 for( ; size-->0 ; from_dir++,to_dir++) {
32 if (1 & *to_dir)
33 panic("copy_page_tables: already exist");
34 if (!(1 & *from_dir))
35 continue;
36 from_page_table = (unsigned long *) (0xfffff000 & *from_dir);
37 if (!(to_page_table = (unsigned long *) get_free_page())) /* get_free_page 返回的是物理地址,后来经过处理赋值给了 *to_dir ,所以页目录表里面存的是物理地址*/
38 return -1; /* Out of memory, see freeing */
39 *to_dir = ((unsigned long) to_page_table) | 7;
40 nr = (from==0)?0xA0:1024;
41 for ( ; nr-- > 0 ; from_page_table++,to_page_table++) { /* 拷贝页表中的项,是物理地址*/
42 this_page = *from_page_table;
43 if (!(1 & this_page))
44 continue;
45 this_page &= ~2;
46 *to_page_table = this_page;
47 if (this_page > LOW_MEM) {
48 *from_page_table = this_page;
49 this_page -= LOW_MEM;
50 this_page >>= 12;
51 mem_map[this_page]++;
52 }
53 }
54 }
55 invalidate();
56 return 0;
57 }
/* from_dir对应的页目录项物理地址 */