交换分区
在Linux的安装过程中,用户将会被提示创建一个交换分区;
这是一个特殊的分区,其大小可以由用户根据系统内存需求和推荐进行决定;
一般来说一个分区中应当存在一个文件系统,而交换分区虽然被称为分区但其并不存在文件系统;
这块空间虽然在磁盘空间中,但实际上这块空间是交由内存管理所运用;
-
交换分区与文件系统的关系:
-
性:
它将直接由操作系统进行管理,用于存放被换出的内存页;
-
专用性:
由于交换分区是专门用于内存管理的,因此它与用于存储文件的常规文件系统分区有着本质的区别;
操作系统将直接在交换分区上操作内存页而不是文件或文件系统结构;
-
内存管理运用:
-
内存扩展
交换分区相当于是物理内存的一个拓展,提供了一种机制,允许系统使用硬盘空间来模拟额外的RAM从而增加了可用的内存资源;
-
内存释放
当系统的物理内存不足时操作系统可以将不活跃的内存页移交到交换分区并释放内存空间给其他更需要紧急处理的程序或是数据;
页与页框(页帧)
在内存管理中存在两个概念,分别为页与页框(页帧);
而页框(页帧)是物理内存当中的最小单位,其大小等于页的大小;
页通过页表映射至不同页框(页帧)中以实行内存管理;
-
页(Page)
-
页框/页帧(Page Frame)
页框/页帧的大小可以进行修改,但是其大小的修改只能重新选择操作系统的编译选项对操作系统进行重新编译才能生成;
虚拟内存中的页通过页表映射到物理内存中的页框;
页表记录了每个页对应的页框的信息;
其中页表中存储的数据被称为页表项;
页表项是页表中的基本单元,每一个页表项对应一个页,记录了该页在物理内存中的映射信息(页框/页帧);
-
-
页表查找
页号用于索引页表,并找到对应的页表项;
-
-
内存访问
当需要访问一个被交换到磁盘上的页面时将会触发缺页中断;
操作系统会将所需的页面从交换分区中换回物理内存,并重新更新页表以反映新的映射关系从而结局缺页中断的问题;
交换分区与内存之间的交换
当存在交换分区且物理内存不足等情况后,操作系统将会将部分没有必要的 页框/页帧 换出至磁盘中的交换分区中,这种交换被称为页面置换;
这是通过页面置换的算法实现的;
通常页面置换的算法包括:
-
最近最少使用
操作系统将选择最近最少使用的页面进行置换;
-
先进先出
操作系统将选择最早加载到内存中的页进行置换;
-
最不常用
操作系统将选择使用频率最低的页面进行置换;
通常被换出的大小为一个页框/页帧的大小,由于局部性原理,置换的页面可能是连续的,所以对于资源的浪费上一般只有最后一个页才会被浪费;
同时由于空间局部性原理,当在访问一个页时将会有很大的概率去访问该页的上下文,所以当在进行交换时将会有一个预加载机制,固定大小可以有效的进行这个预加载机制;
同时交换大小的固定可以减少内部碎片;
操作系统如何管理内存
在计算机当中操作系统可以直接看到物理内存并直接或间接对物理内存进行内存管理;
操作系统将把物理内存看做是若干个"页框/页帧";
且将通过 “先描述,再组织” 的方式对物理内存进行管理;
在操作系统内存中存在名为struct page的结构体;
这个结构体用于表示无力内存中的一个"页框/页帧",每个物理"页框/页帧"都有一个对应的 struct page 结构体实例,操作系统内核将通过这些结构体来管理物理内存;
其主要的字段如下:
struct page {
unsigned long flags;
atomic_t count;
struct address_space *mapping;
pgoff_t index;
void *private;
void *virtual;
};
以4GB为例,该内存当中将会有
4
×
1024
×
1024
×
1024
bytes
4
×
1024
bytes/page
=
1048576
pages
\frac{4 \times 1024 \times 1024 \times 1024 \text{ bytes}}{4 \times 1024 \text{ bytes/page}} = 1048576 \text{ pages}
4×1024 bytes/page4×1024×1024×1024 bytes=1048576 pages
个这样的结构体;
而这些结构体将会以数组的方式进行管理,struct page mem_array[1048576];
而这个数组中每一个数组下标即对应着一个页框的 页号 ;
- 例如
-
mem_array[0]对应第一个物理页框; -
mem_array[1]对应第二个物理页框; - 以此类推,
mem_array[1048575]对应最后一个物理页框;
在32位机器中,页内偏移量占用低12位,页号占用高20位;
因为这个结构体是存在于页框当中,而页框的大小仅只有4kb;
所以对应的结构体并不会太大(避免过多占用内存),通常以union的形式定义;
物理地址转换页号与页内偏移量
假设页的大小为4kb即 212 字节;
其中页号占用高20位,页内偏移量占用低12位;
- 提取页号
- 掩码:
0xFFFF F000 - 操作: 物理地址 &
0xFFFF F000 - 结果: 保留高
20位,将低12位清零;
- 提取页内偏移量
- 掩码:
0x0000 0FFF - 操作: 物理地址 &
0x0000 0FFF - 结果: 保留低
12位,将高20位清零;
其二进制表示:0001 0010 0011 0100 0101 0110 0111 1000;
当需要访问一个内存时只需要先找到这个4kb对应的page即可以找到对应的物理页框;
而实际上所有方位内存的动作都可以看做是访问内存Page数组;
内存管理,文件系统与文件管理之间的联系
当操作系统启动时将会进行预加载;
在文件系统中的预加载的内容一般为文件系统中的关于SuperBlock,GroupDescriptorTable,BlockBitmap,InodeBitmap等属性信息从而方便操作系统内核对其进行管理;
-
属性
当一个进程需要打开一个文件时,操作系统将会为这个打开的文件在进程的task_struct结构体中维护一个file_struct结构体,其中这个结构体中保存了一个 file*fd_array[]指针数组用于指向各个struct file文件结构体;
其中file* fd_array[]数组的下标即为文件描述符;
当打开一个文件时即为需要去访问该文件的信息,在struct file结构体中存储的信息只为少量的信息;
详细信息一般被存储在文件的Inode中;
而操作系统将会通过物理内存中的InodeBitmap,InodeTable中依次去寻找其对应的Inode;
当找到对应的Inode后操作系统内核将为这个打开的文件维护一个struct inode结构体并将Inode中的信息加载至该结构体当中从而能够建立文件与内核之间的联系;
struct inode {
umode_t i_mode;
unsigned long i_ino;
atomic_t i_count;
struct file_operations *i_fop;
struct super_block *i_sb;
struct address_space *i_mapping;
loff_t i_size;
struct timespec i_atime;
struct timespec i_mtime;
struct timespec i_ctime;
};
-
内容
同样的在struct file结构体中有一个指针,该指针指向了一个名为struct address_space的结构体;
struct radix_tree_root {
void *rnode;
};
在这个结构体中将会维护一棵名为radix_tree_root树,这是一棵结构为基数树的树;
而其中这棵树的每个节点即指向了一个strcut page的结构体;
struct page {
unsigned long flags;
atomic_t count;
struct address_space *mapping;
pgoff_t index;
void *private;
void *virtual;
};