《linux内核精髓》-记录-资源管理

《linux内核精髓》-记录-资源管理

资源管理

资源管理

本节主要内容:通过cgroup和namespace实现容器功能

容器

cgroup:

cgroup是将任意进程进行分组化管理的linux内核功能。cgroup本身提供将进程进行分组化管理的功能和接口的基础结构,I/O或内存的分配控制等具体资源管理通过这个功能来实现。这些资源管理功能称为cgroup子系统或控制器。

  • cgroup子系统有内存的memory控制器、控制进程调度的cpu控制器。由/proc/cgroup确定内核可以使用的cgroup子系统。
  • cgroup提供一个cgroup虚拟文件系统,作为分组管理和子系统设置的用户接口。(虚拟文件系统指不具有物理设备的文件系统。)
  • 文件名前缀为cgroup及没有前缀的文件由cgroup的基础结构提供的特殊文件。前缀为debug的文件由debug子系统提供的特殊文件。特殊文件分为只读和可读写两种。最重要的是tasks特殊文件(tasks文件记录线程id)。
  • tasks中包含shell的TID(也是pid,即进程ID)
文件名 r/w 用途
release_agent rw 删除分组时执行的命令。这个文件只存在于根分组
notify_on_release rw 设置是否执行release_agent。为1时执行
tasks rw 属于分组的线程TID列表
cgroup.procs r 属于分组的进程PID列表。仅包括多线程进程的线程leader的TID,与tasks不同
cgroup.event_control rw 监视状态变化和分组删除事件的配置文件

实际使用cgroup时,应将线程添加到分组后,在分组内的特殊文件中设置值,来控制系统的运行。

namespace

namespace,可以让每个进程组拥有独立的PID、IPC和网络空间。

名称 说明
clone_newipc 划分IPC(进程间通信)命名空间。信号量(semaphre)、共享内存、消息队列等进程间通信资源
clone_newnet 划分网络命名空间、分配网络接口
clone_newns 划分挂载命名空间,与chroot同样分配新的根文件系统
clone_newpid 划分PID命名空间,分配新的进程ID空间
clone_newuts 划分UTS命名空间,分配新的UTS空间

LXC(linux container) linux容器,在启动lxc之前必须启用cgroup文件系统,挂在cgroup文件系统。

mount -t cgroup cgroup/cgroup

创建根目录,挂载如:lib、etc、bin等目录。
创建网络,创建用来连接分配到容器的网络接口的网桥。
之后可以通过lxc启动容器

调度策略

本部分主要内容: linux调度策略

调度策略

调度策略可以分为TSS(time sharing system,分时系统)和实时系统两种。

  • 一般进程通过分时运行,通过时间片的方式,将cpu分配给各个进程。
  • 实时调度策略适合优先级要求很高的进程。相比于TSS调度策略。cpu将优先分配给实时调度策略的进程。

linxu 进程静态优先级为0-99。TSS调度策略优先级为0,实时调度策略优先级为1-99.

  • TSS调度策略有动态优先级。长时间持续使用cpu进程,其动态优先级会逐渐降低。优先级更高更容易分配到cpu。
  • linux的五种调度策略:sched_other、sched_fifo、sched_rr、sched_batch、sched_idle。
    • sched_other: 标准调度策略,也是TSS分时系统调度策略,2.6.23之前时间片由优先级决定。
    • sched_fifo: 实时调度策略,优先级指定为1-99,除等待i/io完成时休眠、自发休眠或优先级更高的实时进程获得优先权外,不会释放执行权。经常不会主动释放cpu。
    • sched_rr: 也是实时调度策略,与sched_fifo不同的是,它具有时间片,时间片使用完后会转移到其他进程。时间片固定值100毫秒
    • sched_batch: 此策略不会根据休眠时间更改优先级,不能作为会话调度策略。使用了此策略的进程会被识别为0的cpu bound进程。因此,优先级必然会比会话型shell进程低。对非会话型进程使用这个调度策略,可以使会话保持高优先级,保持应答。
    • sched_IDLE: cpu空闲时,即sched_idle等级以外处于可执行状态的进程消失时,将被赋予执行权,它将成为优先级最低的进程。
    • 特殊标志:sched_reset_on_fork 为限制实时调度策略,为调度策略添加标志flag。在执行fork()时,新生成的子进程就称为sched_other策略的进程。
  • 关于调度策略的系统调用
    sched_setscheduler() 更改调度策略和进程优先级
    sched_getscheduler() 获取当前调度策略与进程优先级
    sched_setparam()  更改调度参数(进程优先级)
    sched_getparam() 获取当前调度参数
    sched_get_priority_max() 获取调度策略的进程静态优先级范围 
    sched_get_priority_min() 获取调度策略的进程静态优先级范围
    sched_rr_get_interval() 获取当前时间片
    
  • chart命令
    • chart命令可以简单更改调度策略。
    • 更改实时调度策略必须具有root权限。

RT group scheduling 与 RT Throttling

本节主要内容: 对实时进程所使用的cpu时间进行限制的功能RT group scheduling和RT Throttling.
在内核2.6.25后的版本中加入此功能。
实时调度策略哟静态优先级,调度优先级比其他一般进程高,需要执行时一定会分配cpu时间。如果实时进程陷入无限循环,就会造成系统卡死。
该功能通过是实现限制实时进程的cpu时间使执行权在实时进程无限循环的情况下也能切换到其他进程,避免系统死机。

  • 实时
    • 实时功能的目的使实现满足实时限制的处理。在有限时间内得到处理结果。即使内核运行过程中,也能迅速切换到要处理事件的进程。内核内部设置了优先权点(reemption point),可以根据事件立刻切换到实时进程。
    • 要求实时性的处理,如图形处理。分配时间提高吞吐量的目的和实时的目的是不同的。
  • RT Throtting
    • 通过限制分配给实时进程的每个单位时间的cpu时间,就可以防止实时调度策略 进程出现bug导致系统死机。
    • 可以指定单位时间内分配多少cpu时间给实时进程。标准设置为1秒,cpu分配时间是0.95秒,非实时进程1秒可以使用cpu0.05秒。
    • 实时:在一定时间内完成处理。
    • 整个系统的cpu时间可以使用sysctl来获取、设置。
    • 当CONFIG_RT_GROUP_SCHED有效时,受到cgroup设置值的限制,不能设置与cgroup的有效值相矛盾的设置。将sched_rt_runtime_us设置为-1,是用来使RT Throttling失效的设置。
    • sysctl的设置仅用于有效与无效的切换,单个设置使用cgroup进行。RT group scheuling是cgroup的子系统。要使用RT Group Scheduling,必须启用CONFIG_RT_GROUP_SCHED。
    cpu_rt_period_us 单位时间
    cpu_rt_runtime_us 分配时间
    

Fair Group Scheduling

本节内容: cgroup之管理cpu资源的Fair group scheduling。

  • fair group scheduling
    • 是cgroup资源管理器之一,用来控制linux内核的进程调度程序进行cpu时间分配。可以对每个特定进程组进行资源管理。
    • Fair Group scheduling 使用的是linux2.6.23之后引入的cfs的cpu时间分配控制功能。
    • 需要挂载cgroup文件系统。挂载时需要启用cpu资源控制。
    • cpu.shares特殊文件,可以对进程调度程序所处理的进程组设置cpu时间分配的比重。通过修改这个值,可以调整cpu时间比例。默认1024.
    • 能以进程组为单位控制cpu资源分配。

cpuset

