`
wx1569063608
  • 浏览: 22629 次
文章分类
社区版块
存档分类
最新评论

Linux基础篇之内存管理机制

 
阅读更多

转载这篇文章之前,先区分下缓存和缓冲的区别,

缓冲和缓存都是RAM中的数据。简单来说,buffer是即将要写入磁盘的数据,而cache是从磁盘中读取数据的。buffer是由各种进程分配的,被用在如输入队列等方面,一个简单的例子如某个进程要求有多个字段读入,在所有字段 被读入完整之前,进程把先前读入的字段放在buffer中保存。cache经常被用在磁盘的I/O请求上,如果有多个进程都要访问某个文件,于是该文件便被做成cache以方便下次被访问,这样可以提高系统性能。

1 Linux内存管理的主要特点

--------------------------------------------------------------------------------
无论物理内存多大,Linux都将其充分利用,将一些程序调用过的硬盘数据读入内存,利用内存读写的高速特性来提高Linux系统的数据访问性能。而Windows是只在需要内存时,才为应用程序分配内存,并不能充分利用大容量的内存空间。Linux的这一特性,主要是利用空闲的物理内存,划分出一部份空间,做为cache、buffers,以此提高数据访问性能。页面高速缓存(page cache)是Linux内核实现的一种主要磁盘缓存。它主要用来减少对磁盘的I/O操作。具体地讲,是通过把磁盘中的数据缓存到物理内存中,把对磁盘的访问变为对物理内存的访问。

2 物理内存、虚拟内存

--------------------------------------------------------------------------------
物理内存就是系统硬件提供的内存大小,是真正的内存,相对于物理内存,在Linux下还有一个虚拟内存的概念,虚拟内存就是为了满足物理内存的不足而提出的策略,它是利用磁盘空间虚拟出的一块逻辑内存,用作虚拟内存的磁盘空间被称为交换空间(Swap Space)。
Linux的内存管理采取的是分页存取机制,为了保证物理内存能得到充分的利用,内核会在适当的时候将物理内存中不经常使用的数据块自动交换到虚拟内存中,而将经常使用的信息保留到物理内存。


Linux内存运行机制:
2.1 Linux系统会不时的进行页面交换操作,以保持尽可能多的空闲物理内存
2.2 Linux进行页面交换是有条件的,不是所有页面在不用时都交换到虚拟内存,Linux内核根据”最近最经常使用“算法,仅仅将一些不经常使用的页面文件交换到虚拟内存
2.3 交换空间的页面在使用时会首先被交换到物理内存,如果此时没有足够的物理内存来容纳这些页面,它们又会被马上交换出去

3 Linux内存监控

--------------------------------------------------------------------------------
free -m:
[root@rango  backup_CentOS]# free -m 
            total      used      free    shared    buffers    cached 
Mem:          3805      3683      121          0        120        690 
-/+ buffers/cache:      2872      932 
Swap:        2041        134      1907
注解:
total:    物理内存的总大小used:已经使用的物理内存大小free:空闲的物理内存大小
shared:    多个进程共享的内存大小buffers/cached:磁盘缓存的大小
Mem:    代表物理内存使用情况(-/+buffers/cached):代表磁盘缓存使用状态
Swap:    表示交换空间内存使用状态
(-buffers/cache) used内存数:2872M(指的第一部分Mem行中的used- buffers - cached)
(+buffers/cache) free内存数:  932M (指的第一部分Mem行中的free+ buffers + cached)
从内核的角度可使用的内存:121M
从应用程序可使用的内存:free+buffers/cache=121+120+690=931M,为第二行的free值。对于应用程序来说,buffers/cached占有的内存是可用的,因为buffers/cached是为了提高文件读取的性能,当应用程序需要用到内存的时候,buffers/cached会很快地被回收,以供应用程序使用。


Linux缓存机制:buffers与cached都是内存操作,用来保存系统曾经打开过的文件以及文件属性信息,这样当操作系统需要读取某些文件时,会首先在buffers与cached内存区查找,如果找到,直接读出传送给应用程序,如果没有找到需要数据,才从磁盘读取。
buffers是用来缓冲块设备做的,它只记录文件系统的元数据(metadata)以及tracking in-flightpages,而cached是用来给文件做缓冲。更通俗一点说:buffers主要用来存放目录里面有什么内容,文件的属性以及权限等等。而cached直接用来记忆我们打开过的文件和程序。

4  Linux内存释放过程

--------------------------------------------------------------------------------
4.1 free -m查看内存使用情况


4.2 sync:使用sync命令以确保文件系统的完整性,sync命令运行sync 子例程,将所有未写的系统缓冲区写到磁盘中,包含已修改的i-node、已延迟的块I/O和读写映射文件。为确保可靠起见,应执行两遍sync命令,这是因为sync命令完成时,并不保证信息实际写到了磁盘上。


4.3 修改/proc/sys/vm/drop_caches:
echo 3 > /proc/sys/vm/drop_caches
说明:
1)/proc是一个虚拟文件系统,我们可以通过对它的读写操作作为与kernel实体间进行通信的一种手段。也就是说可以通过修改/proc中的文件,来对当前kernel的行为做出调整。也就是说我们可以通过调整/proc/sys/vm/drop_caches来释放内存。
2)drop_caches:
Writing to this file causes the kernel to drop cleancaches,dentries and inodes from memory, causing that memory tobecomefree.
To free pagecache, use echo 1 > /proc/sys/vm/drop_caches;
to free dentries and inodes, use echo 2 >/proc/sys/vm/drop_caches;
to free pagecache, dentries and inodes, use echo 3>/proc/sys/vm/drop_caches.
Because this is a non-destructive operation and dirty objects arenot freeable, the user should run syncfirst.

5 Linux内存映射

--------------------------------------------------------------------------------
当可执行文件准备运行时,可执行文件的内容仅仅映射到了对应进程虚拟地址空间中,而并没有调入物理内存。当程序开始运行并使用到这部分时,Linux才通过缺页中断把它们从磁盘上调入内存。这种将文件连接到进程虚拟地址空间的过程称为内存映射。
一般情况下,用户空间是不可能也不应该直接访问设备的,但是,设备驱动程序中可实现mmap()函数,这个函数可使得用户空间能直接访问设备的物理地址。实际上,mmap()实现了这样的一个映射过程,它将用户空间的一段内存与设备内存关联,当用户访问用户空间的这段地址范围时,实际上会转化为对设备的访问。
当用户调用mmap()的时候,内核会进行如下的处理:
① 在进程的虚拟空间查找一块VMA。
② 将这块VMA进行映射。
③ 如果设备驱动程序或者文件系统的file_operations定义了mmap()操作,则调用它。
④ 将这个VMA插入进程的VMA链表中。
vma包含了用于访问设备的虚拟地址的信息,因此大量的工作由内核完成。为了执行mmap,驱动程序只需要为该地址返回建立合适的页表,并将vma->vm_ops替换为一系列的新操作就可以了。

6 Linux共享内存

--------------------------------------------------------------------------------
6.1 共享内存

--------------------------------------------------------------------------------
共享内存可以说是最有用的进程间通信方式,也是最快的IPC形式。两个不同进程A、B共享内存的意思是,同一块物理内存被映射到进程A、B各自的进程地址空间。进程A可以即时看到进程B对共享内存中数据的更新,反之亦然。由于多个进程共享同一块内存区域,必然需要某种同步机制,互斥锁和信号量都可以。

采用共享内存通信的一个显而易见的好处是效率高,因为进程可以直接读写内存,而不需要任何数据的拷贝。对于像管道和消息队列等通信方式,则需要在内核和用户空间进行四次的数据拷贝,而共享内存则只拷贝两次数据:一次从输入文件到共享内存区,另一次从共享内存区到输出文件。实际上,进程之间在共享内存时,并不总是读写少量数据后就解除映射,有新的通信时,再重新建立共享内存区域。而是保持共享区域,直到通信完毕为止,这样,数据内容一直保存在共享内存中,并没有写回文件。共享内存中的内容往往是在解除映射时才写回文件的。因此,采用共享内存的通信方式效率是非常高的。

6.2 共享内存的释放

--------------------------------------------------------------------------------
在使用共享内存的程序异常退出时,由于没有释放掉共享内存,在调试时会出现错误。
释放共享内存的方法:
1)如果总是通过Crtl+C来结束的话,可以做一个信号处理器,当接收到这个信号的时候,先释放共享内存,然后退出程序。
2)通过linux命令ipcrm shm shmid来释放,在使用该命令之前可以通过ipcs -m命令来查看共享内存。
查看共享内存:ipcs -m          -m只显示共享内存信息,-q只显示消息队列,-s只显示信号量
[root@rango  backup_CentOS]# ipcs -m


------ Shared Memory Segments -------- 
key        shmid      owner      perms    bytes      nattch    status      
0x00000000 98304      rango      600      393216    2          dest        
0x00000000 131073    rango      600      393216    2          dest        
0x00000000 163842    rango      600      393216    2          dest        
0x00000000 196611    rango      600      393216    2          dest        
0x00000000 229380    rango      600      393216    2          dest        
0x00000000 262149    rango      600      393216    2          dest        
0x00000000 294918    rango      600      393216    2          dest        
0x00000000 327687    rango      600      393216    2          dest        
0x00000000 360456    rango      600      393216    2          dest
第一列就是共享内存的key;        第二列是共享内存的编号shmid;
第三列就是创建的用户owner;    第四列就是权限perms;
第五列为创建的大小bytes;        第六列为连接到共享内存的进程数nattach;
第七列是共享内存的状态status。其中显示“dest”表示共享内存段已经被删除,但是还有用户在使用它,当该段内存的mode字段设置为SHM_DEST时就会显示“dest”。当用户调用shmctl的IPC_RMID时,内存先查看多少个进程与这个内存关联着,如果关联数为0,就会销毁这段共享内存,否者设置这段内存的mod的mode位为SHM_DEST,如果所有进程都不用则删除这段共享内存。


释放共享内存:ipcrm <shmid>  #释放单个共享内存
ipcs -m | awk ‘$2 ~/[0-9]+/ {print$2}’ | while read s; do sudo ipcrm –m $s; done  #释放所有共享内存
ps:释放共享内存的python脚本

rmsharemem.py
#!/usr/bin/env python 
# Description: Remove the share memory 
# Author: RangoChen 
# Date: 2013.12.19
# -*- coding: utf-8 -*-
# Remove the share memory
import os
import sys
import getopt

 

def usage():
  print "usage: python rmsharemem.py -h -o <owner> -ssize <shmid list>"
  print " -h show help information"
  print " -o <owner> the owner create share memory needto delete"
  print " -s <size> the share memory size"
  print " <shmid list> the shmid list need to delete"

 

def getsharemem():
  sharemap = {}
  fp = os.popen('ipcs -m')
  lines = fp.readlines()
  for l in lines:
      if not l.startswith('0x'):
          continue
  s = l.split()
  if sharemap.has_key(s[2]):
      sharemap[s[2]].append(s)
  else:
        sharemap[s[2]] = [s]
  #print 'Share memory map:\n', sharemap
return sharemap

 

if __name__ == "__main__":
  opts, args = getopt.getopt(sys.argv[1:], "o:hs:")
    # opts is the parameter with options
  # args is the parameter no ptions
    owner = None
    size = 0
  for o, p in opts:
      if o == '-h':
      usage()
      sys.exit(0)
  elif o == '-o':
      owner = p
  elif o == '-s':
      size = p

 

if not owner:
  val = raw_input("Are you sure to remove all sharememory?(yes/no)")
  if (val == "yes"):
      usage()
      sys.exit(0)

 

count = 0
total = 0
if len(args) > 0:
    for shmid in args:
        cmd = 'ipcrm -m %s' % shmid
      print 'execute command: %s' % cmd
        ret = os.system(cmd)
        total += 1
      if ret == 0:
            count += 1
            print 'remove %s shared memory success' % shmid
      else:
          print 'remove %s shared memory failed' % shmid
  else:
      shmmap = getsharemem()
      for o, l in shmmap.items():
          if owner and o == owner:
              continue
      for p in l:
            total += 1
            if size and size == p[4]:
                continue
          cmd = 'ipcrm -m %s' % p[1]
          print 'execute command: %s' % cmd
          ret = os.system(cmd)
          if ret == 0:
                count += 1
              print 'remove %s shared memory success' % p[1]
          else:
              print 'remove %s shared memory failed' % p[1]
print 'total share memory number = %s' % total
print 'remove success number = %s' % count
sys.exit(0)

6.3 共享内存大小的修改

--------------------------------------------------------------------------------
查看共享内存的大小:cat    /proc/sys/kernel/shmmax
临时修改:echo 268435456 > /proc/sys/kernel/shmmax#把共享内存大小设置为256MB;
永久修改:vim /etc/rc.d/rc.local:  echo 268435456 > /proc/sys/kernel/shmmax
即可每次启动时把共享内存修改为256MB.


7 总结

--------------------------------------------------------------------------------
此文介绍了Linux内存管理机制,包括内存映射、共享内存的实现机制等。

 

以上部分为转载的其他的文章,下面列举下linux中常用的一些进程管理的命令:

ps aux:查看系统的所有进程数据

ps: Process State
 SysV风格:-
 BSD风格:
 
 a: 所有与终端有关的进程
 u:
 x: 所有与终端无关的进程
 
进程的分类:
 跟终端相关的进程
 跟终端无关的进程

进程状态:
 D:不可中断的睡眠
 R:运行或就绪
 S:可中断的睡眠
 T:停止
 Z:僵死
 
 <:高优先级进程
 N: 低优先级进程
 +:前台进程组中的进程
 l: 多线程进程
 s: 会话进程首进程

ps 
 -elF
 -ef
 -eF

ps -o PROPERTY1,PROPERTY2

ps -o pid,comm,ni

pstree: 显示当前系统上的进程树

pgrep:
pidof: 根据程序名称,查找其相关进程的ID号;

top:动态的查看进程的变化

top:
 M: 根据驻留内存大小进行排序
 P:根据CPU使用百分比进行排序
 T: 根据累计时间进行排序
 
 l: 是否显示平均负载和启动时间
 t: 是否显示进程和CPU状态相关信息
 m: 是否显示内存相关信息
 
 c: 是否显示完整的命令行信息
 q: 退出top
 k: 终止某个进程

top
 -d: 指定延迟时长,单位是秒
 -b: 批模式
 -n #:在批模式下,共显示多少批

进程的信号传递kill

kill -signal PID

killall -signal 【command name】

进程的执行顺序

nice:新执行的命令即给予新的nice值

nice -n 数字 command

已存在的进程的nice值的调整

renice 【number】 PID

系统资源的查看

查看与内存相关的信息:free -m

查看与内核相关的信息: uname -a

查看系统启动时间与工作负载:uptime

跟踪网络:netstat -tunlp 或者netstat -a

分析内核产生的信息:dmesg

检测系统资源变化:vmstat

找出某个正在进行的进程的PID:pidof

通过文件(或文件系统)找出正在使用该文件的程序fuser

列出被进程所打开的文件名:lsof

转载于:https://my.oschina.net/alfredliukai/blog/509614

分享到:
评论

相关推荐

    Linux管理之内存篇

    在Linux系统管理中,内存是至关重要的组成部分,它关乎到系统的性能、稳定性和响应速度。本文将深入探讨Linux管理之内的内存...而通过学习Linux内核源码,可以更深入地理解内存管理机制,对于系统调优具有重要意义。

    深入理解Linux内存管理

    物理内存描述部分是理解内存管理机制的基础。这部分详细解释了Linux如何组织和管理物理内存。 - **节点**:多处理器系统中,内存可以分布在不同的节点上,每个节点都拥有自己的内存资源。 - **区**:为了更高效地...

    00-Linux内存管理之一:基本概念篇.rar

    在IT领域,Linux操作系统是广泛使用的开源系统,其内存管理机制是系统性能的关键因素。本文将深入探讨"00-Linux内存管理之一:基本概念篇"中的核心知识点,旨在为读者提供一个全面的理解。 首先,我们需要理解Linux...

    Linux内存管理笔记.doc

    Linux操作系统的内存管理机制是一个复杂的系统,它包括段式管理和页式管理两种机制。段式管理用于将逻辑地址转换成线性地址,而页式管理用于将线性地址转换成物理地址。 在Linux操作系统中,虚拟内存是一个非常重要...

    Linux基础-系统概论篇

    ### Linux基础-系统概论篇 #### Linux简介 Linux 是一款功能强大且广泛使用的操作系统,其设计理念深受 Unix 影响但并非 Unix 的衍生版本。它以其免费、开源、安全、高效、稳定等特点著称,特别是在处理高并发能力...

    鸟哥的Linux_私房菜--基础文件.pdf

    ### Linux 操作系统基础知识 #### 一、操作系统概念解析 要深入理解《鸟哥的Linux私房菜——...通过学习本书,读者不仅可以掌握Linux的基础知识,还能深入了解Linux的内部机制,为进一步探索高级主题打下坚实的基础。

    Artix Microblaze两篇基础篇高级 篇

    《Artix Microblaze两篇基础篇高级篇》是一份深度探讨Microblaze技术的教程,专注于在Xilinx Artix FPGA系列芯片上实现嵌入式处理系统。Microblaze是Xilinx公司推出的一种软核处理器,它允许用户根据具体需求自定义...

    linux内核学习笔记(2)——内存寻址

    Linux内核通过页表机制实现虚拟地址到物理地址的映射,这是内存管理的基础。 页表是由一系列的页表项组成,每个页表项指向一个内存页,即4KB的物理内存块。在32位系统中,虚拟地址由两部分组成:页目录索引和页表...

    探讨Android内存管理

    Android 内存管理机制 如何评估 App 的内存占用 一些减少 App 内存占用的建议 内存管理概述 Android 运行时 (ART) 和 Dalvik 虚拟机使用分页和内存映射来管理内存。这意味着应用修改的任何内存,无论修改的方式是...

    裁剪Linux内核屏蔽页面交换机制的研究与实现.pdf

    《裁剪Linux内核屏蔽页面交换机制的研究与实现》这篇论文主要探讨了在特定场景下,如何修改Linux操作系统内核以禁用页面交换机制,以适应实时系统的需求。页面交换是Linux内存管理的关键技术,它允许系统将不常用的...

    linux 内核(arm).rar

    此外,ARM处理器的中断处理机制、异常处理以及内存管理单元(MMU)的工作方式也是内核需要考虑的关键点。 Linux内核的配置和编译是学习过程中的重要环节。通过配置工具make menuconfig,我们可以选择内核要支持的...

    深度剖析linux内核

    本篇文章将深入探讨“深度剖析Linux内核”这一主题,涵盖内核启动流程、内核组成部分、进程调度、内存管理和驱动程序等方面。 首先,让我们来看看Linux内核的启动流程。当计算机加电后,BIOS会执行基本输入输出系统...

    Linux_c++_编程之链接与装载--基础篇

    这篇基础篇将探讨这两个概念,帮助开发者深入理解程序是如何从源代码转变为可执行文件,并最终在系统中运行的。 首先,我们要了解什么是链接。链接是将编译后的目标文件(.o文件)合并成一个单一可执行文件的过程。...

    操作系统原理-Linux篇

    内存管理是操作系统的关键功能之一。Linux采用分页和分段技术管理内存,实现了虚拟内存,使得程序可以使用超过物理内存的地址空间。同时,Linux内核还实现了内存交换机制,将不活跃的数据暂时存放到硬盘上,以释放...

    文件系统驱动编程基础篇

    "文件系统驱动编程基础篇之八——安全机制"可能涵盖驱动程序的安全策略,如权限管理、内存保护和异常处理,确保驱动稳定且不易被攻击。 "文件系统驱动编程基础篇之九——文件分配表"深入剖析了文件分配表(FAT)的...

Global site tag (gtag.js) - Google Analytics