linux 0.11 copy_page_tables()函數
來源:互聯網
上載者:User
/* 他通過只複製記憶體頁面來複製一定範圍內的線性地址的內容*/00150int copy_page_tables(unsigned long from,unsigned long to,long size)
00151 {
00152 unsigned long * from_page_table;
00153 unsigned long * to_page_table;
00154 unsigned long this_page;
00155 unsigned long * from_dir, * to_dir;
00156 unsigned long nr;
00157 //下面是判斷from 和to 是否在4M的邊界處
00158 if ((from&0x3fffff) || (to&0x3fffff))
00159 panic("copy_page_tables called with wrong alignment"); //賦給from_dir 頁目錄表的來源目錄起始號 (from>>20)&oxfffc =(from>>22)<<2
00160 from_dir = (unsigned long *) ((from>>20) & 0xffc); /* _pg_dir = 0 */ //賦給to_dir 頁目錄表的目的目錄起始號 (to>>20)&oxfffc =(to>>22)<<2
00161 to_dir = (unsigned long *) ((to>>20) & 0xffc); //賦給size要複製的目錄表項的個數
00162 size = ((unsigned) (size+0x3fffff)) >> 22; //下面兩個for迴圈是複製的開始。外層迴圈控制目錄表項的移動,內層 //迴圈控制二級頁表項移動,複製的內容是複製目錄項和頁表項
00163 for( ; size-->0 ; from_dir++,to_dir++) {
00164 if (1 & *to_dir)
00165 panic("copy_page_tables: already exist");
00166 if (!(1 & *from_dir))
00167 continue; //得到目錄項指向的二級頁表的起始地址 屏蔽後面的頁內索引
00168 from_page_table = (unsigned long *) (0xfffff000 & *from_dir); //利用get _free_page()申請一個記憶體頁
00169 if (!(to_page_table = (unsigned long *) get_free_page()))
00170 return -1; /* Out of memory, see freeing */ //設定目錄表項的標誌位賦給to_dir
00171 *to_dir = ((unsigned long) to_page_table) | 7;
//判斷from是否是從0 開始,若是,則只需複製0xA0個頁面 第一次調用fork()只複製核心空間 只需要160個頁面即為640kB;00172 nr = (from==0)?0xA0:1024; //複製每一個頁表項
00173 for ( ; nr-- > 0 ; from_page_table++,to_page_table++) {
00174 this_page = *from_page_table;
00175 if (!(1 & this_page))
00176 continue;
00177 this_page &= ~2;
00178 *to_page_table = this_page; //在fork()函數中會用到,就是把每個頁都設定成唯讀,父進程和 //子進程共用頁面,當進程想寫頁面時,產生缺頁中斷,利用寫時複 //制技術 //在核心就不需要進入執行
00179 if (this_page > LOW_MEM) {
00180 *from_page_table = this_page;
00181 this_page -= LOW_MEM;
00182 this_page >>= 12;
00183 mem_map[this_page]++;
00184 }
00185 }
00186 }
00187 invalidate(); //重新整理頁面快取
00188 return 0;
00189 }