本节内容:控制物理cpu分配的cpuset
cpuset时linux控制组cgroup之一,其功能指定特定的进程或线程所使用的cpu组。还能指定内存节点的分配。

  • 用法
    • 使用cpuset前,必须通过内核config启用cpuset功能。最近的发布版本在标准中已启用。
    • 也需要挂载cgroup。通过向cpuset.cpus特殊文件写入要分配的cpu编号控制分组。之后往task特殊文件中添加pid($$表示shell本身的pid)。此后shell启动的进程全部在这个组下,使用的cpu为cpuset.cpus中的cpu。
      通过固定使用cpu,可以提高缓存的利用效率和性能。

使用memory cgroup限制内存使用量

memory cgroup 是cgroup之一,用来控制进程所使用的内存(lru管理的缓存)数量。

  • memory cgroup

    • 控制进程使用的内存数量,避免因处理大文件或大量文件导致页面缓存增大,内存资源紧张,可在多用户环境中限制各用户可以使用的的内存量。
    • memory cgroup 是 cgroup的一种,因此必须挂载cgroup系统。
  • 用法

    文件名 说明
    memory.usage_in_bytes 显示当前内存(进程内存+页面缓存)的使用量
    memory.memsw.usage_in_bytes 显示当前内存(进程内存+页面缓存)+交换区使用量
    memory.limit_in_bytes 设置、显示内存(进程内存+页面缓存) 使用量的限制值
    memory.memsw.limit_in_bytes 设置、显示内存(进程内存+页面缓存)+交换区使用量的限制
    memory.falicnt 显示内存(进程内存+页面缓存) 达到限制的次数
    memory.memsw.failcnt 显示内存(进程内存+页面缓存) +交换区达到限制值的次数
    memory.max_usage_in_bytes 显示记录的内存(进程内存+页面缓存)使用量的最大值
    memory.memsw.max_usage_in_bytes 显示记录的内存(进程内存+页面缓存)+交换区使用量的最大值
    memory.stat 输出统计信息
    memory.force_empty 强制释放分配给分组的内容
    memory.use_hierarchy 设置、显示层次结构的使用
    memory.swappiness 设置、显示针对分组的swappiness(相当于sysctl的vm.swappiness)
  • 限制内存使用量
    内存使用量可以使用memory.limit_in_bytes进行限制。

    echo 10M > /cgroup/groupa/memory.limit_in_bytes
    
  • 层次结构
    通过Memory cgroup控制的分组可以采用层次结构。可以在memory.use_hierarchy中写入1,启用分组的层次结构。

    echo 1 > /cgroup/memory.use_hierarchy
    
  • 显示统计信息
    关于各分组内存使用量信息可以从memory.stat文件读取

    名称 说明
    cache 页面缓存量(字节数)
    rss 匿名页面与交换区缓存的内存量(字节数)
    mappend_file 指向进程空间的文件映射所使用的内存量(字节数)
    pgpgin 页面换入次数
    pgpgout 页面换出次数
    swap 交换区使用量(字节数)
    inactive_anon LRU列表中无效的匿名页面(字节数)
    active_anon LRU列表中有效的匿名页面(字节数)
    inactive_file LRU列表中无效的文件缓存(字节数)
    active_file LRU列表中有效的文件缓存(字节数)
    unevictable 不能用mlock等回收的内存量(字节数)

    下列内容在使用层次结构时有效,将显示层次结构的上层的分组限制值。

    名称 说明
    hierarchical_memory_limit 上层分组对内存(进程内存+页面缓存)的限制值
    hierarchical_memsw_limit 上层分组对内存(进程内存+页面缓存)+交换区的限制值

    层次结构分组下的合计值

    名称 说明
    total_cache 本分组下所有页面缓存量(字节数)的合计值
    total_rss 本分组下所有匿名页与交换区缓存内存量(字节数)的合计值
    total_mappend_files 本分组下所有指向进程空间的文件映射所使用的内存量(字节数)的合计值
    total_pgpgin 本分组下所有页面换入次数的合计值
    total_pgpgout 本分组下所有页面换出次数的合计值
    total_swap 本分组下所有交换区使用量(字节数)的合计值
    total_inactive_anon 本分组下所有LRU列表中无效的匿名页面(字节数)的合计值
    total_active_anon 本分组下所有LRU列表中有效的匿名页面(字节数)的合计值
    total_inactive_file 本分组下所有LRU列表中无效的文件缓存(字节数)的合计值
    total_active_file 本分组下所有LRU列表中有效的文件缓存(字节数)的合计值
    total_unevictable 本分组下所有不能用molock等回收的内存量(字节数)的合计值

使用block I/O控制器设置I/O优先级

本节主要内容: 通过block I/O控制将进程分组,并对该分组设置I/O的优先级。

  • 使用Block I/O控制器的前提条件

    • block I/O时cgroup的子系统之一,时作为I/O调度程序之一的CFQ的一部分安装。使用Block I/O控制器时,必须使用启用了config选型编译的内核。
    • 如果有/proc/cgroups,运行中的内核就可以支持cgroup。文件中显示了blkio,且enbable为1则表示支持并开启。内核参数为 cgroup_disable=blkio
    • 确认CFQ作为I/O调度程序使用。
    cat /sys/class/block/sdb/queue/scheduler
    
    • I/O调度程序时对一般块设备使用的,比如:loopback设备loop0不会显示cfq,sda、sdb等一般块设备才可能显示。
  • 尝试使用Blocki/O控制器

    • 控制器通过cgroup文件系统进行,需要先噶在blkio作为子系统使用。
    • blkio.weigh中写入范围在100-1000的Weight值。初始值为500,值越大表示优先级越高。仅根分组的weight初始值为1000。
  • Block I/O控制器提供的的特殊文件

    文件名 r/w 用途
    blkio.wight rw 设置分组weight值的文件。weight值可以设置100-1000.weight越大,优先级越高
    blkio.weight_device rw 按照<设备主号码>:<设备副号码><weight值>的格式
    blkio.io_merged r 合并的I/O数
    blkio.io_queued r 当前保留的I/O数
    blkio.io_service_bytes r I/O请求总字节数
    blkio.io_serviced r I/O请求数
    blkio.io_service_time r 从I/O亲求设备到完成所花费的总时间,单位为纳秒
    blkio.io_wait_time r I/O亲求到达设备之前保留在等待队列的总时间。单位为纳秒
    blkio.reset_stats w 写入后,统计信息被清除
    blkio.sectors r I/O请求的总扇区数
    blkio.time r 目前为止分配给分组的时间片的长度,单位为纳秒

    I/O合并是指将应用程序发出的多个I/O请求合并为1个。提高I/O处理效率。

  • 关于Block I/O控制器的CFQ设置用虚拟文件

    • /sys/block//queue/iosched中CFQ的设置用虚拟文件,会对Block I/O控制器的运行产生影响。
    group_isolation   rw  用来设置在I/O性能和分组间优先级控制二者中优先切换到哪一个,为0时,为了实现I/O性能最大化,会适度降低一些分组优先级的兼容性
    
  • 限制事项

    • Block I/O控制器不支持非同步I/O,即支持初次读入和Direct I/O的读写。普通的写入经过页面缓存的非同步I/O,因此不属于优先级控制对象,都被看做根分组发出的I/O.
    • 不支持分组层次化,分组层次限制仅为1层,无法创建从根分组开始有两层次以上的分组。
    • 根分组与子分组作同等处理
    • block I/O 控制器对各分组的I/O请求分配时间片。仅允许各分组在这个时间片内执行I/O操作。分组的weight值越大,时间片越长,通过这个方式来指定分组间的优先级。
    • block I/O 控制器只有在针对设备的I/O发生竞争时,才根据优先级对I/O进行控制。

