首页 > 编程知识 正文

qsettings读写ini文件,linux网络原理

时间:2023-05-05 12:38:05 阅读:163100 作者:535

title: Linux-Arm page table

date :2019-11-2616336044:04

description: linux四级页表及其原理

1 .多级页面表概念介绍页面表之前,先回顾一下操作系统的基本概念,虚拟内存。

1.1虚拟内存存在于用户的视点中,每个进程都有自己的地址空间。 a进程的4GB和b进程的4GB是完全独立的,他们看到的是操作系统虚拟化的地址空间。 但是,虚拟地址最终必须落到实际内存的物理地址上进行操作。 操作系统通过页面表机制实现进程从虚拟地址到物理地址的翻译。 每个页面的大小都是固定的。 页面表管理有两个关键点:页面大小和页面表的级数。

1.2页面大小在Linux上,可以使用以下命令检查当前操作系统的页面大小

# getconf PAGE_SIZE 1.3页中的表层数越少,从虚拟地址到物理地址的映射越快,但需要管理的页表条目越多,支持的地址空间也越有限。 相反,页表的级数越多,存储的页表数据越少,可以支持相对较大的地址空间,但虚拟地址到物理地址的映射越慢。

举一个例子。 如果要在32位操作系统上支持4GB进程的虚拟地址空间,假设页表大小为4K,则总共为2的20次方页。 如果采用最快的1级页表,则需要2的20次方个页表条目才能对应。 如果页表条目是4字节,则进程需要内存(10485764=4M )来存储页表条目。 使用2级页表时,需要1024个页目录、1024个页表条目和2028个页表管理条目,(20484=) 8k可以支持4GB的地址空间转换。 此外,操作系统需要支持的是64位地址空间,为了支持数百个进程,这种开销是无法承受的。所以每个操作系统制定页表级数的时候都是在映射速度和页表占用空间中取折中。

从v2.6.11开始,Linux最终采用的方案是4级页表,分别为:

PGD:pageglobaldirectory(47-39 )、页面全局目录pud:pageupperdirectory (38-30 )、页面上级目录PMD:pagemiddledirectory 一个64位虚拟空间需要2^9个PGD 2^9个PUD 2^9个PMD 2^9个PTE=2048个页表数据结构。 当前的页表数据结构已扩展到8byte。 (2048*8=)仅16K )就可以支持2^48=) 256T的进程地址空间。

PGD: Page Global Directory

在Linux系统中,虽然每个进程对应用户空间的pgd都不同,但是Linux内核的pgd是相同的。 创建新的进程时,创建新进程的新页面目录PGD,从内核的页面目录swapper_pg_dir中将内核区间页面目录条目写入新进程页面目录PGD中的对应过程如下。 do_fork(-copy_mm )-mm _ init (PGD _ alloc )-set _ PGD _ fast (-get _ PGD _ slow )-memow )。

因此,每个进程的页面目录分为两个部分,第一个部分是“用户空间”,用于映射整个进程空间(0x0000 0000-0xBFFF FFFF )的3G虚拟地址第二部分是“系统空间”,它映射(0xC000 0000-0xFFFF FFFF ) 1gb的虚拟地址。 可以看到Linux系统中每个进程的页面目录的第二部分是相同的。 因此,从进程的角度看,每个进程都有4G的虚拟空间,较低的3G是自己的用户空间,最高1G是与所有进程和内核共享的系统空间。 每个进程都有自己的页面全局目录(PGD )。 这是一个物理页,其中包含pgd_t数组。

PTE: 页表项(page table entry)

PGD包括多个PUD的地址,PUD包括多个PMD的地址,以及PMD包括多个PT的地址。 每个PTE页面表条目都指向页面框,即实际的物理页面。

1.4页表存在的问题是,尽管16K的页表数据支持256T的地址空间寻址。 但是,这带来了额外的问题,页表存在于存储器中。 那就是,一次存储器IO只通过虚拟地址到物理地址的转换,就去存储器查询4次页表,如果加入真正的存储器访问,那么获取存储器数据就需要5次存储器IO。

TLB应运而生

与CPU的L1、L2、L3的缓存思想一致,地址转换所需的存储器I/O次数多,需要时间。 既然如此,干脆用CPU尽可能地对页表进行cache处理不就好了吗?这样就形成了TLB(translationlookasidebuffer )。

,专门用于改进虚拟地址到物理地址转换速度的缓存。其访问速度非常快,和寄存器相当,比L1访问还快。有了TLB之后,CPU访问某个虚拟内存地址的过程如下:

