Linux Memory Management Source Analysis __linux

Source: Internet
Author: User
Tags error code goto

Memory Management Source Analysis Author: Changuo in order to deep memory management research, I decided to study its source code, but the version is too much, so choose 0.12 Kernel source code, because its short, but no dirty taste. The memory management code is located in the MM folder. Contains Makefile, MEMORY.C, page.s swap.c four files. Makefile is used for file compilation, primarily for managing source files. MEMORY.C for memory paging management. Implement dynamic allocation and recycling of memory pages in the main memory area. The SWAP.C program mainly realizes the virtual memory Exchange function. PAGE.S includes exception interrupt handler, which is mainly divided into two kinds of cases: one is because of page fault caused by the abnormal interrupt, through the call Do_no_page (error_code,address) to deal with; two is: page exception caused by page write protection, call page write protection processing function do _wp_page (error_code,address) for processing. The error code Error_code is automatically generated by the CPU and pressed into the stack, and the linear address of the access is obtained from the register CR2 when an exception occurs. CR2 a linear address that is specifically used to store page errors. The two functions, Get_free_page () and Free_page (), are designed to manage the use and idleness of physical memory in main memory, regardless of the linear address of each thread. void Free_page (unsigned long addr)//memory.c {if (addr < low_mem) return; if (addr >=. High_memory) Panic ("trying To free nonexistent page "); Addr-= Low_mem; Addr >>= 12; if (mem_map[addr]--) return; mem_map[addr]=0; Panic ("Trying to free free page"); } unsigned long get_free_page (void) {Register unsigned long __res asm ("Ax");//SWAP.C repeat: __asm__ ("STD; Repne; scasb/n/t "" Jne 1f/n/t "Movb $1,1 (%%edi)/n/t" "Sall $12,%%ecx/n/t" "Addl%2,%%ecx/n/t "" "Movl%%ecx,%%edx/n/t" "Movl $1024,%%ecx/n/t" "Leal 4092 (%%edx),%%edi/n/t" "REP; stosl/n/t "" "Movl%%edx,%%eax/n" "1:": "=a" (__res): "0" (0), "I" (Low_mem), "C" (paging_pages), "D" (mem_map+paging_pages-1 ): "Di", "CX", "DX"); if (__res >= high_memory) goto repeat; if (!__res && swap_out ()) goto repeat; return __res; The two functions, Free_page_tables () and Copy_page_tables (), release or copy the block of physical memory pages that correspond to the specified linear address and length (the number of page tables) in the physical memory block that corresponds to a page table. Not only modifies the contents of the page directories and page tables that manage the linear addresses, but also releases or consumes the physical memory pages that correspond to every page table entry in the table. /* This function frees a continuos blocks of page tables, as needed * by ' exit () '. As does Copy_page_tables (), this is handles only 4Mb blocks. */int Free_page_tables (unsigned long from,unsigned long size)//memory.c {unsigned long *pg_table; unsigned long * dir , nr; if (from & 0x3fffff) Panic ("Free_page_tables called with wrong alignment"); if (!from) panic ("trying to free up swapper memory spaces"); Size = (size + 0x3fffff) >> 22; Dir = (unsigned long *) ((from>>20) & 0XFFC); /* _pg_DIR = 0 */for (; size-->0; dir++) {if (!) ( 1 & *dir)) continue; Pg_table = (unsigned long *) (0xfffff000 & *dir); for (nr=0 nr<1024; nr++) {if (*pg_table) {if (1 & *pg_table) free_page (0xfffff000 & *pg_table); else SWAP_ Free (*pg_table >> 1); *pg_table = 0; } pg_table++; } free_page (0xfffff000 & *dir); *dir = 0; } invalidate (); return 0; } * * 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 I-I don ' t want to debug:-) * * note! We don ' t copy just any chunks of memory-addresses have to * is divisible by 4Mb (one page-directory entry), as s the * function easier. It ' s used only by fork anyway. * * Note 2!! When from==0 we are copying kernel spaces for the "the" I fork (). Then we DONT want to copy a full page-directory entry, as * that would leads to some serious memory waste-we just copy th E * 160 pages-640kb. Even that's more than we need, but it * doesn ' t take any more memory-we don ' t copy-on-write in the low * 1 mb-range The pages can be shared with the kernel. Thus the * special case for nr=xxxx. */int Copy_page_tables (unsigned long from,unsigned long to,long size) {unsigned long * from_page_table; unsigned long * to_page_table; unsigned long this_page; unsigned long * from_dir, * TO_DIR; unsigned long new_page; unsigned long nr; if ((FROM&AMP;0X3FFFFF) | | (TO&AMP;0X3FFFFF)) Panic ("Copy_page_tables called with wrong alignment"); From_dir = (unsigned long *) ((from>>20) & 0XFFC); /* _pg_dir = 0/To_dir = (unsigned long *) ((to>>20) & 0XFFC); Size = ((unsigned) (SIZE+0X3FFFFF)) >> 22; for (; size-->0; from_dir++,to_dir++) {if (1 & *to_dir) Panic ("copy_page_tables:already exist"); if (!) ( 1 & *from_dir)) continue; From_page_table = (unsigned long *) (0xfffff000 & *from_dir); if (!) ( To_page_table = (unsigned long *) get_free_page ()) Return-1; /* Out of memory, freeing * * *to_dir = ((unsigned long) to_page_table) | 7; NR = (from==0) 0xa0:1024; for (; nr--> 0; from_page_table++,to_page_table++) {this_page = *from_page_table; if (!this_page) continue; if (!) ( 1 & this_page)) {if (!) ( New_page = Get_free_page ())) return-1; Read_swap_page (this_page>>1, (char *) new_page); *to_page_table = This_page; *from_page_table = New_page | (Page_dirty | 7); Continue } this_page &= ~2; *to_page_table = This_page; if (This_page > Low_mem) {*from_page_table = This_page; this_page-= Low_mem; This_page >>= e]++; }} invalidate (); return 0; Put_page () is used to map a specified physical memory page to a specified linear address. It first determines the validity of the specified memory page address, and should issue a warning outside of the 1MB and the system's highest-end memory address. Then compute the directory entry for the specified linear address in the page directory, and if the directory entry is valid (P=1), take the address of its corresponding page table, otherwise request a free page to use for the page table and set the properties of the corresponding page table entry in the page table. Finally, the specified physical memory page address is still returned. * * This function puts a page in memory at the wanted address. * It returns the physical address of the page gotten, 0 if * out of memory (either when trying to access page-table or * page.) */static unsigned long put_page (unsigned long page,unsigned long address) {unsigned long tmp, *page_table; * NOTE!!! T His uses the fact that _pg_dir=0/if (Page < Low_mem | | page >= high_memory) printk ("Trying to put page%p at%p/n ", page,address); if (mem_map[(PAGE-LOW_MEM) >>12]!= 1) printk ("Mem_map disagrees with%p at%p/n", page,address); Page_table = (unsigned long *) ((address>>20) & 0XFFC); if ((*page_table) &1) page_table = (unsigned long *) (0xfffff000 & *page_table); else {if (!) ( Tmp=get_free_page ()) return 0; *page_table = tmp | 7; Page_table = (unsigned long *) tmp; } page_table[(ADDRESS&GT;&GT;12) & 0x3ff] = page | 7; /* No need for invalidate * * return page; Do_wp_page () is a page write protection handler that is invoked during a page exception break. It first determines whether the address is in the process's code area, if it terminates the program, and then executes the copy-page action at write-time (copy on Write) * * * Routine handles present pages, as users try to write * to a shared page. It is doing by copying the "page to a" new address * and decrementing the shared-Page counter for the old page. * If it ' s in code spaces we exit with a segment error. */void Do_wp_page (unsigned long error_code,unsigned long address) {if (Address < task_size) PRINTK ("/n/rbad! KERNEL MEMORY wp-err!/n/r "); if (Address-current->start_code > Task_size) {printk ("Bad things happen:page Error in do_wp_page/n/r"); Do_exit ( SIGSEGV); #if 0/* We cannot do this yet:the Estdio the library writes to the code space * * Stupid, stupid. I really want the LIBC.A from GNU/if (Code_space (address)) Do_exit (SIGSEGV); #endif un_wp_page (unsigned long *) ((address>>10) & 0XFFC) + (0xfffff000 & * (unsigned long *) (ADDRESS&G T;&GT;20))) (&AMP;0XFFC))); Do_no_page () is a page-fault handler that is called during an exception interrupt. void Do_no_page (unsigned long error_code,unsigned long address) {int nr[4]; unsigned long tmp; unsigned long page; int bl Ock,i; struct M_inode * inode; if (Address < task_size) PRINTK ("/n/rbad!! KERNEL PAGE missing/n/r "); if (Address-current->start_code > Task_size){PRINTK ("Bad things happen:nonexistent page error in do_no_page/n/r"); Do_exit (SIGSEGV);} page = * (unsigned long *) ((address >>) & 0XFFC); if (page & 1) {page &= 0xfffff000 page = = (address >>) & 0XFFC; tmp = * (unsigned long *) page; if ( TMP &&! (1 & TMP)) {swap_in (unsigned long *) page); Address &= 0xfffff000; TMP = address-current->start_code; if (tmp >= library_offset) {inode = current->library; block = 1 + (tmp-library_offset)/block_size;} else if (tm P < current->end_data) {inode = current->executable; block = 1 + tmp/block_size;} else {inode = NULL; = 0; } if (!inode) {get_empty_page (address), return,} if (Share_page (inode,tmp)) return; if (!) ( page = Get_free_page ()) oom (); /* Remember that 1 the ' used ' for header/for (i=0; i<4; block++,i++) Nr[i] = Bmap (Inode,block); Bread_page (PAGE,INODE-&GT;I_DEV,NR); i = tmp + 4096-current->end_data; if (i>4095) i = 0; TMP = page + 4096; while (i--> 0) {tmp--; * (char *) tmp = 0;} if (Put_page (page,address)) return; Free_page (page); Oom (); Get_empty_page (0) also takes a page of free physical memory and maps to the specified linear address. The Get_free_page () and Put_page () functions are used primarily to implement this function. void Get_empty_page (unsigned long address) {unsigned long tmp; if (!) ( Tmp=get_free_page ()) | | !put_page (tmp,address)) {free_page (TMP);/* 0 is ok-ignored */Oom ();}} The above list only a few important functions, for the detailed analysis of the source code can see Dr. Zhao's book, and then carefully analysis is estimated to be a book, hehe. This log is the most irresponsible one, did not add a comment on each line, I am very sorry, but I this weeks is exhausted, not too much time to study the kernel, can not give you good analysis results, once again apologize.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.