虚拟子系统存储的调整

主要内容: 使用/proc进行虚拟存储子系统的调整

  • 虚拟空间存储方式
    在linux上分配内存时,通过页面为单位的虚拟存储方式进行。可以不用担心内存碎片。
    • 程序使用的页面是在应用程序最初访问时由内核分配的。
    • 如果分配的页面为程序文本、有初始值的数据(.data)区域或(被mmap的)数据文件区域,则在页面分配的同时从对应的文件读取数据,页面通过这些数据初始化。
    • 如果不存在初始值的数据区域,则只进行页面分配处理。这种页面作为匿名(anonymous)页面处理。
    • 通过malloc()等分配可用的存储区时,不会离开向该区域(空间)分配实际的页面。而是在必要的时候分配需要用到的页面。
    • 多数应用程序一般都不会使用分配的所有存储区。有分配最大数据量大小相等的缓冲区以及散列表这种没有实体的空间。使用虚拟存储方式就不需要向未使用的空间分配内存。
  • 虚拟空间超额使用量的调整
    可以使用ulimiti命令对进程的最大虚拟空间进行限制。
    • 在linux中有“允许超过物理内存量分配多少虚拟空间”的参数,通过:
    /proc/sys/vm/overcommit_memory  #控制虚拟空间分配策略的参数
    /proc/sys/vm/overcommit_ratio  #指定允许过量使用的虚拟空间占物理内存总量的百分比默认50%
    
    • overcommit_memory包含三种值:
    OVERCOMMIT_GUESS(0)    #默认  预测将空闲内存、页面缓存量、空闲交换区量、可回收slab(长字节)量等回收的页面数,虚拟空间要求分配的量比这个数小时,分配成功。多进程同时要求大量虚拟空间时无法正确预测的。可分配的虚拟空间大小基本是物理内存大小和交换分区大小的合计值。
    OVERCOMMIT_ALWAYS(1)   虚拟空间分配总是成功。
    OVERCOMMIT_NEVER(2)    会记录下整个系统内已分配的虚拟空间量。严格由系统管理,在分配和释放虚拟空间时重新计算。这个值为/proc/meminfo的Committed_AS
    
    • overcommit_guess的情况下,对mmap系统调用设置了map_noreserve的虚拟空间量不添加到committed_as种,overcommit_never会将map_noreserver添加到committed_as。
    • 所有物理内存量+总交换区量+通过/proc/sys/vm/overcommit_ratio指定的比例得到值,作为可分配虚拟空间总量。这个值在/proc/meminfo的commitLimit查看。commitLimit仅在利用overcommit_never时有效。在overcommit_guess、overcommit_always的情况下,这个项目没有意义。

ramzswap

主要内容: 将一部分内存作为交换设备使用的ramzswap。
将一部分内存空间作为交换设备使用的基于RAM的块设备。对要换出(swapout)的页面压缩后,写入内存。压缩使用LZO。运转速度高于一般磁盘设备。可以避免内存不足时,内存回收处理导致心能下降,或抑制oom Killer的运作。
在内存容量小,单cpu性能高的情况下可以提高性能

  • ramzswap disk的使用方法
    • 首先需要将用来压缩/解压缩数据的LZO模块按照到内核中。
    modprobe lzo_compress
    modprobe lzo_decompress
    
    对于没有静态安装到内核的情况下,可以使用 insmod ramzswap.ko进行安装。自己构建内核时,将config_lzo_decompress设置为y或m。 安装模块后,还需要对ramzswap设备进行初始化,启用交换功能。
  • backing swap的使用方法
    另一种使用方法:将部分内存作为ramzswap disk使用,再将交换文件或交换块设备作为backing swap使用。如果内存不足则仅使用ramzswap disk进行处理,如果内存更少,则页面的内容存放到backing swap中。
    • 默认为所有内存的大小的15%。设置为1024kb。内存使用量一旦增加,首先压缩的页会写入ramzswap disk区域。未压缩到50%以下的页面写入backing swap,超过--memlimit_kb选项的写入backing swap。

oom killer的运行于结构

out of Memory (oom) killer 作为确保内存的最终手段,可以再耗尽内存或交换区后,向进程发送终止信号,强制终止进程。即使再无法释放内存的情况下,也能重复进行确保内存的处理过程。

  • 进程的选定
    oom killer在内存耗尽时,会查看所有进程,斌分别未每个进程计算分数。将信号发送给分数最高的进程。
  • 计算分数的方法
    • 计算分数以进程虚拟内存大小为基准,虚拟内存大小可以使用ps命令的vsz或/proc//status的vmsize。对于正在消耗虚拟内存的进程,其最初的分较高。单位为1kb为1分。小号1gb内存的进程,得分约为1000000.
    • 如果进程正在执行swapoff系统调用,则得分设置为最大值(unsignedlong的最大值),禁用swap的行为与消除内存不足是相反的,会立刻将其做为oom Killer的对象进程。
    • 如果是母进程则将所有子进程内存大小的一半作为分数
    • 根据进程的cpu使用实际和启动实际调整得分。认为越长时间运行或从事越多的进程越重要,保持得分较低。
      用得分除以cpu使用时间(10秒为单位)的平方根。如果cpu使用时间为90秒,则结果为3。根据进程启动时间也可以调整得分。用得分除以启动时间(1000秒为单位)的平方根的平方根。如果是持续运行16000秒的进程,则用得分除以16的平方根“4”的平方根“2”。越长时间的进程就越重要。
    • 通过nice命令等将优先级设置较低的进程,将得分翻倍。nice-n中设置为1-19的命令的得分翻倍。
    • 特权进程普遍较为重要,因此将其得分设置为1/4。
    • 通过capset(3)等设置了功能(capability)CAP_SYS_RAWIO的进程,其得分为1/4。将直接对硬件进行操作的进程判断为重要进程。
    • 关于cgroup,如果进程只允许与促使OOM killer运行的进程所允许的内存节点完全不同的内存节点,则其得分为1/8.
    • 通过proc文件系统oom_adj的值调整得分。
      在设置了CAP_SYS_RAWIO的情况下,发送SIGTERM,在没有设置的情况下,发送SIGKILL。各进程的得分可以在/proc//oom_score来确认
      init(pid为1的)进程不能成为oom killer的对象。当成为对象的进程包含子进程时,先向子进程发送信号。
      向成为对象的进程发送信号后,对于引用系统的全线程,即使线程组(TGID)不同,如果存在与对象进程共享相同内存空间的进程,则也向这些进程发送信号。

关于OOM Killer的proc文件系统

主要内容: 关于oom killer相关的proc文件系统。
/proc//oom_adj 设置值就可以调整得分。调整值的范围-16~15。正值容易被OOM killer选定。负值可能性较低。3为2^3 倍,当为-5时,得分为1/2^5 。
如果设置为-17,就是禁止oom killer 发出的信号。

  • /proc/sys/vm/panic_on_oom设置为1时,在OOM killer 允许时可以不发送进程信号,只是内核产生重大故障。如果oom_kill_allocation_task设置除0以外的值,则促使oom killer运行的进程自身将接收到信号。
  • oom_dump_tasks设置除0以外的值时,在oom killer运行时的输出中会增加进程的列表信息。可以使用dmesg或syslog来确认。
  • linux2.6.36 以后的版本为oom_score_adj替换oom_adj,范围为-1000~1000,设置-1000时,该进程就被排除在OOM killer强制终止的对象外。

