精华内容
下载资源
问答
  • linux 内存内核、版本查看命令内存1、free 查看内容使用情况 (可以加m 转化为Mb h 转化为Gb)totalusedfreesharedbufferscachedMemSwap表示物理 内存总量表示总计分配给缓存(包含buffers 与cache )使用的数量,...

    linux 内存、内核、版本查看命令

    内存

    1、free 查看内容使用情况 (可以加m 转化为Mb h 转化为Gb

    totalusedfreesharedbufferscachedMemSwap
    表示物理 内存总量

    表示总计分配给缓存

    (包含buffers 与cache )

    使用的数量,但其中可能

    部分缓存并未实际使用

    未被分配的内存共享内存

    系统分配但未被使

    用的buffers 数量

    系统分配但未被

    使用的cached数量

    实际使用的buffers总量和cacheed总量

    未被使用的buffers 与cache

     和未被分配的内存之和,这

    就是系统当前实际可用内存

    2、top命令就好像是“linux下的任务管理器”:


    然后是列表的含义:

    PID进程ID
    USER进程所有者
    PR优先级
    NInice值,负值表示高优先级,正值表示低优先级
    VIRT进程使用的虚拟内存总量
    RES进程使用的、未被换出的物理内存大小
    SHR共享内存大小
    S进程状态
    %CPU上次更新到现在的CPU时间占用百分比
    %MEM进程使用的物理内存百分比
    TIME+进程使用CPU总时间
    COMMAND命令名、命令行

    3、uptime命令能够打印系统总共运行了多长时间和系统的平均负载。uptime命令可以显示的信息显示依次为:现在时间、系统已经运行了多长时间、目前有多少登陆用户、系统在过去的1分钟、5分钟和15分钟内的平均负载

    -V:显示指令的版本信息。

    4、vmstat

    procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
     r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
     0  0     76 187932 154112 372228    0    0   143    32   36   90  1  1 94  3  0

    具体参数如下表:

    rThe number of processes waiting for run time.  处于运行队列中的内核线程数目(进程数)。
    bThe number of processes in uninterruptible sleep.置于等待队列(等待资源、等待输入/输出)的内核线程数目。 处于block队列中不可中断的进程数
    swpdthe amount of virtual memory used. 可用的虚拟交换内存
    freethe amount of idle memory.空闲内存
    buffthe amount of memory used as buffers.已用缓冲数目
    cachethe amount of memory used as cache.已用缓存数目
    siAmount of memory swapped in from disk (/s).磁盘到内存的交换页数目 (单位/S)
    soAmount of memory swapped to disk (/s).从交换内存到磁盘的交换页数目(单位/S)
    biBlocks received from a block device (blocks/s).接收到块设备的块数(块/秒)
    boBlocks sent to a block device (blocks/s).发送到块设备的块数(块/秒)
    inThe number of interrupts per second, including the clock.每秒中断数,包括时钟中断
    csThe number of context switches per second.每秒上下文切换数
    usTime spent running non-kernel code. (user time, including nice time)用户时间,处于用户模式的时间百分比
    syTime spent running kernel code. (system time)系统时间,处于内核模式的时间百分比
    idTime spent idle. Prior to Linux 2.5.41, this includes IO-wait time.CPU空闲时间,空闲时间百分比
    waTime spent waiting for IO. Prior to Linux 2.5.41, included in idle.CPU 空闲时间,在此期间系统有未完成的磁盘/NFS I/O 请求
    wtTime stolen from a virtual machine. Prior to Linux 2.6.11, unknown.

    来自于虚拟机偷取的CPU所占的百分比(这个不会翻译...)


    linux查看内核和版本信息

    1)查看当前版本的内核信息

            uname -a


    2)linux查看当前操作系统版本信息

            cat /proc/version 


    3)Linux查看版本当前操作系统发行版信息

        cat /etc/issue


    4)Linux查看cpu相关信息,包括型号、主频、内核信息等

        cat /proc/cpuinfo

          processor        : 0
         vendor_id         : AuthenticAMD
      cpu family        : 15
      model             : 1
      model name      : AMD A4-3300M APU with Radeon(tm) HD Graphics
      stepping         : 0
      cpu MHz          : 1896.236
      cache size       : 1024 KB
      fdiv_bug         : no
      hlt_bug          : no
      f00f_bug        : no
      coma_bug      : no
      fpu                : yes
      fpu_exception   : yes
      cpuid level      : 6
      wp                : yes
      flags             : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr
                               sse sse2 syscall mmxext lm 3dnowext 3dnow
      bogomips      : 3774.87

    5)Linux查看版本说明当前CPU运行在32bit模式下, 但不代表CPU不支持64bit

            getconf LONG_BIT

    32

    6)lsb_release 是查看系统版本信息的工具

    [root@localhost ~]# lsb_release -a
    -bash: lsb_release: command not found

    解决方法:yum install redhat-lsb -y

    [root@localhost ~]# lsb_release  -a
    LSB Version:    :core-4.0-amd64:core-4.0-noarch:graphics-4.0-amd64:graphics-4.0- noarch:printing-4.0-amd64:printing-4.0-noarch
    Distributor ID: CentOS
    Description:    CentOS Linux release 6.0 (Final)
    Release:        6.0
    Codename:       Final
    展开全文
  • linux内存管理--linux内核高端内存

    千次阅读 2014-04-12 20:28:32
    Linux内核地址映射模型 x86 CPU采用了段页式地址映射模型。进程代码中的地址为逻辑地址,经过段页式地址映射后,才真正访问物理内存。 段页式机制如下图。   Linux内核地址空间划分 ...Linux内核高端内存

    Linux内核地址映射模型
    x86 CPU
    采用了段页式地址映射模型。进程代码中的地址为逻辑地址,经过段页式地址映射后,才真正访问物理内存。

    段页式机制如下图。

     

    Linux内核地址空间划分

    通常32位Linux内核地址空间划分0~3G为用户空间,3~4G为内核空间。注意这里是32位内核地址空间划分,64位内核地址空间划分是不同的。

     

    Linux内核高端内存的由来

    当内核模块代码或线程访问内存时,代码中的内存地址都为逻辑地址,而对应到真正的物理内存地址,需要地址一对一的映射,如逻辑地址0xc0000003对应的物理地址为0×3,0xc0000004对应的物理地址为0×4,… …,逻辑地址与物理地址对应的关系为

    物理地址 = 逻辑地址 – 0xC0000000

    逻辑地址 物理内存地址
    0xc0000000 0×0
    0xc0000001 0×1
    0xc0000002 0×2
    0xc0000003 0×3
    0xe0000000 0×20000000
    0xffffffff 0×40000000 ??

    假设按照上述简单的地址映射关系,那么内核逻辑地址空间访问为0xc0000000 ~ 0xffffffff,那么对应的物理内存范围就为0×0 ~ 0×40000000,即只能访问1G物理内存。若机器中安装8G物理内存,那么内核就只能访问前1G物理内存,后面7G物理内存将会无法访问,因为内核的地址空间已经全部映射到物理内存地址范围0×0 ~ 0×40000000。即使安装了8G物理内存,那么物理地址为0×40000001的内存,内核该怎么去访问呢?代码中必须要有内存逻辑地址的,0xc0000000 ~ 0xffffffff的地址空间已经被用完了,所以无法访问物理地址0×40000000以后的内存。

    显然不能将内核地址空间0xc0000000 ~ 0xfffffff全部用来简单的地址映射。因此x86架构中将内核地址空间划分三部分:ZONE_DMA、ZONE_NORMAL和ZONE_HIGHMEM。ZONE_HIGHMEM即为高端内存,这就是内存高端内存概念的由来。


    在x86结构中,三种类型的区域如下:

    ZONE_DMA        内存开始的16MB

    ZONE_NORMAL       16MB~896MB

    ZONE_HIGHMEM       896MB ~ 结束

     

    Linux内核高端内存的理解

    前面我们解释了高端内存的由来。 Linux将内核地址空间划分为三部分ZONE_DMA、ZONE_NORMAL和ZONE_HIGHMEM,高端内存HIGH_MEM地址空间范围为0xF8000000 ~ 0xFFFFFFFF(896MB~1024MB)。那么如内核是如何借助128MB高端内存地址空间是如何实现访问可以所有物理内存

    当内核想访问高于896MB物理地址内存时,从0xF8000000 ~ 0xFFFFFFFF地址空间范围内找一段相应大小空闲的逻辑地址空间,借用一会。借用这段逻辑地址空间,建立映射到想访问的那段物理内存(即填充内核PTE页面表),临时用一会,用完后归还。这样别人也可以借用这段地址空间访问其他物理内存,实现了使用有限的地址空间,访问所有所有物理内存。如下图。

    例如内核想访问2G开始的一段大小为1MB的物理内存,即物理地址范围为0×80000000 ~ 0x800FFFFF。访问之前先找到一段1MB大小的空闲地址空间,假设找到的空闲地址空间为0xF8700000 ~ 0xF87FFFFF,用这1MB的逻辑地址空间映射到物理地址空间0×80000000 ~ 0x800FFFFF的内存。映射关系如下:

    逻辑地址 物理内存地址
    0xF8700000 0×80000000
    0xF8700001 0×80000001
    0xF8700002 0×80000002
    0xF87FFFFF 0x800FFFFF

    当内核访问完0×80000000 ~ 0x800FFFFF物理内存后,就将0xF8700000 ~ 0xF87FFFFF内核线性空间释放。这样其他进程或代码也可以使用0xF8700000 ~ 0xF87FFFFF这段地址访问其他物理内存。

    从上面的描述,我们可以知道高端内存的最基本思想:借一段地址空间,建立临时地址映射,用完后释放,达到这段地址空间可以循环使用,访问所有物理内存。

    看到这里,不禁有人会问:万一有内核进程或模块一直占用某段逻辑地址空间不释放,怎么办?若真的出现的这种情况,则内核的高端内存地址空间越来越紧张,若都被占用不释放,则没有建立映射到物理内存都无法访问了。

    在香港尖沙咀有些写字楼,洗手间很少且有门锁的。客户要去洗手间的话,可以向前台拿钥匙,方便完后,把钥匙归还到前台。这样虽然只有一个洗手间,但可以满足所有客户去洗手间的需求。要是某个客户一直占用洗手间、钥匙不归还,那么其他客户都无法上洗手间了。Linux内核高端内存管理的思想类似。


    Linux内核高端内存的划分
    内核将高端内存划分为3部分:VMALLOC_START~VMALLOC_END、KMAP_BASE~FIXADDR_START和FIXADDR_START~4G。


    对于高端内存,可以通过 alloc_page() 或者其它函数获得对应的 page,但是要想访问实际物理内存,还得把 page 转为线性地址才行(为什么?想想 MMU 是如何访问物理内存的),也就是说,我们需要为高端内存对应的 page 找一个线性空间,这个过程称为高端内存映射。

    对应高端内存的3部分,高端内存映射有三种方式:
    映射到”内核动态映射空间”(noncontiguous memory allocation)
    这种方式很简单,因为通过 vmalloc() ,在”内核动态映射空间”申请内存的时候,就可能从高端内存获得页面(参看 vmalloc 的实现),因此说高端内存有可能映射到”内核动态映射空间”中。

    持久内核映射(permanent kernel mapping)
    如果是通过 alloc_page() 获得了高端内存对应的 page,如何给它找个线性空间?
    内核专门为此留出一块线性空间,从 PKMAP_BASE 到 FIXADDR_START ,用于映射高端内存。在 2.6内核上,这个地址范围是 4G-8M 到 4G-4M 之间。这个空间起叫”内核永久映射空间”或者”永久内核映射空间”。这个空间和其它空间使用同样的页目录表,对于内核来说,就是 swapper_pg_dir,对普通进程来说,通过 CR3 寄存器指向。通常情况下,这个空间是 4M 大小,因此仅仅需要一个页表即可,内核通过来 pkmap_page_table 寻找这个页表。通过 kmap(),可以把一个 page 映射到这个空间来。由于这个空间是 4M 大小,最多能同时映射 1024 个 page。因此,对于不使用的的 page,及应该时从这个空间释放掉(也就是解除映射关系),通过 kunmap() ,可以把一个 page 对应的线性地址从这个空间释放出来。

    临时映射(temporary kernel mapping)
    内核在 FIXADDR_START 到 FIXADDR_TOP 之间保留了一些线性空间用于特殊需求。这个空间称为”固定映射空间”在这个空间中,有一部分用于高端内存的临时映射。

    这块空间具有如下特点:
    (1)每个 CPU 占用一块空间
    (2)在每个 CPU 占用的那块空间中,又分为多个小空间,每个小空间大小是 1 个 page,每个小空间用于一个目的,这些目的定义在 kmap_types.h 中的 km_type 中。

    当要进行一次临时映射的时候,需要指定映射的目的,根据映射目的,可以找到对应的小空间,然后把这个空间的地址作为映射地址。这意味着一次临时映射会导致以前的映射被覆盖。通过 kmap_atomic() 可实现临时映射。

    高端内存的映射可以使用下面的一张图看出来:



    常见问题:

    1、用户空间(进程)是否有高端内存概念?

    用户进程没有高端内存概念。只有在内核空间才存在高端内存。用户进程最多只可以访问3G物理内存,而内核进程可以访问所有物理内存。

    2、64位内核中有高端内存吗?

    目前现实中,64位Linux内核不存在高端内存,因为64位内核可以支持超过512GB内存。若机器安装的物理内存超过内核地址空间范围,就会存在高端内存。

    3、用户进程能访问多少物理内存?内核代码能访问多少物理内存?

    32位系统用户进程最大可以访问3GB,内核代码可以访问所有物理内存。

    64位系统用户进程最大可以访问超过512GB,内核代码可以访问所有物理内存。

    4、高端内存和物理地址、逻辑地址、线性地址的关系?

    高端内存只和物理地址有关系,和线性地址、逻辑地址没有直接关系。

    5、为什么不把所有的地址空间都分配给内核?

    若把所有地址空间都给内存,那么用户进程怎么使用内存?怎么保证内核使用内存和用户进程不起冲突?

    展开全文
  • Linux查看内核、CPU、内存及各组件版本的命令和方法 Linux查看内核版本: uname -a  more /etc/*release   more /etc/RedHat-release  more /proc/version 查看C

    Linux下查看内核、CPU、内存及各组件版本的命令和方法

    Linux查看内核版本: uname -a
                            more /etc/*release 
                            more /etc/RedHat-release
                            more /proc/version

    查看CPU信息:grep "model name" /proc/cpuinfo
                            more /proc/cpuinfo

    查看CPU位数:getconf LONG_BIT
                            ls  如果在root下ls有lib64 文件夹说明系统64

    查看libc、gcc版本:ldd /sbin/mii-tool
                                    rpm -qa | grep glibc
                                    gcc –v

    查看内存信息:more /proc/meminfo

        grep MemTotal /proc/meminfo
    CentOS查看CPU、内存、版本等系统信息
     
      CentOS查看系统信息

      一:查看CPU

      more /proc/cpuinfo | grep "model name"

      grep "model name" /proc/cpuinfo

      如果觉得需要看的更加舒服

      grep "model name" /proc/cpuinfo | cut -f2 -d:

      怎么样,Linux的命令就要这样熟悉。

      二:查看内存

      grep MemTotal /proc/meminfo

      grep MemTotal /proc/meminfo | cut -f2 -d:

      free -m |grep "Mem" | awk '{print $2}'

      三:查看cpu是32位还是64位

      查看CPU位数(32 or 64)

      #getconf LONG_BIT

      #echo $HOSTTYPE

      #uname -a

      四:查看当前linux的版本

      #more /etc/RedHat-release

      #cat /etc/redhat-release

      五:查看内核版本

      #uname -r

      #uname -a

      六:查看当前时间

      date

      七:查看硬盘和分区

      df -h

      

      fdisk -l

      也可以查看分区

      du -sh

      可以看到全部占用的空间

      du /etc -sh

      可以看到这个目录的大小

      八:查看安装的软件包

      查看系统安装的时候装的软件包

      cat -n /root/install.log

      more /root/install.log | wc -l

      查看现在已经安装了那些软件包

      rpm -qa

      rpm -qa | wc -l

      yum list installed | wc -l

      不过很奇怪,我通过rpm,和yum这两种方式查询的安装软件包,数量并不一样。没有找到原因。

      九:查看键盘布局

      cat /etc/sysconfig/keyboard

      cat /etc/sysconfig/keyboard | grep KEYTABLE | cut -f2 -d=

      十:查看selinux情况

      sestatus

      sestatus | cut -f2 -d:

      cat /etc/sysconfig/selinux

      十一:查看ip,mac地址

      在ifcfg-eth0 文件里你可以看到mac,网关等信息。

      ifconfig

      cat /etc/sysconfig/network-scripts/ifcfg-eth0 | grep IPADDR

      cat /etc/sysconfig/network-scripts/ifcfg-eth0 | grep IPADDR | cut -f2 -d=

      ifconfig eth0 |grep "inet addr:" |awk '{print $2}'|cut -c 6-

      ifconfig  | grep 'inet addr:'| grep -v '127.0.0.1' | cut -d: -f2 | awk '{ print $1}'

      查看网关

      cat /etc/sysconfig/network

      查看dns

      cat /etc/nf

      十二:查看默认语言

      echo $LANG $LANGUAGE

      cat /etc/sysconfig/i18n

      十三:查看所属时区和是否使用UTC时间

      cat /etc/sysconfig/clock

      十四:查看主机名

      hostname

      cat /etc/sysconfig/network

    修改主机名就是修改这个文件,同时最好也把host文件也修改

    1. 内核版本:popen("uname -sr", "r");
    2.内存容量:/proc/meminfo ‘MemTotal:’字段
    3.操作系统版本:/etc/issue 或者 /etc/*ease
    4.当前用户名:a.getuid()获取当前用户的uid;b.getpwuid(uid)或者用户名
    5.cpu名称:/proc/cpuinfo ’model name‘字段
    6.cpu内核数:/proc/cpuinfo 'processor'字段最大值+1(逻辑核数), 'physical id'字段最大值 + 1

    展开全文
  • LinuxLinux内核空间(低端内存、高端内存

    万次阅读 多人点赞 2018-07-20 16:50:01
    内核也是程序,也应该具有自己的虚存空间,但是作为一种为用户程序服务的程序,内核空间有它自己的特点。   内核空间与用户空间的关系 在一个32位系统中,一个程序的虚拟空间最大可以是4GB,那么最直接的做法...

    内核也是程序,也应该具有自己的虚存空间,但是作为一种为用户程序服务的程序,内核空间有它自己的特点。

     

    内核空间与用户空间的关系

    在一个32位系统中,一个程序的虚拟空间最大可以是4GB,那么最直接的做法就是,把内核也看作是一个程序,使它和其他程序一样也具有4GB空间。但是这种做法会使系统不断的切换用户程序的页表和内核页表,以致影响计算机的效率。解决这个问题的最好做法就是把4GB空间分成两个部分:一部分为用户空间,另一部分为内核空间,这样就可以保证内核空间固定不变,而当程序切换时,改变的仅是程序的页表。这种做法的唯一缺点便是内核空间和用户空间均变小了。

    例如:在i386这种32位的硬件平台上,Linux在文件page.h中定义了一个常量PAGE_OFFSET:

    #ifdef CONFIG_MMU
    #define __PAGE_OFFSET  (0xC0000000)        //0xC0000000为3GB
    #else
    #define __PAGE_OFFSET  (0x00000000)
    #endif
    
    #define PAGE_OFFSET		((unsigned long)__PAGE_OFFSET)

    Linux以PAGE_OFFSET为界将4GB的虚拟内存空间分成了两部分:地址0~3G-1这段低地址空间为用户空间,大小为3GB;地址3GB~4GB-1这段高地址空间为内核空间,大小为1GB。

    当系统中运行多个程序时,多个用户空间与内核空间的关系可以表示如下图:

    如图中所示,程序1、2……n共享内核空间。当然,这里的共享指得是分时共享,因为在任何时刻,对于单核处理器系统来说,只能有一个程序在运行。

     

    内核空间的总体布局

    Linux在发展过程中,随着硬件设备的更新和技术水平的提高,其内核空间布局的发展也是一种不断打补丁的方式。这样的后果就是使得内核空间被分成不同的几个区域,而且在不同的区域具有不同的映射方式。通常,人们认为Linux内核空间有三个区域,即DMA区(ZONE_DMA)、普通区(ZONE_NORMAL)和高端内存区(ZONE_HIGHMEM)。

    实际物理内存较小时内核空间的直接映射

    早期计算机实际配置的物理内存通常只有几MB,所以为了提高内核通过虚拟地址访问物理地址内存的速度,内核空间的虚拟地址与物理内存地址采用了一种从低地址向高地址依次一一对应的固定映射方式,如下图所示:

    可以看到,这种固定映射方式使得虚拟地址与物理地址的关系变得很简单,即内核虚拟地址与实际物理地址只在数值上相差一个固定的偏移量PAGE_OFFSET,所以当内核使用虚拟地址访问物理页框时,只需在虚拟地址上减去PAGE_OFFSET即可得到实际物理地址,比使用页表的方式要快得多!

    由于这种做法几乎就是直接使用物理地址,所以这种按固定映射方式的内核空间也就叫做“物理内存空间”,简称物理内存。另外,由于固定映射方式是一种线性映射,所以这个区域也叫做线性映射区。

    当然,这种情况下(计算机实际物理内存较小时),内核固定映射空间仅占整个1GB内核空间的一部分。例如:在配置32MB实际物理内存的x86计算机系统时,内核的固定映射区便是PAGE_OFFSET~(PAGE_OFFSET+0x02000000)这个32MB空间。那么内核空间剩余的内核虚拟空间怎么办呢?

    当然还是按照普通虚拟空间的管理方式,以页表的非线性映射方式使用物理内存。具体来说,在整个1GB内核空间中去除固定映射区,然后在剩余部分中再去除其开头部分的一个8MB隔离区,余下的就是映射方式与用户空间相同的普通虚拟内存映射区。在这个区,虚拟地址和物理地址不仅不存在固定映射关系,而且通过调用内核函数vmalloc()获得动态内存,故这个区就被称为vmalloc分配区,如下图所示:

    对于配置32MB实际物理内存的x86计算机系统来说,vmalloc分配区的起始位置为PAGE_OFFSET+0x02000000+0x00800000。

    这里说明一下:这里说的内核空间与物理页框的固定映射,实质上是内核页对物理页框的一种“预定”,并不是说这些页就“霸占”了这些物理页框。即只有当虚拟页真正需要访问物理页框时,虚拟页才与物理页框绑定。而平时,当某个物理页框不被与它对应的虚拟页所使用时,该页框完全可以被用户空间以及后面所介绍的内核kmalloc分配区使用。

    总之,在实际物理内存较小的系统中,实际内存的大小就是内核空间的物理内存区与vmalloc分配区的边界。

    ZONE_DMA区与ZONE_NORMAL区

    对于整个1GB的内核空间,人们还把该空间头部的16MB叫做DMA区,即ZONE_DMA区,因为以往硬件将DMA空间固定在了物理内存的低16MB空间;其余区则叫做普通区,即ZONE_NORMAL。

     

    内核空间的高端内存

    随着计算机技术的发展,计算机的实际物理内存越来越大,从而使得内核固定映射区(线性区)也越来越大。显然,如果不加以限制,当实际物理内存达到1GB时,vmalloc分配区(非线性区)将不复存在。于是以前开发的、调用了vmalloc()的内核代码也就不再可用,显然为了兼容早期的内核代码,这是不能允许的。

    下图就表示了这种内核空间所面临的局面:

    显然,出现上述问题的原因就是没有预料到实际物理内存可以超过1GB,因而没有为内核固定映射区的边界设定限制,而任由其随着实际物理内存的增大而增大。

    解决上述问题的方法就是:对内核空间固定映射区的上限加以限制,使之不能随着物理内存的增加而任意增加。Linux规定,内核映射区的上边界的值最大不能大于一个小于1G的常数high_menory,当实际物理内存较大时,以3G+high_memory为边界来确定物理内存区。

    例如:对于x86系统,high_memory的值为896M,于是1GB内核空间余下的128MB为非线性映射区。这样就确保在任何情况下,内核都有足够的非线性映射区以兼容早期代码并可以按普通虚存方式访问实际物理内存的1GB以上的空间。

    也就是说,高端内存的最基本思想:借一段地址空间,建立临时地址映射,用完后释放,达到这段地址空间可以循环使用,访问所有物理内存。当计算机是物理内存较大时,内核空间的示意图如下:

    习惯上,Linux把内核空间3G+high_memory~4G-1的这个部分叫做高端内存区(ZONE_HIGHMEM)。

    总结一下:在x86结构的内核空间,三种类型的区域(从3G开始计算)如下:

    • ZONE_DMA:内核空间开始的16MB
    • ZONE_NORMAL:内核空间16MB~896MB(固定映射)
    • ZONE_HIGHMEM :内核空间896MB ~ 结束(1G)

    根据应用目标不同,高端内存区分vmalloc区、可持久映射区和临时映射区。内核空间中高端内存的布局如下图所示:

    vmalloc映射区

    vmalloc映射区时高端内存的主要部分,该区间的头部与内核线性映射空间之间有一个8MB的隔离区,尾部与后续的可持久映射区有一个4KB的隔离区。

    vmalloc映射区的映射方式与用户空间完全相同,内核可以通过调用函数vmalloc()在这个区域获得内存。这个函数的功能相当于用户空间的malloc(),所提供的内存空间在虚拟地址上连续(注意,不保证物理地址连续)。

    可持久内核映射区

    如果是通过 alloc_page() 获得了高端内存对应的 page,如何给它找个线性空间?

    内核专门为此留出一块线性空间,从PKMAP_BASE开始,用于映射高端内存,就是可持久内核映射区。

    在可持久内核映射区,可通过调用函数kmap()在物理页框与内核虚拟页之间建立长期映射。这个空间通常为4MB,最多能映射1024个页框,数量较为稀少,所以为了加强页框的周转,应及时调用函数kunmap()将不再使用的物理页框释放。

    临时映射区

    临时映射区也叫固定映射区和保留区。该区主要应用在多处理器系统中,因为在这个区域所获得的内存空间没有所保护,故所获得的内存必须及时使用;否则一旦有新的请求,该页框上的内容就会被覆盖,所以这个区域叫做临时映射区。

    关于高端内存区一篇很不错的文章:linux 用户空间与内核空间——高端内存详解

     

    内核内存分配修饰符gfp

    为了在内核内存请求函数对请求进行必要的说明,Linux定义了多种内存分配修饰符gfp。它们是行为修饰符、区修饰符、类型修饰符。

    行为修饰符

    在内存分配函数中的行为修饰符说明内核应当如何分配内存。主要行为修饰符如下:

    Linux的主要内核内存分配行为修饰符
    修饰符 说明
    __GFP_WAIT 分配器可以休眠
    __GFP_HIGH 分配器可以访问紧急事件缓冲池
    __GFP_IO 分配器可以启动磁盘IO
    __GFP_FS 分配器可以启动文件系统IO
    __GFP_COLD 分配器应该使用高速缓冲中快要淘汰的页框
    __GFP_NOWARN 分配器不发出警告
    __GFP_REPEAT 分配失败时重新分配
    __GFP_NOFAILT 分配失败时重新分配,直至成功
    __GFP_NORETRY 分配失败时不再重新分配

    区修饰符

    区修饰符说明需要从内核空间的哪个区域中分配内存。内存分配器默认从内核空间的ZONE_NORMAL开始逐渐向高端获取为内存请求者分配内存区,如果用户特意需要从ZONE_DMA或ZONE_HOGNMEM获得内存,那么就需要内存请求者在内存请求函数中使用以下两个区修饰符说明:

    Linux的主要内核内存分配区修饰符
    修饰符 说明
    __GFP_DMA 从ZONE_DMA区分配内存
    __GFP_HIGHMEM 从ZONE_HIGHMEM区分配内存

    类型修饰符

    类型修饰符实质上是上述所述修饰符的联合应用。也就是:将上述的某些行为修饰符和区修饰符,用“|”进行连接并另外取名的修饰符。这里就不多介绍了。

     

    内核常用内存分配及地址映射函数

    函数vmalloc()

    函数vmalloc()在vmalloc分配区分配内存,可获得虚拟地址连续,但并不保证其物理页框连续的较大内存。与物理空间的内存分配函数malloc()有所区别,vmalloc()分配的物理页不会被交换出去。函数vmalloc()的原型如下:

    void *vmalloc(unsigned long size)
    {
           return __vmalloc(size, GFP_KERNEL | __GFP_HIGHMEM, PAGE_KERNEL);
    }
    void *__vmalloc(unsigned long size, gfp_t gfp_mask, pgprot_t prot)
    {
    	return kmalloc(size, (gfp_mask | __GFP_COMP) & ~__GFP_HIGHMEM);
    }

    其中,参数size为所请求内存的大小,返回值为所获得内存虚拟地址指针。

    与vmalloc()配套的释放函数如下:

    void vfree(const void *addr)
    {
    	kfree(addr);
    }

    其中,参数addr为待释放内存指针。

    函数kmalloc()

    kmalloc()是内核另一个常用的内核分配函数,它可以分配一段未清零的连续物理内存页,返回值为直接映射地址。由kmalloc()可分配的内存最大不能超过32页。其优点是分配速度快,缺点是不能分配大于128KB的内存页(出于跨平台考虑)。

    在linux/slab.h文件中,该函数的原型声明如下:

    static __always_inline void *kmalloc(size_t size, gfp_t flags)
    {
    	struct kmem_cache *cachep;
    	void *ret;
    
    	if (__builtin_constant_p(size)) {
    		int i = 0;
    
    		if (!size)
    			return ZERO_SIZE_PTR;
    
    #define CACHE(x) \
    		if (size <= x) \
    			goto found; \
    		else \
    			i++;
    #include <linux/kmalloc_sizes.h>
    #undef CACHE
    		return NULL;
    found:
    #ifdef CONFIG_ZONE_DMA
    		if (flags & GFP_DMA)
    			cachep = malloc_sizes[i].cs_dmacachep;
    		else
    #endif
    			cachep = malloc_sizes[i].cs_cachep;
    
    		ret = kmem_cache_alloc_notrace(cachep, flags);
    
    		trace_kmalloc(_THIS_IP_, ret,
    			      size, slab_buffer_size(cachep), flags);
    
    		return ret;
    	}
    	return __kmalloc(size, flags);
    }
    

    其中,参数size为以字节为单位表示的所申请空间的大小;参数flags决定了所分配的内存适合什么场合。

    与函数kmalloc()对应的释放函数如下:

    void kfree(const void *objp)
    {
    	struct kmem_cache *c;
    	unsigned long flags;
    
    	trace_kfree(_RET_IP_, objp);
    
    	if (unlikely(ZERO_OR_NULL_PTR(objp)))
    		return;
    	local_irq_save(flags);
    	kfree_debugcheck(objp);
    	c = virt_to_cache(objp);
    	debug_check_no_locks_freed(objp, obj_size(c));
    	debug_check_no_obj_freed(objp, obj_size(c));
    	__cache_free(c, (void *)objp);
    	local_irq_restore(flags);
    }

    小结一下,kmalloc、vmalloc、malloc的区别:

    • kmalloc和vmalloc是分配的是内核的内存,malloc分配的是用户的内存;
    • kmalloc保证分配的内存在物理上是连续的,vmalloc保证的是在虚拟地址空间上的连续,malloc不保证任何东西;
    • kmalloc能分配的大小有限,vmalloc和malloc能分配的大小相对较大;
    • vmalloc比kmalloc要慢。

    也就是说:kmalloc、vmalloc这两个函数所分配的内存都处于内核空间,即从3GB~4GB;但位置不同,kmalloc()分配的内存处于3GB~high_memory(ZONE_DMA、ZONE_NORMAL)之间,而vmalloc()分配的内存在VMALLOC_START~4GB(ZONE_HIGHMEM)之间,也就是非连续内存区。一般情况下在驱动程序中都是调用kmalloc()来给数据结构分配内存,而vmalloc()用在为活动的交换区分配数据结构,为某些I/O驱动程序分配缓冲区,或为模块分配空间。

    可参考文章:Kmalloc和Vmalloc的区别

    函数alloc_pages()

    与上述在虚拟空间分配内存的函数不同,alloc_pages()是在物理内存空间分配物理页框的函数,其原型如下:

    static inline struct page * alloc_pages(gfp_t gfp_mask, unsigned int order)
    {
    	if (unlikely(order >= MAX_ORDER))
    		return NULL;
    
    	return alloc_pages_current(gfp_mask, order);
    }

    其中,参数order表示所分配页框的数目,该数目为2^order。order的最大值由include/Linux/Mmzone.h文件中的宏MAX_ORDER决定。参数gfp_mask为说明内存页框分配方式及使用场合。

    函数返回值为页框块的第一个页框page结构的地址。

    调用下列函数可以获得页框的虚拟地址:

    void *page_address(struct page *page)
    {
    	unsigned long flags;
    	void *ret;
    	struct page_address_slot *pas;
    
    	if (!PageHighMem(page))
    		return lowmem_page_address(page);
    
    	pas = page_slot(page);
    	ret = NULL;
    	spin_lock_irqsave(&pas->lock, flags);
    	if (!list_empty(&pas->lh)) {
    		struct page_address_map *pam;
    
    		list_for_each_entry(pam, &pas->lh, list) {
    			if (pam->page == page) {
    				ret = pam->virtual;
    				goto done;
    			}
    		}
    	}
    done:
    	spin_unlock_irqrestore(&pas->lock, flags);
    	return ret;
    }

    使用函数alloc_pages()获得的内存应该使用下面的函数释放:

    void __free_pages(struct page *page, unsigned int order)
    {
    	if (put_page_testzero(page)) {
    		if (order == 0)
    			free_hot_page(page);
    		else
    			__free_pages_ok(page, order);
    	}
    }
    

    函数kmap()

    kmap()是一个映射函数,它可以将一个物理页框映射到内核空间的可持久映射区。这种映射类似于内核ZONE_NORMAL的固定映射,但虚拟地址与物理地址的偏移不一定是PAGE_OFFSET。由于内核可持久映射区的容量有限(总共只有4MB),因此当内存使用完毕后,应该立即释放。

    函数kmap()的函数原型如下:

    void *kmap(struct page *page)
    {
    	might_sleep();
    	if (!PageHighMem(page))
    		return page_address(page);
    	return kmap_high(page);
    }

     

    本文小结

    由于CPU的地址总线只有32位, 32的地址总线无论是从逻辑上还是从物理上都只能描述4G的地址空间(232=4Gbit),在物理上理论上最多拥有4G内存(除了IO地址空间,实际内存容量小于4G),逻辑空间也只能描述4G的线性地址空间。

    为了合理的利用逻辑4G空间,Linux采用了3:1的策略,即内核占用1G的线性地址空间,用户占用3G的线性地址空间。所以用户进程的地址范围从0~3G,内核地址范围从3G~4G,也就是说,内核空间只有1G的逻辑线性地址空间。

    如果Linux物理内存小于1G的空间,通常内核把物理内存与其地址空间做了线性映射,也就是一一映射,这样可以提高访问速度。但是,当Linux物理内存超过1G时,线性访问机制就不够用了,因为只能有1G的内存可以被映射,剩余的物理内存无法被内核管理,所以,为了解决这一问题,Linux把内核地址分为线性区和非线性区两部分,线性区规定最大为896M,剩下的128M为非线性区。从而,线性区映射的物理内存成为低端内存,剩下的物理内存被成为高端内存。与线性区不同,非线性区不会提前进行内存映射,而是在使用时动态映射。

    低端内存又分成两部分:ZONE_DMA:内核空间开始的16MB、ZONE_NORMAL:内核空间16MB~896MB(固定映射)。剩下的就是高端内存:ZONE_HIGHMEM :内核空间896MB ~ 结束(1G)。

    根据应用目标不同,高端内存区分vmalloc区、可持久映射区和临时映射区三部分。vmalloc区使用vmalloc()函数进行分配;可持久映射区使用allc_pages()获得对应的 page,在利用kmap()函数直接映射;临时映射区一般用于特殊需求。

    用户空间和内核空间
    内核空间(3G~4G)

    高端内存(3G+high_memory~4G)ZONE_HIGHMEM

    非线性映射区

    临时映射区
    可持久映射区
    vmalloc区

    低端内存(3G~3G+high_memory-1)

    线性映射区(固定映射区)

    ZONE_NORMAL
    ZONE_DMA
    用户空间(0~3G-1) 页目录-->中间页目录-->页表

     

    展开全文
  • linux2.6.1内核源码注释

    万次下载 热门讨论 2014-03-10 15:21:33
    包含LINUX内核同步、信号、内存、调度、文件系统、网络系统、时钟等部分的源码注释。前后历时三年,算是干货。
  • linux内核内存分配

    千次阅读 2013-11-18 20:56:07
    内核中的内存分配通常通过kmalloc/kfree来进行,但是也有其它的方式来获取内存,所有这些方式共同提供了内核中分配、释放内存的接口。 一、kmalloc/kfree 类似于标准C中的malloc/free,kmalloc/kfree是内核中的用于...
  • Linux内核内存压缩技术

    千次阅读 2017-12-02 22:59:01
    为什么需要内存压缩说到压缩这个词,我们都可以想到是降低占用空间,使同样的空间可以存放更多的东西,如我们平时常用的压缩文件等。内存压缩同样也是为了节省内存内存无论是多大,总是不够用的(至少目前如此)...
  • 浅析linux内核内存管理之内存

    千次阅读 2012-05-09 22:19:15
    内存池(memory pool)是linux 2.6的一个新特性。内核中有些地方的内存分配是不允许失败的。为了确保这种情况下的成功分配,内核开发者建立了一种称为内存池的抽象。内存池其实就是某种形式的后备高速缓存,它试图始终...
  • 鉴于此,《Linux内核精髓:精通Linux内核必会的75个绝技》选取了资源管理(CPU、内存、进程等)、文件系统、网络、虚拟化、省电、调试、概要分析、追踪、内核调整等Linux内核的核心主题进行了深入剖析和讲解,总结出...
  • Linux内存管理内核API函数alloc_pages( )

    千次阅读 2018-06-24 15:24:59
    http://blog.163.com/chujb_chen/blog/static/10571112013392331217/函数功能描述: alloc_pages( )函数以... 输入参数说明: gfp_mask: 是分配标志,内核分配内存有多种方式,该参数告诉内核如何分配以及在哪...
  • Linux内核 内存映射文件机制mmap

    千次阅读 2014-09-21 00:00:20
    今天研究Linux1.2内核
  • linux内核内存的详细分配

    万次阅读 2015-08-04 22:23:40
    我们知道CPU所访问的都是虚拟内存地址。...在linux内存管理中,用户使用0~3GB的地址空间,而内核只是用了3GB~4GB区间的地址空间,共1GB;非连 续空间的物理映射就位于3GB~4GB之间,如下图示 0GB
  • Linux 内核内存泄露工具使用

    千次阅读 2015-06-04 11:56:18
    1. 内核添加内存泄漏功能选项  kernel memory leak detector  kernel debugging  memory leak debugging  Compile kernel with debug info  通过make menuconfig 进入配置选项界面进入kernel hacking -->
  • Linux内核高端内存

    千次阅读 2012-04-27 12:22:50
    ZZ FROM: ...Linux内核地址映射模型 x86 CPU采用了段页式地址映射模型。进程代码中的地址为逻辑地址,经过段页式地址映射后,才真正访问物理内存。 段页式机制如下图。   Lin
  • linux 内核如何管理内存

    千次阅读 2015-07-30 01:51:46
    翻译自 ttp://duartes.org/gustavo/blog/post/how-the-... 在介绍完了进程虚拟地址空间的布局后, 我们来看一下内核是如何管理内存的:  linux的进程在内核中是由一个task_struct结构体描述的, 其中task_struct里面
  • linux内核内存管理中的pagevec结构体

    千次阅读 2010-12-11 20:59:00
    linux内核内存管理中有一个2.6内核才加入的并不很张扬的结构体,那就是pagevec: struct pagevec {  unsigned long nr;  unsigned long cold;  struct page *pages[14];...
  • 什么是内存泄漏:程序向系统申请内存,使用完不需要之后,不释放内存还给系统回收,造成申请的内存被浪费.发现系统中内存使用量随着时间的流逝,消耗的越来越多,例如下图所示:接下来的排查思路是:...
  • 张诗明: Linux内核内存压缩技术

    千次阅读 2017-12-11 00:00:00
    2017年12月9号,来自四十多家公司的60多位一线工程师和国内众多Linux大咖在深圳绽放花园欢聚一堂,就Linux调度器演进,内核内存压缩技术,RISC-V三个主题展开了深入的讨论和思维的碰撞。这是张诗明《郭健: Linux内核...
  • 浅析linux内核内存管理之PAE

    千次阅读 2012-04-15 20:12:42
    浅析linux内核内存管理之PAE    早期Intel处理器从80386到Pentium使用32位物理地址,理论上,这样可以访问4GB的RAM。然而,大型服务器需要大于4GB的RAM来同时运行数以千计的进程,近几年来这对Intel造成...
  • linux内核中没有分页内存

    千次阅读 2010-02-09 22:10:00
    linux内核中没有分页内存吗?是的,没有,那么windows的内核为何就有呢?毕竟不是一个家族不好做全方位的评判,我的结论就是linux上的任何的程序只将内核作为一个平台而不依赖内核。这个事实的结果就是在linux内核中...
  • Linux内核内存分配函数

    千次阅读 2012-11-23 09:58:53
    kmalloc():如果需要连续的物理页,可以使用此函数,这是内核内存分配的常用方式,也是大多数情况下应该使用的内存分配方式。传递给函数的最常用的标志是GTP_ATOMIC和GTP_KERNEL。前面的标志表示进行不睡眠的高...
  • 日期 ... Linux内存管理 在内核初始化完成之后, 内存管理的责任就由伙伴系统来承担. 伙伴系统基于一种相对简单然而令人吃惊的强大算法.Linux内核使用二进制伙伴算法来管理和分配物理内存页面, 该算
  • 查看Linux内核、cpu、内存等信息

    千次阅读 2014-09-16 09:13:26
    1、查看系统内核版本命令 uname命令 uname -a uname -r uname -v  vim /proc/version more /etc/*release more /etc/issue 2、查看cpu信息 more /proc/cpuinfo 3、查看cpu位数 getconf LONG_BIT ls / 如果...
  • Kasan - Linux 内核内存检测工具

    千次阅读 2017-02-20 00:37:33
    Kernel address sanitizer (Kasan) 是一款随 Linux 内核代码一同发布和维护的内存检测工具,由内核社区维护和发展。本文简要介绍 Kasan 的原理及使用方法。它是一个动态检测内存错误的工具,主要功能是检查内存越界...
  • Linux 驱动之内核空间分配内存

    千次阅读 2015-05-29 10:18:25
    学c语言的时候应该学过,从用户空间看,每个进程都傻乎乎的以为自己有4G的内存空间,其中位于高地址(3G-4G)的1G空间给内核用,另外的3G(0-3G)都是它一个人独占的。所以用户空间很慷慨的把3G的空间分了好几个区域...
  • Linux 内核访问用户空间内存

    千次阅读 2017-05-25 15:22:00
    Linux 中,用户内存内核内存是独立的,在各自的地址空间实现。地址空间是虚拟的,就是说地址是从物理内存中抽象出来的(通过一个简短描述的过程)。由于地址空间是虚拟的,所以可以存在很多。事实上,内核本身...
  • 罗玉平: ARMv8 Linux内核内存屏障

    千次阅读 2017-12-06 00:00:00
    来自20个多家公司的50多位一线工程师于12月3号在上海泰兴路99号张园内的一个咖啡厅欢聚一堂,围绕ROS、移动GPU、ARM 内存屏障以及机器学习这四个热门主题展开...这是《罗玉平: ARMv8 Linux内核内存屏障》演讲slides。

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 370,791
精华内容 148,316
关键字:

linux查看内存内核

linux 订阅