我们要读写磁盘文件时,实质是对页高速缓存进行读写,所以无论读写,都会首先检查页高速缓存有没有这个文件对应的页,如果有,就直接访问,如果没有,就引起缺页中断,给OS发信号,让它把文件放到高速缓存再进行读写,这个过程不经过内核空间到用户空间复制数据
OS中的页机制,对应到硬件中可不一定在主存中,也可以是高速缓存etc,但不会是磁盘,因为磁盘文件的地址和内存不一样,不是按照32位编址的,而是按照ext2 etc方式编址的,需要使用文件管理系统,在Linux中使用VFS和实际文件管理系统来管理文件,所以对于Linux,有两个方式使用系统资源:VMM,VFS,前者用来管理绝大部分的内存,后者用来管理所有的文件和部分特殊文件系统(eg:/shm是内存的一块区域)
page cache可以看作二者的桥梁,把磁盘文件放到高速缓存,就可以按照内存的使用方式使用磁盘的文件,使用完再释放或写回磁盘page cache中的页可能是下面的类型:
含有普通文件数据的页
含有目录的页
含有直接从块设备(跳过文件系统层)读出的数据的页
含有用户态进程数据的页,但页中的数据已经被交换到硬盘
属于他书文件系统文件的页
映射:一个线性区可以和磁盘文件系统的普通文件的某一部分或者块设备文件相关联,这就意味着内核把对区线性中页内某个字节的访问转换成对文件中相应字节的操作
TLB(Translation Lookaside Buffer)高速缓存用于加快线性地址的转换,当一个线性地址第一次被使用时,通过慢速访问RAM中的页表计算出相应的物理地址,同时,物理地址被存放在TLB表项(TLB entry),以便以后对同一个线性地址的引用可以快速得到转换
在初始化阶段,内核必须建立一个物理地址映射来指定哪些物理地址范围对内核可用,哪些不可用
swap(内存交换空间)的功能是应付物理内存不足的情况下所造成的内存扩展记录的功能,CPU所读取的数据都来自于内存,那当内存不足的时候,为了让后续的程序可以顺序运行,因此在内存中暂不使用的程序和数据就会被挪到swap中,此时内存就会空出来给需要执行的程序加载,由于swap是使用硬盘来暂时放置内存中的信息,所以用到swap时,主机硬盘灯就会开始闪个不同
Q:CPU只能对内存进行读写,但又是怎么读写硬盘的呢???A:把数据写入page cache,再经由。。。写入磁盘(包括swap) --《鸟哥》P10
内存本身没有计算能力,寻址之类的都是CPU的事,只是为了简便起见,我们通常画成从内存地址A跳到内存地址B
OS是软件的核心,CPU是执行的核心
前者给后者发指令我要干什么,CPU把他的指令变成现实
二者必须很好的匹配计算机才能很好的工作
Linux内核中与文件Cache操作相关的API有很多,按其使用方式可以分成两类:一类是以拷贝方式操作的相关接口, 如read/write/sendfile等,其中sendfile在2.6系列的内核中已经不再支持;另一类是以地址映射方式操作的相关接口,如mmap等。
第一种类型的API在不同文件的Cache之间或者Cache与应用程序所提供的用户空间buffer之间拷贝数据,其实现原理如图7所示。
第二种类型的API将Cache项映射到用户空间,使得应用程序可以像使用内存指针一样访问文件,Memory map访问Cache的方式在内核中是采用请求页面机制实现的,首先,应用程序调用mmap(),陷入到内核中后调用do_mmap_pgoff。该函数从应用程序的地址空间中分配一段区域作为映射的内存地址,并使用一个VMA(vm_area_struct)结构代表该区域,之后就返回到应用程。当应用程序访问mmap所返回的地址指针时(图中4),由于虚实映射尚未建立,会触发缺页中断。之后系统会调用缺页中断处理函数,在缺页中断处理函数中,内核通过相应区域的VMA结构判断出该区域属于文件映射,于是调用具体文件系统的接口读入相应的Page Cache项,并填写相应的虚实映射表。经过这些步骤之后,应用程序就可以正常访问相应的内存区域了。
mumap() //接触文件或设备对内存的映射,成功返回0,失败返回-1设errno int munmap(void *addr, size_t length); shm_unlink() //关闭进程打开的共享内存对象,成功返回0,失败返回-1 //Link with -lrt. int shm_unlink(const char *name);