/* *author : davidlin *date : 2014-11-22pm *Email : [email protected] or [email protected] *world : the city of SZ, in China *Ver : 000.000.001 *history : editor time  DO  *          1) LinPeng 2014-11-22 created this file! *          2) */ /* * well, here is one of the most complicated functions in mm. It * copies a range of linerar addresses by copying only the pages. * Let ' s hope this is bug-free, ' Cause this one i don ' t want to debug :-) * * note! we don ' t copy just any chunks of memory - addresses have to * be divisible by 4mb (one page-directory entry), as this makes the * function easier. it ' s used only by fork anyway. * * note 2!! when from==0 we are copying kernel space for the first * fork () . then we dont want to copy a full page-directory entry, as * that would lead to some serious Memory waste - we jusT copy the * first 160 pages - 640kb. even that is  MORE THAN WE NEED, BUT IT * DOESN ' T take any more memory - we don ' t copy-on-write in the low * 1 Mb-range, so the pages can be shared with the kernel. thus the * special case for nr=xxxx. *//* linus thought the following copy_page_tables () The function is one of the hardest parts of memory management. The * copy_page_tables () function is only called by the fork function call * copy just copy a page table, the page table is to manage the 4M address, so follow the 4M alignment * does not copy the physical page content, when a write-time copy will copy the page table to manage the physical page content * for processes 0 and 1, only copy the first 160 pages total 640Kb, for efficiency consideration * 0-1m as the kernel resident address area, Prohibit write overlay * parameter from,to is a 0-4g linear address, size is the byte unit */int copy_page_tables (Unsigned long from, Unsigned long to,long size) {unsigned long * from_page_table; //for managing source page tables &Nbsp; unsigned long * to_page_table; //for Management purposes page Table unsigned long this_page; //for saving page tables unsigned long * from_dir, * to_dir; //for managing source page catalog entries, destination page catalog entries unsigned long nr; //to save page table Entries if ((from&0x3fffff) | | (TO&0X3FFFFF)) //4m alignment detection, otherwise diepanic ("Copy_page_tables called with wrong alignment ");from_dir = (unsigned long *) (from>>20) & 0XFFC); /* _pg_dir = 0 */ // SOURCE Page Catalog Entry to_dir = (unsigned long *) ((to>>20)  & 0XFFC); //Destination Page Catalog item size = ((unsigned) (SIZE+0X3FFFFF)) >> 22; The number of //page table entries is the number of bytes divided by 4Mfor ( ; size-->0 ; from_dir++,to_dir+ +) { if (1 & *to_dir) //If the destination page directory entry is already in use, Diepanic ("Copy_page_tables: already exist ");if (! ( 1 & *from_dir) continue; //If the source page catalog entry is unused, skip, do not copy From_ Page_table = (unsigned long *) (0XFFFFF000 & *FROM_DIR);//source page table if (!) ( to_page_table = (unsigned long *) get_free_page ()) return -1; /* Out of memory, see freeing */ //take free physical pages for to_page_table assignment //If there is no free physical page,die *to_dir = (unsigned long) to_page_table) | 7; //Save the page table in the corresponding page directory entry, // 7 = Read write //think about the usual chmod 777 anyfile . nr = (from==0) 0xa0:1024; //If it is a 0 address, copy only 160 pages, otherwise copy 1024 pages //a page Catalog Table management 1024 page Catalog Items // One page Table management 1024 page table Items //one page table Item management has 4 K physical Address for ( ; nr-- > 0 ; from_page_table++,to_page_table++) { this_page = *from_page_table; // From the source page table, take the source page table entry if (! 1 & this_page)) // If the source page table entry is not being used, skip Continue; this_page &= ~2 ;   //Purpose Page Table entry read-write bit, //set to read-only *to_page_table = this_page; //to save the source page table entry in the destination page table entry if (THIS_PAGE > LOW_MEM) { //if it is the main memory area *from_page_table = this_page;//source Page TableItems are also set to read-only this_ page -= low_mem; //offset to relative main memory address this_page >>= 12 //Master Memory Management array index mem_map[this_page]++; //physical page reference count plus 1 } } } invalidate (); //Refresh Cache return 0; //return 0 = success}
This article is from the "mountain Ask the Boy" blog, please be sure to keep this source http://linpeng.blog.51cto.com/9779987/1596728
Linux0.11 Kernel Source Analysis series: Memory management Copy_page_tables () function analysis