rhel5特征

  • oom killer从上次调出到下次调出之间超过5秒时,调用次数重新开始计算。避免仅仅因为突发性的内存负载就终止进程。
  • 在技术变成0后的1秒内调出时,不计入调用的次数。
  • oom killer调用次数不足10次时,实际不会运行。 oom killer调用10次时才开始认为内存不足。
  • 最后oom killer运行不到5秒的话,oom killer不会再次运行。这是为防止不必要地连续终止多个进程。也有等待接收到oom killer发出信号的进程终止(释放内存)的意思。
  • oom killer一旦运行,调用的次数就重新回到0.
  • rhel6不会慎重运行,得分机制与rhel5基本相同

文件系统

主要内容: rhel6等用作标准文件系统的ext4的使用和调整,以及从ext2/ext3转换的方法。还将介绍进行I/O基准测试(benchmark)的fio以及用户空间的文件系统FUSE。

如何使用ext4

ext4在ext3的mtime、atime、ctime基础上增加crtime。

性能、功能 ext3 ext4
最大文件大小 约2TB 约16TB
最大文件系统大小 约16TB 约1EB
块管理方式 阅读参照块方式 区间方式(标准)、阅读参照块方式
日志(journaling)功能
日志校验和(journal checksum) _
延迟分配 _
多块分配 _
持久预留分配 _
条带(stripe)方式 _
时间戳单位 毫秒 纳秒
在线碎片整理 _
  • ext4的生成与挂载
    mke2fs
    选项 说明
    b 指定块的大小
    p 强制执行mke2fs
    I 指定索引节点大小(字节单位)
    O 文件系统功能的启用/禁用
    T 指定文件系统的种类
    v 显示详细内容
  • mount选项
    选项 说明 默认 ext4特有
    data-writeback 将日志模式设置为writeback - -
    data-journal 将日志模式设置为ordered O -
    journal_checksum 为要吸入日志的事务添加校验和 - O
    journal_async_commit 非同步记录写入日志 - O
    barrier=1 启用写入屏障 O -
    barrier=0 警用写入屏障 - -
    discard 向夏季块设备通知块已释放 - -
    nodiscard 不向下级块设备通知块已释放 O -
    delalloc 写入时延迟分配 O O
    nodelalloc 写入时不使用延迟分配,在出现写入请求的当时确保块 - O
    auto_da_alloc 通过rename进行文件替换,通过truncate后的写入进行文件替换hi,不使用延迟分配功能,而是当时立即确保块 O O
    noauto_da_alloc rename和truncate处理时也使用延迟分配 - O
  • ext4的调整
    可以不用内核编译、重启,直接从用户空间确认、更改内核空间的设置参数。
    文件名 说明 默认值
    delayed_allocation_blocka 等待延迟分配的块数
    mb_max_to_scan 分配多块时找出最佳extent而搜索的最大extent数 200
    mb_min_to_scan 分配多块时为找出最佳extent而搜索的最小extent数 10
    inode_goal 下一个要分配的inode编号(调试用) 0(经用)
    inode_readahead_bike 先行读入缓存(buffer cache)的inode表块(table block)数的最大值 32
    mb_order2_req 对于大于该值(2的幂次方)的块要求使用buddy检索 2
    lifetime_write_kbytesmb_state 文件系统生成后吸入的数据量(kb)
    mb_stat 指定收集(1)或不收集(0)多块分配的相关统计信息。统计信息在卸载时显示 0(禁用)
    max_writeback_mb_bump 进行下一次inode处理前尝试吸入磁盘的数据量的最大值(MB) 128
    mb_stream_req 块数小于该值的文件群被集中写入到磁盘上相近的区域 16
    mb_group_prealloc 未指定挂载选项的stripe参数时,以该值的倍数未单位确保块的分配
    session_write_kbytes 挂载后写入文件系统的数据量(kb)
    /sys/fs/ext4/<设备名>下有与文件系统相关的各种文件。
    • lifetime_wirte_kbytes以千字节为单位记录吸入文件系统的数据量。session_write_kbytes以千字节为单位记录文件系统挂载后写入的数据量。
    • mb_stream_req 多块分配处理中安装的时内核内部使用的group预分配(group PA)和inode预分配(inode PA)。group PA由各cpu分别管理,用来将对象文件块(满足条件的)排列到物理上较近的区域,inode PA用来将某一个文件的块排列到物理上连续的区域。块的大小4kb时阈值为64kb,块的大小为1kb时阈值为16kb。默认设置表示对于16块以下的分配处理使用group api,对于16块以上则使用inode PA。这个值可以使用mb_stream_req来更改。通过group pa 实现物理上的局部化。在系统启动时等数据读入处理操作种,通过将文件数据局部化,可以缩短磁盘寻道时间(seek time)。inode pa只在引用对象文件期间保留有效的预分配块。从而在按顺序向对象文件写入时,把块分配到物理上连续的区域,抑制碎片的产生。为了避免产生碎片,文件系统上必须要有足够的内存块。extent size range越大,在整体中所占的比例越大。产生的碎片可以使用e4defrag命令来消除。
    #e2freefrag /dev/sdb5
    Device: /dev/sdb5
    Blocksize: 4096 bytes
    total blocks: 1220703
    
    • inode_readahead_blks 可以控制进行预读inode表的数量。inode表时指磁盘上存储inode结构的区域,被分配给各块组。与flex_bg标志同时使用可以提高运行效率。之心时间差异约为6%。在经常连续读取多个文件的环境下,就可以通过更尴尬inode_readahead_blks来提高读写性能。
  • 使用fio进行I/O的基准测试
    io分随机访问还是依次访问,通过read/write的I/O还是通过访问mmap的空间的I/O?单进程发出的I/O还是多进程发出的I/O。进程受I/O限制还是受cpu限制。
    • fuse(filesystem in Userspace,用户空间文件系统),用来生成用户空间的一般进程的框架。通过fuse可以使一般应用进程生成独特的文件系统,与已有文件系统同样进行挂载。

网络

本章介绍与网络相关的内核功能。主要包括TUN/TAP设备、网桥设备、vlan设备、bonding设备和网络调度、dropwatch。

如何控制网络带宽

内核中安装有成为网络调度或分组调度的带宽控制。这个功能可以控制每个网络设备传输的吞吐量。

  • 设置带宽
    CBQ(class based queueing)是以具有优先级的类为单位分配传输带宽。为每个类准备配置文件并介绍控制带宽的方法。
    RATE指定的是分配到该类的带宽。单位为bit或bps。bit对应bits/秒,bps对应bytes/秒。bandwidth是网络设备的物理带宽。weight是根类的比重,值越大,表示根类一次处理的数据比例越大。根类针对每个设备分别生成。推荐将weight指定为bandwidth的1/10.
    PRIO 为该类的优先级。可设定为1-8.默认为5.数字越大,表示优先级越低。PRIO为8时WEIGHT自动变为1.
    RULE 指定的时带宽控制对象。可以使用通信对象的IP地址或端口来限定,因此,可以只控制http或FTP的带宽。
    RULE=[saddr[/prefix][: port[/mask]], ][daddr[/prefix]][: port[/mask]]
    RULE=192.168.0.19:80
    
    TIME 可以通过时间或星期来修改带宽RATE和WEIGHT的配置。
    TIME=[<dow>,<dow>,……,<dow>/]<from>-<till>;<rate>/<weight>[/<peak>]
    TIME=18:00-06:00;256Kbit/25Kbit
    
  • 启动脚本
    CBQ使用tc(traffic control)来进行设置。
  • 确认带宽控制
    nuttcp确认吞吐量。使用数据包捕获进行确认,每隔200毫秒传输一次数据。这时因为TSO(TCP segmentation Offload)与CBQ的组合使其成为无意图动作。
    对于千兆以太网NIC来说,TBF的缓冲区不够大。TBF(Token Bucket Filter)是Qdisc(queueing discipline)之一,用来把通信数据包放入队列。

