Hello World 4

来源:互联网 发布:log4j.xml配置显示sql 编辑:程序博客网 时间:2024/06/03 03:35

本文装载自:http://www.cnblogs.com/xuqiang/archive/2010/03/29/1953689.html

微笑

开始”映射“之旅,在上面的讲解中经常提及到“”映射“的概念,那到底什么是映射?

一个线性区可以和磁盘上的某个文件关联或者是某个文件的一部分来关联,这也就意味着内核把线性区的访问页内某个字节的访问转换成对于文件的中相应页面的访问,这种技术称之为“内存映射”。

使用strace hello得到:

...

open("/usr/lib/locale/en_AU.UTF-8/LC_TIME", O_RDONLY) = -1 ENOENT (No such file or directory)

open("/usr/lib/locale/en_AU.utf8/LC_TIME", O_RDONLY) = 3

fstat64(3, {st_mode=S_IFREG|0644, st_size=2454, ...}) = 0

mmap2(NULL, 2454, PROT_READ, MAP_PRIVATE, 3, 0) = 0xb80bf000

...
在hello程序加载时,linux kernel使用mmap来实现文件的映射。在说明文件映射的原理之前,首先来看映射所需要的数据结构:下面的图片摘自《深入理解linux内存管理》,同时参见http://blog.chinaunix.net/u3/99507/showart_2121121.html

 

看linux内核很容易被struct address_space 这个结构迷惑,它是代表某个地址空间吗?实际上不是的,它是用于管理文件(struct inode)映射到内存的页面(struct page)的;与之对应,address_space_operations 就是用来操作该文件映射到内存的页面,比如把内存中的修改写回文件、从文件中读入数据到页面缓冲等。

也就是说address_space结构与文件的对应:一个具体的文件在打开后,内核会在内存中为之建立一个struct inode结构,其中的i_mapping域指向一个address_space结构。这样,一个文件就对应一个address_space结构,一个 address_space与一个偏移量能够确定一个page cache 或swap cache中的一个页面。因此,当要寻址某个数据时,很容易根据给定的文件及数据在文件内的偏移量而找到相应的页面。

 

task_struct--->
                        vm_area_struct--->
                                                           file--->
                                                                       address_space--->
                                                                                                        pages(该文件实际指向的内存页面)
当一个进程需要创建一个内存映射时,发出系统调用mmap,mmap系统调用返回的是第一个单元位置的线性单元。mmap函数的主要操作主要是
初始化进程task_struct结构的vm_file字段,具体就是:调用文件的file结构初始化vm_file字段,调用generic_file_mmap函数。
generic_file_mmap函数执行下面的步骤:
使用generic_file_vm_ops表地址初始化vm_area_struct结构的vm_ops字段,其实在这个表中除了nopage和populate方法之外,其他的方法全是空的。nopage方法是由函数filemap_nopage来实现,populate是有filemap_populate来实现。
其实真个的“映射”的工作已经完成,在这个时候,hello文件其实还没有被加载到内存中,当试图访问没有在内存中页面时,发生缺页中断,然后调用上面再vm_ops字段中的nopage方法,来将实际的文件读到内存中。
总结上面的过程的话:我将“映射”大致分为两个过称,首先仅仅是标记了在进程的某个虚拟内存地址上”对应“了磁盘上的某个文件(在这个情景中是hello可执行程序),然后内核开始执行其他的事情,当这个进程试图开始对刚才标记的页面来寻址时,产生缺页异常,然后才是实际的内存(ram)的分配,并将映射的文件加载到内存中,注意的是判断一个页框是否是属于某个进程需要看看对应的页表是否设置了,在上面的缺页处理中,在函数vm_ops->nopage()函数中调用do_no_page函数,在do_no_page函数中实际才设置页表项。
由于csdn不支持图片上传,完整版:http://cid-f41b44b9285d0b86.spaces.live.com/blog/cns!F41B44B9285D0B86!307.entry
原创粉丝点击