歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux綜合 >> Linux資訊 >> Linux文化

Linux系統執行程序時內存管理的情景


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;

......

Copyright © Linux教程網 All Rights Reserved