TUN/TAP设备

主要介绍linux中实现网络通道的TUN/TAP设备。

  • TUN/TAP设备时TUN(tunnel)设备和TAP设备的总称。linux的内核源代码中加入Universal TUN/TAP设备。因此可以很方面地生成TUN/TAP设备实现网络隧道。
    一般来说TUN设备实现三层隧道,TAP设备实现二层隧道。
  • TUN设备。这是虚拟的点对点设备,在一般TCP/IP网络中处理三层IP数据包。体现为tunX表示的点对点的网络设备。
  • TAP设备。在TCP/IP网络中处理二层的以太网帧。一般体现为tapX表示以太网络设备。以太网帧从用户空间的应用程序发送到用于网络隧道的设备-TAP设备。对操作系统来说,以太网帧从外部到达TAP设备。从外部接收以太网帧经由操作系统网络栈发送到TAP设备,由用户空间的应用程序接收。

网桥设备

linux内核中有网桥功能。使用网桥功能,可以将多个网络接口连接到一个网段上。网桥功能的linux机器等同于交换式集线器(switching hub)。linux内核将ip地址分配到网桥接口br0.捕获向连接到网桥的网络接口分配ip地址。

  • brctl命令
    bridge-utils工具包包含对网桥操作的的命令brctl。
    brctl show [网桥名]
    brctl addbr 网桥名
    brctl addif 网桥名 接口名 将接口连接到网桥
    brctl delif 网桥名 接口名 拆除连接到网桥的接口
    brctl delbr 网桥名       删除网桥
    
  • 网桥的设置
    在redhat系列中,设置NM_CONTROLLED=no,就可以将其排除在NetworkManager的管理范围外。
  • 虚拟机的网桥连接
    在启动qemu的情况下,使用-net选项指定tap启动,TAP设备生成和删除时就会执行脚本。

vlan

在linux中,vlan时虚拟分配以太网的功能。只有vlan id 相同才可以互相通信。

bonding驱动程序

bonding驱动程序是将多个物理设备绑定的驱动程序。绑定bonding说法来子bond。绑定的运行根据模式不同有所差异。linux的bonding有7种模式。可以达成eth0和eth1绑定,eth0 为激活状态,eth1为待命状态。

  • balance-rr 轮询来分散负载。第一个数据从eth0发送,第二个数据从eth1发送。(默认)
  • active-backup 激活备份模式。主从之间进行判断
  • blance-xor 通过mac地址的异或结果(XOR)来决定从设备。从设备由散列算法(hashlist)进行管理,通过mac地址、IP地址和tcp、udp的端口号的组合来算出散列值。在这种模式下,只要条件不改变,就会使用宪公投的从设备。
  • broadcast 已连接的所有从设备发送相同的数据。即使某个从设备发送失败也不会中断,而是从其他从设备发送数据。
  • balance-tlb
  • balance-alb
    激活备份模式在激活从设备发生连接故障时,就会切换到从设备。第一次激活从设备时,bond0的mac地址设置为eth0的mac地址。即使切换也不会改变。连接障碍通过MII(Media Independent Interface)监控时的周期。的单位为毫秒,初始设置为100毫秒。使用MII监视时NIC必须和MII相对应。使用arp监控。arp_ip_target监控的ip地址,监控过程种一直传输的时arp数据包。
    updelay 选项在检测出从设备的连接后,不会立刻连接,等待updelay所指定的时间。单位为毫秒。这个选项在MII连接监控种有效。推荐设置为miimon数值的倍数。
    primary 选项设置作为激活从设备的接口。如果设primary=eth0,eth0就设置为激活从设备。当发生故障切换恢复后,仍然会将eth0作为激活从设备。

netowrk drop monitor

dropwatch监控内核的网络栈丢包。
收到数据包后,数据从网络驱动程序传输到内核的网络层。在这里进行校验或ip地址的确认等数据包验证处理。如果时非法包,则依据RFC丢弃,即使是合法的数据包,在超过缓冲区大小等情况也会有意识地丢弃。
各协议释放socket缓冲区时(kfree_skb函数)收集信息。可以应对IP、ARP、ICMP、IGMP、UDP协议的数据包。
dropwatch 输入 start 启动。其中nf_hook_slow时netfilter的函数。表示根据DROP的规则已废弃。

虚拟化

xen时众多linxu发行版采用的管理程序。
半虚拟化 客户端操作系统在已虚拟化的情况下,修改内核或设备驱动程序的方法。
全虚拟化 使用支持虚拟化功能的intel vt或amd-v等cpu的方法。在pc硬件上运行的操作系统直接在虚拟机环境上运行的方法。

kvm

kvm 为全虚拟化,由管理程序--kvm启动程序和设备仿真器--qemu-kvm构成。kvm特征是kvm驱动程序作为linux内核的一部分运行,因此可以使用linux内核的大部分功能。

更改cpu分配,提高性能

有的多核cpu在核间共享L2缓存或L3缓存。两个虚拟cpu分配给不共享缓存的内核时,一旦加大内存负载就有可能造成cpu性能降低。

EPT 提高客户端操作系统的性能

  • MMU(Memory Management Unit) 具有内存管理功能的硬件。MMU有一个主要功能是将虚拟地址转换为物理地址。
  • 影子页表 管理程序将影子页表设置为cpu的cr3寄存器。从而让客户端虚拟地址转换为主机物理地址。
  • EPT(Extended Table) intel的cpu硬件虚拟化支持。communication bandwidths in MB/s的值越大表示性能越高,context switching在禁用EPT时性能较高。表示EPT容易引起TLB错误。EPT消耗的TLB更多。
  • EPT+hugepage 用来减轻TLB错误。

IOMMU提高客户端操作系统运行速度

虚拟环境下,io主要有三种方式:仿真方式、半虚拟化方式、直接I/O方式

  • DMA(Direct Memory Access)传输。是指可以在内存和I/O直接进行数据交换的结构。
    DMA传输过程:
    • 确保传输用的内存。
    • 在设备寄存器种确保第一步设置中的DMA传输用内存的地址。
    • 在设备寄存器种确保第一步设置中的DMA传输用内存的大小。
    • 向DMA控制器请求开始在设备和内存间进行数据传输。
    • DMA传输完成后,设置DMA完成标志,将中断交给cpu。
      第二部中设备的寄存器地址是物理内存的地址。第四步后,设备会对设置的物理内存进行访问。这时物理内存和设备不再由cpu直接进行数据交换。
  • IOMMU 是I/O设备的MMU(Memory management unit),再pci设备的寄存器中设置客户端物理内存地址,并向设备请求DMA传输。

IOMMU+sr-IOV提高客户端操作系统速度

SR-IOV(Single Root I/O Virtualization) 是一个PCI Express设备向操作系统提供多个虚拟设备的功能。

SR-IOV带宽控制

ip命令可以对nic拥有的带宽进行设置,将其分配给各VF。

使用ksm节约内存

ksm(kernel samepage merging),是通过共享相同内容的存储页面,将其整合为一体,从而有效使用内存的功能。
ksm会通过内核线程ksmd定期对用户内存进行扫描。如果为同一内容,则再cow & nbsp;(copy on write)模式下合并该区域(存储页面)。这个存储区更新时,内核自动重新生成存储页面的副本。
要扫描的区域时通过madvise的MADV_MERGEABLE指定的内存,并且匿名页面成为合并对象。
pages_sharing与pages_shared的比值越高,ksm的效果越明显。

如何挂载客户端操作系统的磁盘

