- 论坛徽章:
- 1
|
LINUX的存储问题
好像我们讨论的跑题了,呵呵
看你提出的问题。偶觉得一起看看linux中进程是地址映射过程可能有所帮助。
1、Linus虚存采用动态地址映射方式,即Process的地址空间和存储空间的对应关系是在程序的执行过程中实现的:Process每用到一个地址时, 都需虚存的地址转换机构把虚拟地址转化为内存的实际地址。
2、每一个进程的task_struct中都有一个结构mm_struct,此结构包含了进程中与储存管理相关的大部分信息,其申明如下:
struct mm_struct {
int count; // 使用该mm结构的个数,如果是多处理机,则有可能count >; 1
pgd_t * pgd; /* 进程页目录的起始地址,如上图所示 */
unsigned long context;
unsigned long start_code, end_code, start_data, end_data;
/*start_code、end_code:进程代码段的起始地址和结束地址。
start_data、end_data:进程数据段的起始地址和结束地址。*/
unsigned long start_brk, brk, start_stack, start_mmap;
unsigned long arg_start, arg_end, env_start, env_end;
/* arg_start、arg_end:调用参数区的起始地址和结束地址。
env_start、env_end:进程环境区的起始地址和结束地址。*/
unsigned long rss, total_vm, locked_vm;
/* rss:进程内容驻留在物理内存的页面总数。*/
unsigned long def_flags;
struct vm_area_struct * mmap; /* 以双向链表组成的vma模块的首指针。 */
struct vm_area_struct * mmap_avl; /* 以avl树结构组成的虚拟空间的首指针。*/
struct semaphore mmap_sem;
}
3、用户共有4GB的虚存空间,实际可申请的虚存空间为0~3GB。3GB~4GB的虚存空间在用户进程创建时,已由函数fork()将kernel的代码段和数据段映射到3GB~4GB的虚存空间。因而所有进程的3GB~4GB的虚存空间的映象都是相同的,从而以这种方式使所有进程共享kernel的代码段和数据段。
4、进程的虚拟空间通常由一个个vma块组成,这些块的结构如下所示:
struct vm_area_struct {
struct mm_struct * vm_mm; /* VM area parameters */
unsigned long vm_start; //该vma块代表的使用虚拟空间的起始地址
unsigned long vm_end; //该vma块代表的使用虚拟空间的结束地址
pgprot_t vm_page_prot; //保护位
unsigned short vm_flags; //标志位
/* AVL tree of VM areas per task, sorted by address */
short vm_avl_height; //avl树高度
struct vm_area_struct * vm_avl_left; //vma块的左子节点
struct vm_area_struct * vm_avl_right; //vma块的右子节点
/* linked list of VM areas per task, sorted by address */
struct vm_area_struct * vm_next; /* 在按地址大小排列的单向链表上的下一个指针*/
/* for areas with inode, the circular list inode->;i_mmap */
/* for shm areas, the circular list of attaches */
/* otherwise unused */
struct vm_area_struct * vm_next_share;
struct vm_area_struct * vm_prev_share;
/* more */
struct vm_operations_struct * vm_ops; //对VMA块进行操作的函数集
unsigned long vm_offset;
struct inode * vm_inode; //该VMA块对应的文件
unsigned long vm_pte; /* shared mem */
};
采用avl树的优点是可以快速找到相关地址所在的vma块。同时,同一个任务的vma块还按前后顺序排成一个线性链表。
5、sys_execve系统调用负责将可执行文件映象载入到内存,与内存相关的操作主要是: 通过调用exit_mmap清除当前进程的所有的虚存块,通过调用clear_page_table清除当前进程的页表项,通过调用flush_old_signals清除当前进程的残留信号,通过调用flush_old_files清除当前进程的已打开文件,从而将当前进程掏空,成为一个空壳。然后系统根据bprm结构更新current进程的控制块,并通过调用两次do_mmap分别将执行文件的代码段和数据段映射到虚存。系统一般只将前两页载入物理内存中,同时分配一页给堆栈,其它的均留在硬盘中通过虚拟内存映射机制映射为虚拟内存。当运行中发生缺页中断时,系统处理缺页中断,将缺页调入物理内存中,如果发生物理内存不足的情况,则由kswapd()选择合适的页调入交换文件中或扔掉(如未发生写操作)。 |
|