执行程序时内存管理的情景(一点自己的心得)
时间:2008-01-16 13:09:58 来源: 作者:
|
do_execve ->open_exec->dentry_open .... f->f_dentry = dentry; .... f->f_op = fops_get(inode->i_fop); .... 设置f->f_dentry和f->f_op,我们考察执行ext2的情景,因此f_op将是ext2_file_operations ->search_binary_handler->load_elf_binary->elf_map->do_mmap->do_mmap_pgoff .... vma->vm_file = file; get_file(file); error = file->f_op->mmap(file, vma); .... 设置vm_file,执行f_op->mmap,在ext2_file_operations中的mmap是generic_file_mmap,在generic_file_mmap中主要是设置vma->vm_ops = ops,绝大多数情况下ops是file_private_mmap static struct vm_operations_struct file_private_mmap = { nopage: filemap_nopage, }; 执行do_mmap时,如果是代码段,一般只允许读和执行,如果是数据段,一般允许读和写,但是vma->vm_page_prot中只设置有可读和可执行位(没有深入研究) sys_execve做完映射后就退出了.当调度到该进程时并执行代码时,立即产生page fault,依次do_page_fault->handle_mm_fault->handle_pte_fault->do_no_page ... new_page = vma->vm_ops->nopage(vma, address & PAGE_MASK, (vma->vm_flags & VM_SHARED)?0:write_access); ... 从前面知道,此处将调用filemap_nopage(基本所有这类的情景都执行这个函数) filemap_nopage->page_cache_read ..... page = page_cache_alloc(); if (!page) return -ENOMEM; if (!add_to_page_cache_unique(page, mapping, offset, hash)) { int error = mapping->a_ops->readpage(file, page); page_cache_release(page); return error; } .... 此处分配一空闲页,然后读入该页,由于是ext2,应此此处的a_ops是 struct address_space_operations ext2_aops = { readpage: ext2_readpage, writepage: ext2_writepage, sync_page: block_sync_page, prepare_write: ext2_prepare_write, commit_write: generic_commit_write, bmap: ext2_bmap }; 因此将调用ext2_readpage读入。返回do_no_page,根据vma->vm_page_prot设置该页只允许读和执行,一路返回.现在代码可执行了. 如果代码要写数据段,同样将发生以上情景。现在数据段也在内存中了。但是由于要写该数据页,而页只允许读,因此再次发生page fault,依次do_page_fault->handle_mm_fault->handle_pte_fault,由于此时页已经在内存中,将执行do_wp_page,也就是COW,并设置该页允许写,并释放原页.这样就保证了原页(该页也是该文件读写缓冲)没有被更改. 如果可用物理页发生短缺并且kswapd执行swap_out时选中该进程,进而执行try_to_swap_out, ... if (PageSwapCache(page)) { entry.val = page->index; if (pte_dirty(pte)) set_page_dirty(page); set_swap_pte: swap_duplicate(entry); set_pte(page_table, swp_entry_to_pte(entry)); drop_pte: UnlockPage(page); mm->rss--; deactivate_page(page); page_cache_release(page); out_failed: return 0; } flush_cache_page(vma, address); if (!pte_dirty(pte)) goto drop_pte; /*代码段将goto drop_pte,以后发生page fault时再执行前面的情景*/ if (page->mapping) { set_page_dirty(page); goto drop_pte; } /*数据段将执行下面的swap out操作,这样修改过的数据页将被换到交换分区*/ entry = get_swap_page(); if (!entry.val) goto out_unlock_restore; /* No swap space left */ /* Add it to the swap cache and mark it dirty */ add_to_swap_cache(page, entry); set_page_dirty(page); goto set_swap_pte; ...... albcamus 回复于:2006-03-30 13:30:48 比ULK清晰多了, 虽然ULK深入细致些:D |
原文链接:http://linux.chinaunix.net/bbs/viewthread.php?tid=726819 转载请注明作者名及原文出处 |
上一篇: 何把内核中的信息打印到文件










文章评论
共有 位网友发表了评论 查看完整内容