客户端操作系统的磁盘实际上都是主机操作系统上的文件。

  • guestfish 是可以读写客户端操作系统的文件系统工具。guestfish启动后会启动shell,然后启动qemu的子进程。在这个子进程qemu上运行用于作业的客户端操作系统来处理磁盘镜像。使用list-devices命令找出要挂载到的设备。sfdisk -l获取分区信息。使用mount 命令将/dev/volgroup/lv_root挂载到/下。
  • lomount可以像普通命令一样使用。

从客户端操作系统失败虚拟环境

  • cpuid命令是根据输入到EAX寄存器的值返回cpu识别信息或cpu功能信息。
  • 固有文件 kvm主机存在/dev/kvm的特殊文件。xen中会生成/proc/xen/capabilities文件。在dom0上/proc/xen/capabilities写有"control_d"。
  • acpi DSDT/FADT的OEM ID
  • System Management BIOS (SMBIOS)获取bios系统属性识别
  • virt-what 能识别客户端操作系统环境。

kvm

可以通过virsh list 确认客户端操作系统的状态。通过virsh edit来修改客户端操作系统配置文件。使用gdb功能可以对操作系统进行单步运行调试。virsh dump 转储文件

省电

目前用不到,记录一下,用到再回来翻。

调试

主要内容: watchdog(看门狗) 和 crash dump(内核崩溃转储)。

sysRq键

sysRq键获取内核信息。一般可以通过proc文件系统或命令获取信息。如果死机,无法输入命令。sysRq键可以直接从内核输出信息。只要不是禁止中断状态,即使死机也可以获取信息。
可以使用

sysctl -w kernel.sysrq=1  #开启功能

/proc/sys/kernel/sysrq中设置的位掩码。允许的值如下:

允许的命令
1 允许所有
2 允许控制控制台日志级别(0-9)
4 允许控制键盘(kr)
8 允许显示进程等信息(lptwmcz)
16 允许Sync命令
32 允许只读下的重新挂载(u)
64 允许发送信号(ei)
128 允许重启(b)
256 允许控制即时进程(q)

允许sync(s)和重新挂载(u),而不能进行其他操作。可以将数值指定为48.这个控制是从键盘和串行(serial)接口限制控制台的输入。/proc/sysrq-triggr的操作没有限制。
在内核参数中,无论/proc/sys/kernel/sysrq的设置如何,都可以启用sysrq键。

  • sysRq的输入
    从键盘输入sysRq键是,需要同时输入Alt键、sysRq键和命令键。从串口控制台输入时,在发送break信号后5秒内输入命令。此外,向/proc/sysrq-trigger写入命令键也可以达到相同效果的动作。
命令键 命令名称 说明
0~9 loglevel0~8 设置控制台层次。与设置/proc/sys/kernel/printk时相同的
b reBoot 重新启动linux内核
c Crashdump 获取崩溃转储。
d show-all-locks(D) 用于故意造成系统故障时输出获取的所有lock信息。但是task_running状态的进程获取的lock不显示。这是因为这个进程立刻就会释放
e tErm 向init进程(pid为1)以外的所有进程发送SIGTERM信号
f Full 运行OOM Killer
i kill 向init进程(pid为1)以外的所有进程发送SIGKILL信号
j thaw-filesystem
k saK
l aLlcpus 输出系统中的所有cpu栈。还会显示进程栈的回溯(backtrace)
m showMem 输出内存、交换区状态
n Nice 将所有实时进程改变为普通进程,与sched_setscheduler中指定SCHKD_NORMAL为调度策略相同
p showPc 输出cpu的寄存器和进程的信息。有多个cpu时,仅输出处理器中断的cpu信息
q show-all-timers(Q) 输出所有计时器的信息
r unRaw
s Sync 在所有文件系统中尝试sync(把内存缓冲区的内容跟写入磁盘)。内部通过强制运行pdflush来实现。在命令键b之前执行,就可以减少文件系统或文件破坏的风险,重启内核
t showTasks 输出运行中的所有进程栈、回溯
u Unmount 对所有文件系统尝试只读的重启内核
w show-blocked-tasks 仅输出处于UNINTERRUPTABLE状态(无视信号的进程状态)的进程信息
z dump-ftrace-buffer(Z) 输出ftrace缓冲区

rhel5中的命令键w与上游内核不同。命令键w(shoWcpus)输出系统的cpu栈。与上游内核的命令键l(aLlcpus)进行的操作相同。rhel6则与上游内核相同。

  • 各种情况下的使用
    • 某进程看似停止的情况: 通过r确认进程运行的地方。通过确认回溯,可能找出等待获取资源、等待获取lock等的进程之所以停止的原因。如果在等待获取lock时停止,有可能通过d键根据lock的已存关系找到原因,如果正在用户空间运行,可能是编程错误。机器看似死机的情况为了保全数据,s将内存中未完成写入的数据写到磁盘。使用u键将文件系统以只读形式重新挂载,可以防止发生数据不匹配。需要重新开始工作时,使用b键重启内核。如果不需要重新开始工作,可以使用c键提取崩溃转储,找出死机原因。通过i键向所有进程发送SIGKILL信号尝试从死机状态恢复。内核在运行中断状态下死机时,在死机的状态下执行几次w或p,就可以知道死机的位置。进行再现时,先禁用看门狗计时器就可以分析出死机原因。
    • 由于某些故障输出Oops信息等情况:未进行内核崩溃转储的设置时,有时控制台的最后输出kernel panic-not syncing: ~,然后就只能重新启动。这是可以用s键尝试把文件系统的数据写入磁盘,再重新启动,这更安全。
    • 按键c 常用于确认转储的情况

使用diskdump提取内核崩溃转储

diskdump时rhel系列中采用的内核转储功能。

  • 内核崩溃转储:将内存输出到文件的功能。如果应用程序发生段错误(segmentation fault)就会输出core文件,内核崩溃转储就类似于内核的core文件。
  • diskdump的限制事项:为使diskdump内核中即使发生所有故障也能获取内核崩溃转储,子啊设置为禁止中断的状态下获取转储。磁盘驱动程序必须能够支持不适用中断执行I/O的结构-轮询I/O。diskdump不经由文件系统或设备映射功能,直接对设备驱动程序进行操作。因此不饿能向文件或lvm上生成的磁盘分区写入。
  • 启用diskdump:diskdump中必须指定转储用的分区。可以准备用于转储的分区,也可以将swap分区指定为转储位置。
  • 使用压缩和部分转储功能缩小转储文件的大小:部分转储在dump_level中指定转储级别。启用这个功能需要注意,有些种类的页面在跳过时需要检索内核内存管理用的列表。有时故障是由这个列表的破坏而引起的,这是因为diskdump在检索列表的过程中有时也会引起双重重大故障或系统死机。
  • 如果使用这个功能,建议使用转储级别19.这个级别不需要检索内存管理用的列表。
  • 发生故障时通过右键通知:可以添加脚本发送邮件。
  • 将转储输出到的设备冗长化:可以将多个分区作为转储分区

kdump提取内核崩溃转储

  • 启用崩溃转储:首先向内核启动参数添加crashernel=128M。分配128M的内存用于kdump。从rhel6开始扩展crashkernel内核启动参数。可以不根据机器按照的物理内存大小分配内存,或者改变分配的内存量。
crashkernel=512M-2G: 64M,2G-: 128M
如果物理内存不足512MB,则不分配内存作为kdump用。
如果物理内存大于512MB小于2GB,则分配64MB作为kdump用。
如果物理内存大于2gb,则分配128MB。