1.CPU产生一个虚拟地址2.MMU从TLB中获取页表,翻译成物理地址3.MMU把物理地址发送给L1/L2/L3/内存4.L1/L2/L3/内存将地址对应数据返回给CPU

  由于第2步是类似于寄存器的访问速度,所以如果TLB能命中,则虚拟地址到物理地址的时间开销几乎可以忽略。

二.内核页表和进程页表

  内核页表:即主内核页表,在内核中其实就是一段内存,存放在主内核页全局目录init_mm.pgd(swapper_pg_dir)中,硬件并不直接使用。

  进程页表:每个进程自己的页表,放在进程自身的页目录task_struct.pgd中。

  在保护模式下,从硬件角度看,其运行的基本对象为“进程”(或线程),而寻址则依赖于“进程页表”,在进程调度而进行上下文切换时,会进行页表的切换:即将新进程的pgd(页目录)加载到CR3寄存器中。

  1、 内核页表中的内容为所有进程共享,每个进程都有自己的“进程页表”,“进程页表中映射的线性地址包括两部分:
用户态,内核态

  其中,内核态地址对应的相关页表项,对于所有进程来说都是相同的(因为内核空间对所有进程来说都是共享的),而这部分页表内容其实就来源于“内核页表”,即每个进程的“进程页表”中内核态地址相关的页表项都是“内核页表”的一个拷贝。

  2、“内核页表”由内核自己维护并更新,在vmalloc区发生page fault时,将“内核页表”同步到“进程页表”中。以32位系统为例,内核页表主要包含两部分:线性映射区,vmalloc区

  其中,线性映射区即通过TASK_SIZE偏移进行映射的区域,对32系统来说就是0-896M这部分区域,映射对应的虚拟地址区域为TASK_SIZE-TASK_SIZE+896M。这部分区域在内核初始化时就已经完成映射,并创建好相应的页表,即这部分虚拟内存区域不会发生page fault。

  vmalloc区,为896M-896M+128M,这部分区域用于映射高端内存,有三种映射方式:vmalloc、固定、临时。以vmalloc为例(最常使用),这部分区域对应的线性地址在内核使用vmalloc分配内存时,其实就已经分配了相应的物理内存,并做了相应的映射,建立了相应的页表项,但相关页表项仅写入了“内核页表”,并没有实时更新到“进程页表中”,内核在这里使用了“延迟更新”的策略,将“进程页表”真正更新推迟到第一次访问相关线性地址,发生page fault时,此时在page fault的处理流程中进行“进程页表”的更新。

2.1 主内核页表 swapper_pg_dir

  主内核页表负责维护内核空间的页表映射,完成后的内核空间主页表映射如下图


(每一项映射1M空间,lk项刚好映射4G虚拟空间)swapper_pg_dir用于存放内核PGD页表的地方,赋给内核页表init_mm.pgd。swapper_pd_dir的大小为16KB,对应的虚拟地址空间是从0xc0004000 - 0xc0008000,物理地址空间是0x6000400~0x60008000。swapper_pg_dir被定义了绝对地址,在arch/arm/kernel/head.S中定义。

2.2 用户进程页表 2.2.1 进程如何使用内存

  毫无疑问,所有进程(执行的程序)都必须占用一定数量的内存,它或是用来存放从磁盘载入的程序代码,或是存放取自用户输入的数据等等。不过进程对这些内存的管理方式因内存用途不一而不尽相同,有些内存是事先静态分配和统一回收的,而有些却是按需要动态分配和回收的。
对任何一个普通进程来讲,它都会涉及到5种不同的数据段。

  代码段:代码段是用来存放可执行文件的操作指令,也就是说是它是可执行程序在内存中的镜像。代码段需要防止在运行时被非法修改,所以只准许读取操作,而不允许写入(修改)操作——它是不可写的。

  数据段:数据段用来存放可执行文件中已初始化全局变量,换句话说就是存放程序静态分配的变量和全局变量。

  BSS段:BSS段包含了程序中未初始化的全局变量,在内存中 bss段全部置零。

  堆(heap):堆是用于存放进程运行中被动态分配的内存段,它的大小并不固定,可动态扩张或缩减。当进程调用malloc等函数分配内存时,新分配的内存就被动态添加到堆上(堆被扩张);当利用free等函数释放内存时,被释放的内存从堆中被剔除(堆被缩减)

  :栈是用户存放程序临时创建的局部变量,也就是说我们函数括弧“{}”中定义的变量(但不包括static声明的变量,static意味着在数据段中存放变量)。除此以外,在函数被调用时,其参数也会被压入发起调用的进程栈中,并且待到调用结束后,函数的返回值也会被存放回栈中。由于栈的先进先出特点,所以栈特别方便用来保存/恢复调用现场。从这个意义上讲,我们可以把堆栈看成一个寄存、交换临时数据的内存区。