通过service命令或/sys/kernel/kexec_crash_loaded确认是否已设置成功。

  • 通过makedumpfile缩小转储文件大小:当不想包括零页面和可用页面时,可以将转储级别指定为17时。可以用","将转储级别分开,指定两个转储级别。转储31跳过的页面比转储级别11多,转储文件更小。更改设置需要重启kdump服务。根据vmcore文件的大小可以判断储提取转储是否已压缩。
  • 向远程服务器传输崩溃转储:可以配置nfs或ssh将获取的转储文件向远程传输。

崩溃测试

对于内核的崩溃测试,目前暂时用不到

IPMI看门狗计时器

IPMI看门狗计时器可以检查出操作系统死机。

  • IPMI看门狗计时器
    IPMI(ntelligent platform management interface)标准中的硬件看门狗计时器。系统死机时可以执行机器自身的重启(reset)等,从而提高系统的可用性。
    与NMI看门狗计时器的不同之处在于可以通过硬件(IPMI)执行硬启动。
  • IPMI看门狗计时器的使用方法
    需要启动内核配置IPMI_WATCHDOG=yes
参数 说明
timeout 超时时间
pretimeout 到执行超时为止的时间与到执行预超时(pretimeout)运行为止的时间差,单位秒
action 超时处理(reset、none、power_cycle、power_off)
preaction 预超时的处理(pre_name、pre_smi、pre_nmi、pre_int)
preop 超时驱动程序的运行(preop_name、preop_panic)
start_now 设置为1时,ipmi_watchdog模块安装到内核后立刻启动计时器。内核启动后立刻通过看门狗监视系统。
nowayout 设置为1时,一旦打开IPMI看门狗计时器,就不会停止

在指定pre_nmi参数后,会通过NMI通知IPMI看门狗计时器超时,在禁止中断状态下,preaction、preop也会运行。系统正常运行时,实时处理正常运行,系统如果死机,watchdog守护进程作出实时处理就会中断。计时器就不重启,而IPMI看门狗计时器超时。设置start_now=1后,需要选择watchdog守护进程启动前不会超时的pretimeout/timeout时间。
向/dev/watchdog写入字符串,就可以确认IPMI看门狗计时器的运行。写入V则禁用IPMI看门狗计时器。
如果设置了pre_nmi时,如果死机发生的时间超过pretimeout所指定的时间,就捕获主板上的NMI信号,发生NMI中断。内核上的IPMI看门狗计时器使NMI处理程序启动,如果设置了preop_panic,则发生重大故障。

NMI看门狗计时器

是使用NMI的看门狗计时器功能
NMI(Non maskable interrupt)无法禁止的中断。可以检测出pc在禁止中断的状态下的死机。
中断是从硬件发出的信号,I/O的完成或数据包的接收通过中断传递到内核。内核收到中断会进行各种处理,如果进行并行处理就会出现数据不匹配,因此在接收到1个中断时,就会禁止此后的中断直到这个中断的处理完成。NMI并不是用来处理I/O或数据包等一般处理的,而是用来通知紧急情况的。
在禁止中断的状态下,内核进入无限循环或死锁,就不会执行计时器中断处理。

soft lockup

linux内核中安装的锁定检测功能soft lockup。可以检测出内核或设备驱动程序等软件的故障导致内核功能无法运行的状态。
在关键人物(critical mission)领域,就需要这种锁定检测功能。如果watchdog线程没有达到一定运行时间,可以检测出进程调度程序未正常运行,发生锁定。
内核线程定期(检测时间的20%)由计时器唤醒。唤醒的watchdog内核线程会记录自己唤醒的时刻。不更新的时间超过指定时间,则判断为死锁。

  • 锁定检测的限制:soft lockup的检测时通过计时器中断的延长来进行的。

crash命令

crash可以分析内核映像的调试工具。在gdb的基础上设计,可以引用内核内部的各种信息的命令,以会话形式进行操作。

  • 实用工具命令:set命令指定进程后,会将进程的上下文切换到指定的进程,显示这个上下文。没有指定时显示当前进程的上下文。上下文初始值为内核发生重大故障时运行的进程的初始值。-c 可以指定cpu,并显示之前这个cpu上运行的进程。-p可以显示发生重大故障时运行的进程。
    eval 命令将输入的表达式结构以十六进制、十进制、八进制以及二进制显示。
  • bt命令: 输出进程内核栈的遍历。当栈上存在具有内核文本符号(text symbol)的地址时,
    • -t选项显示这些符号。在一般的回溯处理失败时可以使用该选项。
    • -f 选项显示框架(frame)内的所有栈数据。
    • -l选项显示文件名和行数
    • -a选项仅显示各cpu上原本正在运行的进程。针对运行中的系统(实时内核)启动crash命令时,不支持这个选项。
  • dev命令显示字符设备列表。使用-p参数显示PCI设备。输出与lspci相同,使用 -i选项显示I/O端口和I/O内存。内容基本与下列命令相同。cat /proc/ioports cat /roc/iomem
  • dis命令:进行反汇编的命令。如果指定-l,会显示源代码名称和行编号。
  • files命令:显示进程打开的文件信息。
  • irq命令:显示内核内部管理的中断的信息。
  • kmem命令:显示关于内核内存的使用情况信息。 -s选项显示slab缓存(slab cache)的信息。信息与/proc/slabinfo相同。-i 显示整体内存使用情况,和free命令相同。-p选项显示内存映射。也可以指定内存地址。[]中的页面表示尚未释放内存。可用于重大故障时确认内存释放。
  • list 命令:查找在内核中共同使用的list_head结构的链接列表,依次显示列表上的对象(object)。-o 可以指定对象中的list_head结构位置,也会查找列表。-s选项会显示成员。
  • mod命令:显示内核模块的信息,读入符号信息或调试信息。不指定选项时只显示内核模块信息。使用-s选项指定要读入的内核模块。使用-S选项指定目录,就会尝试从所指定的目录自动检索并读入模块。
  • net命令: 显示网络设备信息列表。指定显示的net_device结构的地址,使用struct命令进行转储,就可以获取更加详细的信息。向gdb的print命令传递输入时,p命令可以显示结果。
  • ps命令:-a选项显示赋予该进程的命令行变量和环境变量。-t显示进程的运行时间、开始时刻、用户空间及内核空间上的执行时间。
  • rd命令:读取内存内容的命令。
  • runq命令:显示连接到进程调度程序的运行队列(run queue)的进程(运行中的进程)。
  • search命令:检索内存空间中指定的值。使用-c选项也可以检索字符串。
  • sig命令: 显示进程的信号处理程序。还会显示挂起(pending)的信号信息。-l选项等同于kill -l,显示已定义的信号编号。
  • struct命令: 更加结构的定义和实际的地址,配合结构显示数据。
  • swap命令:输出交换设备的信息。输出内容于swapon-s基本相同。
  • sym命令:解析符号(synbol)的命令。sym-l与cat System.map相同。
  • sys命令: 显示系统的信息。显示时刻或cpu的平均负载(load average)、描述出现故障的原因信息等。与crash命令启动时显示的信息相同。内核配置CONFIG_IKCONFIG启用时,执行sys config就可以显示内核配置的列表。与/proc/config.gz解压后文件相同。可以使用sys-panic故意引起内核出现重大故障。
  • task命令:显示task_struct结构(进程管理所用的数据结构)。
  • timer命令:显示加入到计时器列表中的计时器。
  • whatis命令:显示结构等的类型或变量的定义。
  • wr命令:时改写内存内容的命令。下列使用crash命令,在运行中的系统上改写表示时间的jiffies变量。/proc/kcore和/dev/crash为只读,要使用wr命令需要将CONFIG_STRUCT_DEVMEM设置为off。
  • 扩展命令:snap可以生成实时内核的内核崩溃转储,生成的内核崩溃转储文件也可以使用crash命令来分析。
  • 扩展命令:trace命令可以地对内核映像中包含的ftrace的管理信息或者将其写出到文件。在系统上也可以使用此命令。
    名称 功能
    trace show 显示追踪(trace)信息。与从trace读出的信息相同,trace-cmd命令在内部调用
    trace report 与trace show相同
    trace dump 目录名 根据debugfs的tracing目录下的结构,将环形缓冲区(ring buffer)或管理信息写到文件
    trace dump 文件名 将环形缓冲区或管理信息生成trace-cmd report命令可以处理的数据格式文件
  • gcore命令:生成内核崩溃转储中包括的用户模式进程的核心转储。
  • crash选项:
    选项 说明
    -i 指定包含crash命令的文件,crash在启动时自动执行这个命令
    -s 不再显示crash命令启动信息