2.2.2 进程页表如何创建

进程的内核页全局目录的装载过程

  do_fork()->copy_process()->copy_mm()(如果是fork一个内核线程kernel thread的话,内核线程将会直接使用当前普通进程的页表集,内核线程并不拥有自己的页表集)->dup_mm()->mm_init()->mm_alloc_pgd()->pgd_alloc

  pgd_ctor(mm, pgd) //将swapper_pg_dir全局页目录(部分后256项–即内核最后1G的虚拟地址,这里指的是内核的页表)拷到pgd里,则可以看出,linux下所有进程的内核页全局目录是一样的,都是swapper_pg_dir里最后的1/4的内容,而每个进程的用户态的页表确是不同的,所以在dup_mmap会去将父进程的页表一项一项的爬出来设置为当前进程的页表。

进程的用户态地址页拷贝

  dup_mmap()函数实现页表映射的拷贝

  页表的复制

copy_page_range()copy_pud_range()copy_pmd_range()copy_pte_range()

  cr3寄存器的加载

  cr3寄存器的加载是在进程调度的时候更新的,具体如下schedule()->context_switch()->switch_mm()->load_cr3(next->pgd)。load_cr3加载的是mm_struct->pgd,即线性地址,而实际上加裁到cr3寄存器的是实际的物理地址write_cr3(__pa(pgdir));在装载cr3寄存器时将线性地址通过__pa转换成了物理地址了,所以cr3寄存器是装的是实实在在的物理地址。

2.2.3 用户进程页如何分配


  bss段
BSS段属于静态内存分配。通常是指用来存放程序中未初始化的全局变量和未初始化的局部静态变量。未初始化的全局变量和未初始化的局部静态变量默认值是0,本来这些变量也可以放到data段的,但是因为他们都是0,所以为他们在data段分配空间并且存放数据0是没有必要的。
程序在运行时,才会给BSS段里面的变量分配内存空间。在目标文件(*.o)和可执行文件中,BSS段只是为未初始化的全局变量和未初始化的局部静态变量预留位置而已,它并没有内容,所以它不占据空间。
section table中保存了BSS段(未初始化的全局变量和未初始化的局部静态变量)内存空间大小总和。(objdump -h *.o 命令可以看到)

  data段
数据段(datasegment)通常是指用来存放程序中已初始化的全局变量和已初始化的静态变量的一块内存区域。数据段属于静态内存分配。

  text段
代码段(codesegment/textsegment)通常是指用来存放程序执行代码的一块内存区域。这部分区域的大小在程序运行前就已经确定,并且内存区域通常属于只读,某些架构也允许代码段为可写,即允许修改程序。在代码段中,也有可能包含一些只读的常数变量,例如字符串常量等。

  rodata段
存放的是只读数据,比如字符串常量,全局const变量 和 #define定义的常量。

  heap堆
堆是用于存放进程运行中被动态分配的内存段,它的大小并不固定,可动态扩张或缩减。当进程调用malloc等函数分配内存时,新分配的内存就被动态添加到堆上(堆被扩张);当利用free等函数释放内存时,被释放的内存从堆中被剔除(堆被缩减)

  stack栈
是用户存放程序临时创建的局部变量,也就是说我们函数括弧“{}”中定义的变量(但不包括static声明的变量,static意味着在数据段中存放变量)。除此以外,在函数被调用时,其参数也会被压入发起调用的进程栈中,并且待到调用结束后,函数的返回值也会被存放回栈中。由于栈的先进先出特点,所以栈特别方便用来保存/恢复调用现场。从这个意义上讲,我们可以把堆栈看成一个寄存、交换临时数据的内存区。

  创建进程,虚拟地址和物理地址之间的映射关系

  上面的图说明:同一个变量,地址相同,其实是虚拟地址相同,内容不同其实是被映射到了不同的物理地址!

  过程:当访问虚拟内存时,会访问MMU(内存管理单元)去匹配对应的物理地址,而如果虚拟内存的页并不存在于物理内存中,会产生缺页中断,从磁盘中取得缺的页放入内存,如果内存已满,还会根据某种算法将磁盘中的页换出。(MMU中存储页表,用来匹配虚拟内存和物理内存)
的物理地址!

  过程:当访问虚拟内存时,会访问MMU(内存管理单元)去匹配对应的物理地址,而如果虚拟内存的页并不存在于物理内存中,会产生缺页中断,从磁盘中取得缺的页放入内存,如果内存已满,还会根据某种算法将磁盘中的页换出。(MMU中存储页表,用来匹配虚拟内存和物理内存)

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。