核心转储过滤器

rhel6中,当abrtd的报告大小可以设置(MaxCrashReportsSize),核心文件有时在/var/spool/abrt下生成。核心转储过滤器可以限制core文件生成的位置、大小、以及包含的区域。
核心转储过滤器通过/proc//coredump_filter来设置。

位值 内存区域
第0位 进程内存
第1位 共享内存
第2位 映射到文件的进程固有内存
第3位 映射到文件的进程共享内存
第4位 在文件的进程固有内存中,仅ELF头文件
第5位 hugetlb进程内存
第6位 hugetlb共享内存
内存区域的设置位掩码为1时包括,为0则不包括。rhel6默认位0x33。0x33设置位将第0、1、、5位内存区域包括到core文件。可以使用内核启动产生coredump_filter设置默认值。
  • sysctl: 使用/proc/sys/kernel/core_pattern 使用core_pattern可以设置核心转储文件的命名规则。当第一个字符为|时,将执行其后的进程。默认文件名最后有.。在core的情况下为core.。core_pattern还可以以%开始的模式。
模式 内容
%p 进程ID
%u 用户ID
%g 组ID
%s 信号编号
%t core文件生成的时刻
%h 主机名称
%e 执行文件名称(命令名称)
%c core文件大小的限制(ulimit -c的大小)
指定%p时,文件名的最后不加.。下面更改core_pattern时的例子。
/proc/sys/kernel/core_pipe_limit 是限制收集核心转储的进程同时执行sysctl参数次数。在rhel6中由abrt工具包将默认设置为4。当/proc/sys/kernel/core_pattern的第一个字符为 时,core_pattern进程会获取核心文件,此时内核为了获取进程数据会停止崩溃进程。内核等待core_pattern进程结束后,删除崩溃进程。如果core_pattern进程存在bug,核心转储处理不会结束。不断崩溃的进程都会因core_pattern进程被迫停止。

生成用户模式进程的进程核心转储

使用crash的gcore命令,生成内核崩溃转储中包含的用户模式进程的核心转储。gcore并非crash的标准功能,而是扩展模块。

  • 使用crash参照用户进程的符号信息的方法
    crash可以获得符号信息的进程用户内存。使用add-symbol-file命令添加用户进程的符号信息。add-symbol-file命令第一个参数提取包括应用程序符号信息的obj文件,第二个参数提取与符号信息相对应的文本区域的开始地址。使用vm命令显示crash进程所管理的部分内存区域。使用vm -f 在flags项目显示设置的标志。
    crash不能处理一次也没有分配内存的区域或交换出swap out的内存区域。gcore将这些区域全部设置为0。使用set将crash参数zero_excluded改为on。其初始值设为off。
    gcore命令生成的进程核心转储所包含的执行信息中包含寄存器信息。这是崩溃时用户进程具有的用户空间中寄存器的值。崩溃时,在用户进程的不同状态下寄存器的退出位置也不同,因此需要根据各状态从适当的位置回收寄存器信息。但是,有时难以指定适当的位置,也有寄存器值自身没有退出的情况,并不一定能够回收全部的寄存器信息。
  • 使用lockdep查找系统的死锁
    内核中存在自旋锁(spinlock)、Mutex、信号量(semaphore)等各种锁。这些锁用于内核中的资源排他控制。如果使用方法错误,就会造成死锁的状态,等待锁的进程就永远无法恢复,最严重的情况会导致内核死机。
    lockep记录内核启动后各个锁的获取状态(中断)、锁之间的获取顺序,将其作为锁规则,对于这个规则以外的锁显示警告。
    中断处理和单个锁:中断处理程序的内部获取与原来的程序相同的锁,就有可能发生意想不到的死锁。一般在中断处理程序内部使用的可能性较高。禁止hardirq时softirq也会自动禁止,因此softirq-unsafe的意义与hardirg-unsafe相同。
    多个锁之间的依存关系:多个锁之间可能发生死锁。锁的嵌套,有时按照某个顺序获取相同种类的类(数据结构)的不同实例(instance)的锁。对于mutex,要向mutex_lock_nested(mutex,subclass)的subclass传递1以上的值。subclass的值越大,嵌套的层次就一定越深。
    lockdep的系统开销:lockdep针对锁的每个使用模式,生成64位的散列值并记录下来,散列值相同的使用模式则从第二次以后不进行处理。

检测内核的内存泄露

kmemleak是检测内核空间的内存泄露的调试功能。监测对象通过内核函数kmalloc()、vmalloc()、kmem_cache_alloc()分配的内存区域。使用dmesg命令确认检测出内存泄露的信息是否输出。

概要分析与追踪

perf tools的概要分析

perf tools是由内核维护人员开发的内核综合性能概要分析工具。perf tools的子命令基本按照:1、选定概要事件。2、记录概要分析和数据。3、分析记录的数据。
perf list显示事件列表,perf record记录事件,最后perf report或perf annotate进行详细的事件信息分析。参数:--pid进程id、--tid线程id、--profile_cpu 特定cpu上的所有进程。--all指定所有cpu上的进程。
perf record基本将概要事件和概要对象命令指定为参数。
perf top 或perf record/report可以用来分析特定性能,但不适合汇总综合性能。perf stat就是针对综合性能的功能。
context-switches为进程或线程的切换次时。CPU-migrations为正在运行cpu切换次时。page-faults表示按需分页或交换等使用的页面错误的发生次时和频率。cycles表示进程执行所花费cpu时间。instructions表示执行的命令条数。IPC值越小,则每条命令的时钟数量越大,因此认为效率较低。branches表示分支命令的数量和频率,branch-misses表示分支预测错误的比例。一般来说,缓存未命中次数少,IPC越大,就认为程序的执行效率越高。

使用perf script进行追踪

perf script显示已追踪的事件,或启动处理事件的脚本的功能。--list选项可以获取可使用的脚本列表。要进行离线处理,需要在perf script的record和report后面指定脚本名称。-g选项可以根据record记录的事件数据文件生成脚本模型。

ftrace追踪内核参数调用

ftrace两个功能:插件追踪器(plugin tracer)分析的追踪功能。另一个是追踪内核事件的功能(引进uprobes,可能支持用户空间的追踪)。
depth表示该函数内最大的栈消耗量,size表示仅该函数上使用的栈消耗量。加大负载一段时间后再次读入stack_trace,就会出现消耗了栈的执行路径。irqsoff、preemptoff、preemptirqsoff、wakeup、wakeup-rt分别测量中断、优先权、调度的延迟时间的功能,统称为延迟追踪器。

posted @ 2022-11-03 17:18  天雨流芳=.=  阅读(463)  评论(0编辑  收藏  举报