精华内容
下载资源
问答
  • 风河提升On—Chip Debugging能力强化Linux及多内核支持.pdf
  • 风河提升On-ChiP Debugging能力强化Linux及多内核支持.pdf
  • 风河提升On-Chip Debugging能力 强化Linux及多内核支持.pdf
  • 堆分配后将返回投毒的地址,Linux内核引入了堆强化,这使这些链接列表中的指针会变得非常模糊。在不知道密钥和指针地址的情况下,攻击者无法可靠地用选定的地址毒化指针。在这篇文章中,我将分析Linux内核的free列表...

    c35ce23611b8c9642ba479924513e8e5.png

    0x01 摘要

    常见的堆利用技术中的空闲列表投毒会破坏堆分配器的空闲块的链接列表。堆分配后将返回投毒的地址,Linux内核引入了堆强化,这使这些链接列表中的指针会变得非常模糊。在不知道密钥和指针地址的情况下,攻击者无法可靠地用选定的地址毒化指针。在这篇文章中,我将分析Linux内核的free列表指针混淆有一些缺陷,在适当的条件下,攻击者可以进行自由列表投毒攻击。

    0x02 介绍

    Linux内核中的默认堆分配器是SLUB分配器。每个空闲块中都有一个指针,该指针是跟踪这些空闲块的链表的一部,空闲列表投毒是针对Linux内核的一项已知技术,在《内核开发指南:攻击核心》一书中有记录,2010年,攻击者使用精心设计的地址覆盖了空闲列表指针,该地址随后将在将来的堆分配中返回。

    自2017年以来,使用配置选项CONFIG_SLAB_FREELIST_HARDENED在Linux内核中缓解了自由列表投毒的问题。

    https://patchwork.kernel.org/patch/9864165/中显示了此缓解措施的补丁。

    进行混淆的重要代码如下所示:

    *

    * Returns freelist pointer (ptr). With hardening, this is obfuscated

    * with an XOR of the address where the pointer is held and a per-cache

    * random number.

    */

    static inline void *freelist_ptr(const struct kmem_cache *s, void *ptr,

    unsigned long ptr_addr)

    {

    #ifdef CONFIG_SLAB_FREELIST_HARDENED

    return (void *)((unsigned long)ptr ^ s->random ^ ptr_addr);

    #else

    return ptr;

    #endif

    目标指针与指针的地址和一个随机值进行异或,每个主机的随机值是唯一的,我们可以看到,除非知道秘钥在块地址上也有信息泄漏,否则无法显示或覆盖此指针。

    0x03 准备

    理解攻击的关键是,指向空闲块的指针存储在类似的空闲块内。实际上,这意味着指针和这些指针的地址几乎相同,例如,分配2个16字节的内存块时,指针和指针的地址很可能仅在其较低的12位不同(对于具有12位页面大小的体系结构)。

    当空闲列表指针被ptr ^ ptr_addr ^ s-> random混淆时,则由于ptr和ptr_addr共享相同的高位,这将导致ptr ^ ptr_addr的结果高位为0。因此,如果混淆指针的信息泄漏,那么我们随后可以泄漏s-> random的高52位。

    还注意到,泄漏了s-> random的一些低位。SLUB分配器是基于board的分配器,它将分配舍入到board的大小。我们可以做出一些假设,即分配给我们的内存将与舍入后的board大小对齐。因此,如果我们分配16个字节的内存,则堆分配的低4位将为0。如果分配256个字节,则低8位将为0,如果分配4096个字节,则低12位将为零。但是,如果我们将board尺寸混合在一起,则对于不同的board会出现新的s-> random。

    0x04 攻击

    我们要执行自由列表投毒攻击。首先,我们需要信息泄露,假设我们分配了一个16字节的块,需要知道空闲块中空闲列表指针的内存内容,空闲列表指针是64位体系结构上空闲块的前8个字节。

    当我们公开这个模糊的指针时,只需要高52位和低4位即可,这些位是前面显示的secret值,即s-> random,我们将其称为“secret”。

    现在我们要进行空闲列表指针破坏。我们分配一个16字节的块,释放此缓冲区,将破坏它的指针。我们还需要知道这个空闲块的地址,将其称为PTR_ADDR。

    我们将用来毒化的目标缓冲区称为TARGET_PTR,要计算模糊的空闲列表指针,我们使用:

    secret = high_bits_of_secret | low_bits_of_secret;

    OBFUSCATED_POINTER = TARGET_PTR ^ secret ^ PTR_ADDR;

    当覆盖该指针时,仍然不知道secret的中间位。在上述情况下,我们只知道56(52 + 4)位,而8位仍然未知,中间位可以是任意值。

    我们使用OBFUSCATED_POINTER进行毒化,并具有8位熵来表示堆分配器将返回内存的位置。但是,它仍可能从同一页内存中返回一个地址,因此,如果能够控制这些可能结果中的每一个,那么攻击就可以成功。

    0x05 结论

    这篇文章分析了SLUB分配器中的堆强化功能,以混淆free列表指针,我证明了该方法存在弱点,并且可以在这些混淆的指针中显示secret信息。

    0x06 跟进

    用于Linux内核补丁:

    https://git.kernel.org/pub/scm/linux/kernel/git/kees/linux.git/commit/?h=mm/slub/freelist&id=d5baf9d870941c4c5efaa6435228ae2f3382b6e2

    引述一提交消息的部分:

    kmalloc-32 freelist walk, before:

    ptr ptr_addr stored value secret

    ffff90c22e019020@ffff90c22e019000 is 86528eb656b3b5bd (86528eb656b3b59d)

    ffff90c22e019040@ffff90c22e019020 is 86528eb656b3b5fd (86528eb656b3b59d)

    ffff90c22e019060@ffff90c22e019040 is 86528eb656b3b5bd (86528eb656b3b59d)

    ffff90c22e019080@ffff90c22e019060 is 86528eb656b3b57d (86528eb656b3b59d)

    ffff90c22e0190a0@ffff90c22e019080 is 86528eb656b3b5bd (86528eb656b3b59d)

    ...

    after:

    ptr ptr_addr stored value secret

    ffff9eed6e019020@ffff9eed6e019000 is 793d1135d52cda42 (86528eb656b3b59d)

    ffff9eed6e019040@ffff9eed6e019020 is 593d1135d52cda22 (86528eb656b3b59d)

    ffff9eed6e019060@ffff9eed6e019040 is 393d1135d52cda02 (86528eb656b3b59d)

    ffff9eed6e019080@ffff9eed6e019060 is 193d1135d52cdae2 (86528eb656b3b59d)

    ffff9eed6e0190a0@ffff9eed6e019080 is f93d1135d52cdac2 (86528eb656b3b59d)

    参考及来源:https://blog.infosectcbr.com.au/2020/03/weaknesses-in-linux-kernel-heap.html

    展开全文
  • 第二遍,根据理解,自己改写内容,调试运行以强化知识的理解。本门课程没有包含进程实现、文件管理等内容,有待后续其他课程进行扩展。 课程亮点: 课程讲师在操作系统相关课程上,拥有10年上全日制本科教学经验,全...
  • 基本的内核强化。 基本的TCP / IP堆栈强化。 删除您选择的软件包。 设置/配置PAM模块,例如pam_tally2和pwquality 。 使用limits禁用核心转储。 使用limits设置nproc限制以防止叉子炸弹(不适用于root用户)。 要求 ...
  • linux 内核调试

    2019-05-09 10:34:13
    本文系转载文档 感谢作者 ...参考链接 Linux内核调试的方式以及工具集锦 GitHub https://www.cnblogs.com/cslunatic/p/3639099.html https://www.cnblogs.com/syw-casualet/p/5271369.html ...

    本文系转载文档 感谢作者 https://blog.csdn.net/gatieme/article/details/68948080

    参考链接
    Linux内核调试的方式以及工具集锦
    GitHub

    https://www.cnblogs.com/cslunatic/p/3639099.html
    https://www.cnblogs.com/syw-casualet/p/5271369.html

    1 内核调试以及工具总结


    内核总是那么捉摸不透, 内核也会犯错, 但是调试却不能像用户空间程序那样, 为此内核开发者为我们提供了一系列的工具和系统来支持内核的调试.

    内核的调试, 其本质是内核空间与用户空间的数据交换, 内核开发者们提供了多样的形式来完成这一功能.

    工具描述
    debugfs等文件系统提供了 procfs, sysfs, debugfs以及 relayfs 来与用户空间进行数据交互, 尤其是 debugfs, 这是内核开发者们实现的专门用来调试的文件系统接口. 其他的工具或者接口, 多数都依赖于 debugfs.
    printk强大的输出系统, 没有什么逻辑上的bug是用PRINT解决不了的
    ftrace以及其前端工具trace-cmd等内核提供了 ftrace 工具来实现检查点, 事件等的检测, 这一框架依赖于 debugfs, 他在 debugfs 中的 tracing 子系统中为用户提供了丰富的操作接口, 我们可以通过该系统对内核实现检测和分析. 功能虽然强大, 但是其操作并不是很简单, 因此使用者们为实现了 trace-cmd 等前端工具, 简化了 ftrace 的使用.
    kprobe以及更强大的systemtap内核中实现的 krpobe 通过类似与代码劫持一样的技巧, 在内核的代码或者函数执行前后, 强制加上某些调试信息, 可以很巧妙的完成调试工作, 这是一项先进的调试技术, 但是仍然有觉得它不够好, 劫持代码需要用驱动的方式编译并加载, 能不能通过脚本的方式自动生成劫持代码并自动加载和收集数据, 于是systemtap 出现了. 通过 systemtap 用户只需要编写脚本, 就可以完成调试并动态分析内核
    kgdb && kgtpKGDB 是大名鼎鼎的内核调试工具, KGTP则通过驱动的方式强化了 gdb的功能, 诸如tracepoint, 打印内核变量等.
    perferf Event是一款随 inux内核代码一同发布和维护的性能诊断工具, 核社区维护和发展. Perf 不仅可以用于应用程序的性能统计分析, 也可以应用于内核代码的性能统计和分析. 得益于其优秀的体系结构设计, 越来越多的新功能被加入 Perf, 使其已经成为一个多功能的性能统计工具集
    LTTngLTTng 是一个 Linux 平台开源的跟踪工具, 是一套软件组件, 可允许跟踪 Linux 内核和用户程序, 并控制跟踪会话(开始/停止跟踪、启动/停止事件 等等).

    2 用户空间与内核空间数据交换的文件系统


    内核中有三个常用的伪文件系统: procfs, debugfs和sysfs.

    文件系统描述
    procfsThe proc filesystem is a pseudo-filesystem which provides an interface to kernel data structures.
    sysfsThe filesystem for exporting kernel objects.
    debugfsDebugfs exists as a simple way for kernel developers to make information available to user space.
    relayfsA significantly streamlined version of relayfs was recently accepted into the -mm kernel tree.

    它们都用于Linux内核和用户空间的数据交换, 但是适用的场景有所差异:

    • procfs 历史最早, 最初就是用来跟内核交互的唯一方式, 用来获取处理器、内存、设备驱动、进程等各种信息.

    • sysfskobject 框架紧密联系, 而 kobject 是为设备驱动模型而存在的, 所以 sysfs 是为设备驱动服务的.

    • debugfs 从名字来看就是为 debug 而生, 所以更加灵活.

    • relayfs 是一个快速的转发 (relay) 数据的文件系统, 它以其功能而得名. 它为那些需要从内核空间转发大量数据到用户空间的工具和应用提供了快速有效的转发机制.

    在 Linux 下用户空间与内核空间数据交换的方式, 第 2 部分: procfs、seq_file、debugfs和relayfs

    Linux 文件系统:procfs, sysfs, debugfs 用法简介

    2.1 procfs文件系统


    • ProcFs 介绍`

    procfs 是比较老的一种用户态与内核态的数据交换方式, 内核的很多数据都是通过这种方式出口给用户的, 内核的很多参数也是通过这种方式来让用户方便设置的. 除了 sysctl 出口到 /proc 下的参数, procfs 提供的大部分内核参数是只读的. 实际上, 很多应用严重地依赖于procfs, 因此它几乎是必不可少的组件. 前面部分的几个例子实际上已经使用它来出口内核数据, 但是并没有讲解如何使用, 本节将讲解如何使用procfs.

    • 参考资料

    用户空间与内核空间数据交换的方式(2)——procfs

    2.2 sysfs文件系统


    内核子系统或设备驱动可以直接编译到内核, 也可以编译成模块, 编译到内核, 使用前一节介绍的方法通过内核启动参数来向它们传递参数, 如果编译成模块, 则可以通过命令行在插入模块时传递参数, 或者在运行时, 通过 sysfs 来设置或读取模块数据.

    Sysfs 是一个基于内存的文件系统, 实际上它基于ramfs, sysfs 提供了一种把内核数据结构, 它们的属性以及属性与数据结构的联系开放给用户态的方式, 它与 kobject 子系统紧密地结合在一起, 因此内核开发者不需要直接使用它, 而是内核的各个子系统使用它. 用户要想使用 sysfs 读取和设置内核参数, 仅需装载 sysfs 就可以通过文件操作应用来读取和设置内核通过 sysfs 开放给用户的各个参数:

    mkdir -p /sysfs
    mount -t sysfs sysfs /sysfs
    

    注意, 不要把 sysfssysctl 混淆, sysctl 是内核的一些控制参数, 其目的是方便用户对内核的行为进行控制, 而 sysfs 仅仅是把内核的 kobject 对象的层次关系与属性开放给用户查看, 因此 sysfs 的绝大部分是只读的, 模块作为一个 kobject 也被出口到 sysfs, 模块参数则是作为模块属性出口的, 内核实现者为模块的使用提供了更灵活的方式, 允许用户设置模块参数在 sysfs 的可见性并允许用户在编写模块时设置这些参数在 sysfs 下的访问权限, 然后用户就可以通过 sysfs 来查看和设置模块参数, 从而使得用户能在模块运行时控制模块行为.

    用户空间与内核空间数据交换的方式(6)——模块参数与sysfs

    2.3 debugfs文件系统


    内核开发者经常需要向用户空间应用输出一些调试信息, 在稳定的系统中可能根本不需要这些调试信息, 但是在开发过程中, 为了搞清楚内核的行为, 调试信息非常必要, printk可能是用的最多的, 但它并不是最好的, 调试信息只是在开发中用于调试, 而 printk 将一直输出, 因此开发完毕后需要清除不必要的 printk 语句, 另外如果开发者希望用户空间应用能够改变内核行为时, printk 就无法实现.

    因此, 需要一种新的机制, 那只有在需要的时候使用, 它在需要时通过在一个虚拟文件系统中创建一个或多个文件来向用户空间应用提供调试信息.

    有几种方式可以实现上述要求:

    • 使用 procfs, 在 /proc 创建文件输出调试信息, 但是 procfs 对于大于一个内存页(对于 x864K)的输出比较麻烦, 而且速度慢, 有时回出现一些意想不到的问题.

    • 使用 sysfs( 2.6 内核引入的新的虚拟文件系统), 在很多情况下, 调试信息可以存放在那里, 但是sysfs主要用于系统管理,它希望每一个文件对应内核的一个变量,如果使用它输出复杂的数据结构或调试信息是非常困难的.

    • 使用 libfs 创建一个新的文件系统, 该方法极其灵活, 开发者可以为新文件系统设置一些规则, 使用 libfs 使得创建新文件系统更加简单, 但是仍然超出了一个开发者的想象.

    为了使得开发者更加容易使用这样的机制, Greg Kroah-Hartman 开发了 debugfs(在 2.6.11 中第一次引入), 它是一个虚拟文件系统, 专门用于输出调试信息, 该文件系统非常小, 很容易使用, 可以在配置内核时选择是否构件到内核中, 在不选择它的情况下, 使用它提供的API的内核部分不需要做任何改动.

    用户空间与内核空间数据交换的方式(1)——debugfs

    Linux内核里的DebugFS

    Linux驱动调试的Debugfs的使用简介

    Linux Debugfs文件系统介绍及使用

    Linux内核里的DebugFS

    Debugging the Linux Kernel with debugfs

    debugfs-seq_file

    Linux Debugfs文件系统介绍及使用

    Linux 文件系统:procfs, sysfs, debugfs 用法简介

    用户空间与内核空间数据交换的方式(1)——debugfs

    Linux 运用debugfs调试方法

    2.4 relayfs文件系统


    relayfs 是一个快速的转发(relay)数据的文件系统, 它以其功能而得名. 它为那些需要从内核空间转发大量数据到用户空间的工具和应用提供了快速有效的转发机制.

    Channelrelayfs 文件系统定义的一个主要概念, 每一个 channel 由一组内核缓存组成, 每一个 CPU 有一个对应于该 channel 的内核缓存, 每一个内核缓存用一个在 relayfs 文件系统中的文件文件表示, 内核使用 relayfs 提供的写函数把需要转发给用户空间的数据快速地写入当前 CPU 上的 channel 内核缓存, 用户空间应用通过标准的文件 I/ O函数在对应的 channel 文件中可以快速地取得这些被转发出的数据 mmap 来. 写入到 channel 中的数据的格式完全取决于内核中创建channel 的模块或子系统.

    relayfs 的用户空间API :

    relayfs 实现了四个标准的文件 I/O 函数, open、mmap、poll和close

    函数描述
    open打开一个 channel 在某一个 CPU 上的缓存对应的文件.
    mmap把打开的 channel 缓存映射到调用者进程的内存空间.
    read读取 channel 缓存, 随后的读操作将看不到被该函数消耗的字节, 如果 channel 的操作模式为非覆盖写, 那么用户空间应用在有内核模块写时仍可以读取, 但是如 channel 的操作模式为覆盖式, 那么在读操作期间如果有内核模块进行写,结果将无法预知, 因此对于覆盖式写的 channel, 用户应当在确认在 channel 的写完全结束后再进行读.
    poll用于通知用户空间应用转发数据跨越了子缓存的边界, 支持的轮询标志有 POLLINPOLLRDNORMPOLLERR
    close关闭 open 函数返回的文件描述符, 如果没有进程或内核模块打开该 channel 缓存, close 函数将释放该channel 缓存

    注意 : 用户态应用在使用上述 API 时必须保证已经挂载了 relayfs 文件系统, 但内核在创建和使用 channel时不需要relayfs 已经挂载. 下面命令将把 relayfs 文件系统挂载到 /mnt/relay.

    用户空间与内核空间数据交换的方式(4)——relayfs

    Relay:一种内核到用户空间的高效数据传输技术

    2.5 seq_file


    一般地, 内核通过在 procfs 文件系统下建立文件来向用户空间提供输出信息, 用户空间可以通过任何文本阅读应用查看该文件信息, 但是 procfs 有一个缺陷, 如果输出内容大于1个内存页, 需要多次读, 因此处理起来很难, 另外, 如果输出太大, 速度比较慢, 有时会出现一些意想不到的情况, Alexander Viro 实现了一套新的功能, 使得内核输出大文件信息更容易, 该功能出现在 2.4.15(包括 2.4.15)以后的所有 2.4 内核以及 2.6 内核中, 尤其是在 2.6 内核中,已经大量地使用了该功能

    用户空间与内核空间数据交换的方式(3)——seq_file

    内核proc文件系统与seq接口(4)—seq_file接口编程浅析

    Linux内核中的seq操作

    seq_file源码分析

    用序列文件(seq_file)接口导出常用数据结构

    seq_file机制

    3 printk


    在内核调试技术之中, 最简单的就是 printk 的使用了, 它的用法和C语言应用程序中的 printf 使用类似, 在应用程序中依靠的是 stdio.h 中的库, 而在 linux 内核中没有这个库, 所以在 linux 内核中, 实现了自己的一套库函数, printk 就是标准的输出函数

    linux内核调试技术之printk

    调整内核printk的打印级别

    linux设备驱动学习笔记–内核调试方法之printk

    4 ftrace && trace-cmd


    4.1 trace && ftrace


    Linux当前版本中, 功能最强大的调试、跟踪手段. 其最基本的功能是提供了动态和静态探测点, 用于探测内核中指定位置上的相关信息.

    静态探测点, 是在内核代码中调用 ftrace 提供的相应接口实现, 称之为静态是因为, 是在内核代码中写死的, 静态编译到内核代码中的, 在内核编译后, 就不能再动态修改. 在开启 ftrace 相关的内核配置选项后, 内核中已经在一些关键的地方设置了静态探测点, 需要使用时, 即可查看到相应的信息.

    动态探测点, 基本原理为 : 利用 mcount 机制, 在内核编译时, 在每个函数入口保留数个字节, 然后在使用 ftrace时, 将保留的字节替换为需要的指令, 比如跳转到需要的执行探测操作的代码。

    ftrace 的作用是帮助开发人员了解 Linux 内核的运行时行为, 以便进行故障调试或性能分析.

    最早 ftrace 是一个 function tracer, 仅能够记录内核的函数调用流程. 如今 ftrace 已经成为一个 framework, 采用 plugin 的方式支持开发人员添加更多种类的 trace 功能.

    FtraceRedHatSteve Rostedt 负责维护. 到 2.6.30 为止, 已经支持的 tracer 包括 :

    Tracer描述
    Function tracer 和 Function graph tracer跟踪函数调用
    Schedule switch tracer跟踪进程调度情况
    Wakeup tracer跟踪进程的调度延迟, 即高优先级进程从进入 ready 状态到获得 CPU 的延迟时间. 该 tracer 只针对实时进程
    Irqsoff tracer当中断被禁止时, 系统无法相应外部事件, 比如键盘和鼠标, 时钟也无法产生 tick 中断. 这意味着系统响应延迟, irqsoff 这个 tracer 能够跟踪并记录内核中哪些函数禁止了中断, 对于其中中断禁止时间最长的, irqsoff 将在 log 文件的第一行标示出来, 从而使开发人员可以迅速定位造成响应延迟的罪魁祸首.
    Preemptoff tracer和前一个 tracer 类似, preemptoff tracer 跟踪并记录禁止内核抢占的函数, 并清晰地显示出禁止抢占时间最长的内核函数.
    Preemptirqsoff tracer同上, 跟踪和记录禁止中断或者禁止抢占的内核函数, 以及禁止时间最长的函数.
    Branch tracer跟踪内核程序中的 likely/unlikely 分支预测命中率情况. Branch tracer 能够记录这些分支语句有多少次预测成功. 从而为优化程序提供线索.
    Hardware branch tracer利用处理器的分支跟踪能力, 实现硬件级别的指令跳转记录. 在 x86 上, 主要利用了 BTS 这个特性.
    Initcall tracer记录系统在 boot 阶段所调用的 init call.
    Mmiotrace tracer记录 memory map IO 的相关信息.
    Power tracer记录系统电源管理相关的信息
    Sysprof tracer缺省情况下, sysprof tracer 每隔 1 msec 对内核进行一次采样,记录函数调用和堆栈信息.
    Kernel memory tracer内存 tracer 主要用来跟踪 slab allocator 的分配情况. 包括 kfree, kmem_cache_allocAPI 的调用情况, 用户程序可以根据 tracer 收集到的信息分析内部碎片情况, 找出内存分配最频繁的代码片断, 等等.
    Workqueue statistical tracer这是一个 statistic tracer, 统计系统中所有的 workqueue 的工作情况, 比如有多少个 work 被插入 workqueue, 多少个已经被执行等. 开发人员可以以此来决定具体的 workqueue 实现, 比如是使用 single threaded workqueue 还是 per cpu workqueue.
    Event tracer跟踪系统事件, 比如 timer, 系统调用, 中断等.

    这里还没有列出所有的 tracer, ftrace 是目前非常活跃的开发领域, 新的 tracer 将不断被加入内核。

    ftrace和它的前端工具trace-cmd(深入了解Linux系统的利器)

    ftrace 简介

    内核性能调试–ftrace

    使用 ftrace 调试 Linux 内核,第 1 部分

    ftrace的使用

    [转]Linux内核跟踪之trace框架分析

    Linux trace使用入门

    4.2 ftrace前端工具trace-cmd


    • trace-cmd 介绍

    trace-cmd 和 开源的 kernelshark 均是内核Ftrace 的前段工具, 用于分分析核性能.

    他们相当于是一个 /sys/kernel/debug/tracing 中文件系统接口的封装, 为用户提供了更加直接和方便的操作.

    • 使用
    #  收集信息
    sudo trace-cmd reord subsystem:tracing 
    
    #  解析结果
    #sudo trace-cmd report
     

      trace-cmd: A front-end for Ftrace

      其本质就是对/sys/kernel/debug/tracing/events 下各个模块进行操作, 收集数据并解析

      5 Kprobe && systemtap


      5.1 内核kprobe机制


      kprobelinux 内核的一个重要特性, 是一个轻量级的内核调试工具, 同时它又是其他一些更高级的内核调试工具(比如 perfsystemtap)的 “基础设施”, 4.0版本的内核中, 强大的 eBPF 特性也寄生于 kprobe 之上, 所以 kprobe 在内核中的地位就可见一斑了.

      Kprobes 提供了一个强行进入任何内核例程并从中断处理器无干扰地收集信息的接口. 使用 Kprobes 可以收集处理器寄存器和全局数据结构等调试信息。开发者甚至可以使用 Kprobes 来修改 寄存器值和全局数据结构的值.

      如何高效地调试内核?

      printk 是一种方法, 但是 printk 终归是毫无选择地全量输出, 某些场景下不实用, 于是你可以试一下tracepoint, 我使能 tracepoint 机制的时候才输出. 对于傻傻地放置 printk 来输出信息的方式, tracepoint 是个进步, 但是 tracepoint 只是内核在某些特定行为(比如进程切换)上部署的一些静态锚点, 这些锚点并不一定是你需要的, 所以你仍然需要自己部署tracepoint, 重新编译内核. 那么 kprobe 的出现就很有必要了, 它可以在运行的内核中动态插入探测点, 执行你预定义的操作.

      它的基本工作机制是 : 用户指定一个探测点, 并把一个用户定义的处理函数关联到该探测点, 当内核执行到该探测点时, 相应的关联函数被执行,然后继续执行正常的代码路径.

      kprobe 实现了三种类型的探测点 : kprobes, jprobeskretprobes(也叫返回探测点). kprobes 是可以被插入到内核的任何指令位置的探测点, jprobes 则只能被插入到一个内核函数的入口, 而 kretprobes 则是在指定的内核函数返回时才被执行.

      kprobe工作原理

      随想录(强大的kprobe)

      kprobe原理解析(一)

      5.2 前端工具systemtap


      SystemTap 是监控和跟踪运行中的 Linux 内核的操作的动态方法. 这句话的关键词是动态, 因为 SystemTap 没有使用工具构建一个特殊的内核, 而是允许您在运行时动态地安装该工具. 它通过一个 Kprobes 的应用编程接口 (API) 来实现该目的.

      SystemTap 与一种名为 DTrace 的老技术相似,该技术源于 Sun Solaris 操作系统. 在 DTrace 中, 开发人员可以用 D 编程语言(C 语言的子集, 但修改为支持跟踪行为)编写脚本. DTrace 脚本包含许多探针和相关联的操作, 这些操作在探针 “触发” 时发生. 例如, 探针可以表示简单的系统调用,也可以表示更加复杂的交互,比如执行特定的代码行

      DTraceSolaris 最引人注目的部分, 所以在其他操作系统中开发它并不奇怪. DTrace 是在 Common Development and Distribution License (CDDL) 之下发行的, 并且被移植到 FreeBSD 操作系统中.

      另一个非常有用的内核跟踪工具是 ProbeVue, 它是 IBMIBM® AIX® 操作系统 6.1 开发的. 您可以使用 ProbeVue 探查系统的行为和性能, 以及提供特定进程的详细信息. 这个工具使用一个标准的内核以动态的方式进行跟踪.

      考虑到 DTraceProbeVue 在各自的操作系统中的巨大作用, 为 Linux 操作系统策划一个实现该功能的开源项目是势不可挡的. SystemTap2005 年开始开发, 它提供与 DTraceProbeVue 类似的功能. 许多社区还进一步完善了它, 包括 Red HatIntelHitachiIBM 等.

      这些解决方案在功能上都是类似的, 在触发探针时使用探针和相关联的操作脚本.

      SystemTap 学习笔记 - 安装篇

      Linux 自检和 SystemTap 用于动态内核分析的接口和语言

      Brendan’s blog Using SystemTap

      内核调试神器SystemTap — 简介与使用(一)

      内核探测工具systemtap简介

      SystemTap Beginner

      使用systemtap调试linux内核

      Ubuntu Kernel Debuginfo

      Linux 下的一个全新的性能测量和调式诊断工具 Systemtap, 第 3 部分: Systemtap

      6 kgdb && kgtp


      6.1 kgdb


      • KDB 和 KGDB 合并, 并进入内核

      KGDB 是大名鼎鼎的内核调试工具, 他是由 KDBKGDB 项目合并而来.

      kdb 是一个Linux系统的内核调试器, 它是由SGI公司开发的遵循GPL许可证的开放源码调试工具. kdb 嵌入在Linux 内核中. 为内核&&驱动程序员提供调试手段. 它适合于调试内核空间的程序代码. 譬如进行设备驱动程序调试. 内核模块的调试等.

      kgdbkdb 现在已经合并了. 对于一个正在运行的kgdb 而言, 可以使用 gdbmonitor 命令来使用 kdb 命令. 比如

      (gdb)gdb monitor ps -A
       

        就可以运行 kdbps 命令了.

        分析一下 kdb 补丁和合入主线的 kdb 有啥不同

        kdbkgdb 合并之后, 也可以使用 kgdbIO 驱动(比如键盘), 但是同时也 kdb也丧失了一些功能. 合并之后的kdb不在支持汇编级的源码调试. 因此它现在也是平台独立的.

        1. kdump和kexec已经被移除。

        2. 从/proc/meninfo中获取的信息比以前少了。

        3. bt命令现在使用的是内核的backtracer,而不是kdb原来使用的反汇编。

        4. 合并之后的kdb不在具有原来的反汇编(id命令)

        总结一下 : kdbkgdb 合并之后,系统中对这两种调试方式几乎没有了明显的界限,比如通过串口进行远程访问的时候,可以使用 kgdb 命令, 也可以使用 kdb 命令(使用gdb monitor实现)

        6.2 KGTP


        KGTP 是一个 实时 轻量级 Linux 调试器 和 跟踪器. 使用 KGTP

        使用 KGTP 不需要在 Linux 内核上打 PATCH 或者重新编译, 只要编译KGTP模块并 insmod 就可以.

        其让 Linux 内核提供一个远程 GDB 调试接口, 于是在本地或者远程的主机上的GDB可以在不需要停止内核的情况下用 GDB tracepoint 和其他一些功能 调试 和 跟踪 Linux.

        即使板子上没有 GDB 而且其没有可用的远程接口, KGTP 也可以用离线调试的功能调试内核(见http://code.google.com/p/kgtp/wiki/HOWTOCN#/sys/kernel/debug/gtpframe和离线调试)。

        KGTP支持 X86-32 , X86-64 , MIPS 和 ARM 。
        KGTP在Linux内核 2.6.18到upstream 上都被测试过。
        而且还可以用在 Android 上(见 HowToUseKGTPinAndroid)

        github-KGTP

        KGTP内核调试使用

        KGTP中增加对GDB命令“set trace-buffer-size”的支持 - Week 5

        7 perf


        Perf 是用来进行软件性能分析的工具。
        通过它, 应用程序可以利用 PMU, tracepoint 和内核中的特殊计数器来进行性能统计. 它不但可以分析指定应用程序的性能问题 (per thread). 也可以用来分析内核的性能问题, 当然也可以同时分析应用代码和内核,从而全面理解应用程序中的性能瓶颈.

        最初的时候, 它叫做 Performance counter, 在 2.6.31 中第一次亮相. 此后他成为内核开发最为活跃的一个领域. 在 2.6.32 中它正式改名为 Performance Event, 因为 perf 已不再仅仅作为 PMU 的抽象, 而是能够处理所有的性能相关的事件.

        使用 perf, 您可以分析程序运行期间发生的硬件事件,比如 instructions retired , processor clock cycles 等; 您也可以分析软件事件, 比如 Page Fault 和进程切换。
        这使得 Perf 拥有了众多的性能分析能力, 举例来说,使用 Perf 可以计算每个时钟周期内的指令数, 称为 IPC, IPC 偏低表明代码没有很好地利用 CPU.

        Perf 还可以对程序进行函数级别的采样, 从而了解程序的性能瓶颈究竟在哪里等等. Perf 还可以替代 strace, 可以添加动态内核 probe 点. 还可以做 benchmark 衡量调度器的好坏.

        人们或许会称它为进行性能分析的”瑞士军刀”, 但我不喜欢这个比喻, 我觉得 perf 应该是一把世间少有的倚天剑.
        金庸笔下的很多人都有对宝刀的癖好, 即便本领低微不配拥有, 但是喜欢, 便无可奈何. 我恐怕正如这些人一样, 因此进了酒馆客栈, 见到相熟或者不相熟的人, 就要兴冲冲地要讲讲那倚天剑的故事.

        Perf – Linux下的系统性能调优工具,第 1 部分

        perf Examples

        改进版的perf, Performance analysis tools based on Linux perf_events (aka perf) and ftrace

        Perf使用教程

        linux下的内核测试工具——perf使用简介

        perf 移植

        8 其他Tracer工具


        8.1 LTTng


        LTTng 是一个 Linux 平台开源的跟踪工具, 是一套软件组件, 可允许跟踪 Linux 内核和用户程序, 并控制跟踪会话(开始/停止跟踪、启动/停止事件 等等). 这些组件被绑定如下三个包 :

        描述
        LTTng-tools库和用于跟踪会话的命令行接口
        LTTng-modules允许用 LTTng 跟踪 LinuxLinux 内核模块
        LTTng-UST用户空间跟踪库


        Linux 平台开源的跟踪工具:LTTng

        用 lttng 跟踪内核

        LTTng and LTTng project

        8.2 eBPF


        extended Berkeley Packet Filter(eBPF)是一个可以在事件上运行程序的高效内核虚拟机(JIT)。它可能最终会提供 ftrace 和 perf_events 的内核编程,并强化其他的 tracer。这是 Alexei Starovoitov 目前正在开发的,还没有完全集成,但是从4.1开始已经对一些优秀的工具有足够的内核支持了,如块设备I/O的延迟热图。可参考其主要作者 Alexei Starovoitov 的BPF slides和eBPF samples。

        8.3 Ktap


        ktap 在过去是一款前景很好的 tracer,它使用内核中的 lua 虚拟机处理,在没有调试信息的情况下在嵌入式设备上运行的很好。它分为几个步骤,并在有一段时间似乎超过了 Linux 上所有的追踪器。然后 eBPF 开始进行内核集成,而 ktap 的集成在它可以使用 eBPF 替代它自己的虚拟机后才开始。因为 eBPF 仍将持续集成几个月,ktap 开发者要继续等上一段时间。我希??今年晚些时候它能重新开发。

        8.4 dtrace4linux


        dtrace4linux 主要是 Paul Fox 一个人在业余时间完成的,它是 Sun DTrace 的 Linux 版本。它引入瞩目,还有一些 provider 可以运行,但是从某种程度上来说还不完整,更多的是一种实验性的工具(不安全)。我认为,顾忌到许可问题,人们会小心翼翼的为 dtrace4linux 贡献代码:由于当年 Sun 开源DTrace 使用的是 CDDL 协议,而 dtrace4linux 也不大可能最终进入 Linux kernel。Paul 的方法很可能会使其成为一个 add-on。我很乐意看到 Linux 平台上的 DTrace 和这个项目的完成,我认为当我加入 Netflix 后将会花些时间来协助完成这个项目。然而,我还是要继续使用内置的 tracers,如 ftrace 和 perf_events。

        8.5 OL DTrace


        Oracle Linux DTrace为了将 DTrace 引入 Linux,特别是 Oracle Linux,做出了很大的努力。这些年来发布的多个版本表明了它的稳定进展。开发者们以一种对这个项目的前景看好的态度谈论着改进 DTrace 测试套件。很多有用的 provider 已经完成了,如:syscall, profile, sdt, proc, sched 以及 USDT。我很期待 fbt(function boundary tracing, 用于内核动态跟踪)的完成,它是 Linux 内核上非常棒的 provider。OL DTrace 最终的成功将取决于人们对运行 Oracle Linux(为技术支持付费)有多大兴趣,另一方面取决于它是否完全开源:它的内核元件是开源的,而我没有看到它的用户级别代码。

        8.6 sysdig


        sysdig是一个使用类tcpdump语法来操作系统事件的新tracer,它使用lua提交进程。它很优秀,它见证了系统跟踪领域的变革。它的局限性在于它只在当前进行系统调用,在提交进行时将所有事件转储为用户级别。你可以使用系统调用做很多事情,然而我还是很希望它能支持跟踪点、kprobe和uprobe。我还期待它能支持eBPF做内核摘要。目前,sysdig开发者正在增加容器支持。留意这些内容。


        知识共享许可协议本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可, 转载请注明出处, 谢谢合作.
        因本人技术水平和知识面有限, 内容如有纰漏或者需要修正的地方, 欢迎大家指正, 也欢迎大家提供一些其他好的调试工具以供收录, 鄙人在此谢谢啦

        展开全文
      • Linux内核调试的方式以及工具集锦

        万次阅读 多人点赞 2017-04-01 21:31:55
        GitHub Linux内核调试的方式以及工具集锦 LDD-LinuxDeviceDrivers/study/debug 本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可, 转载请注明出处, 谢谢合作 因本人技术水平和知识面...
        CSDNGitHub
        Linux内核调试的方式以及工具集锦LDD-LinuxDeviceDrivers/study/debug


        知识共享许可协议
        本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可, 转载请注明出处, 谢谢合作
        因本人技术水平和知识面有限, 内容如有纰漏或者需要修正的地方, 欢迎大家指正, 也欢迎大家提供一些其他好的调试工具以供收录, 鄙人在此谢谢啦

        "调试难度本来就是写代码的两倍. 因此, 如果你写代码的时候聪明用尽, 根据定义, 你就没有能耐去调试它了."
                --Brian Kernighan

        1 内核调试以及工具总结


        内核总是那么捉摸不透, 内核也会犯错, 但是调试却不能像用户空间程序那样, 为此内核开发者为我们提供了一系列的工具和系统来支持内核的调试.

        内核的调试, 其本质是内核空间与用户空间的数据交换, 内核开发者们提供了多样的形式来完成这一功能.

        工具描述
        debugfs等文件系统提供了 procfs, sysfs, debugfs以及 relayfs 来与用户空间进行数据交互, 尤其是 debugfs, 这是内核开发者们实现的专门用来调试的文件系统接口. 其他的工具或者接口, 多数都依赖于 debugfs.
        printk强大的输出系统, 没有什么逻辑上的bug是用PRINT解决不了的
        ftrace以及其前端工具trace-cmd等内核提供了 ftrace 工具来实现检查点, 事件等的检测, 这一框架依赖于 debugfs, 他在 debugfs 中的 tracing 子系统中为用户提供了丰富的操作接口, 我们可以通过该系统对内核实现检测和分析. 功能虽然强大, 但是其操作并不是很简单, 因此使用者们为实现了 trace-cmd 等前端工具, 简化了 ftrace 的使用.
        kprobe以及更强大的systemtap内核中实现的 krpobe 通过类似与代码劫持一样的技巧, 在内核的代码或者函数执行前后, 强制加上某些调试信息, 可以很巧妙的完成调试工作, 这是一项先进的调试技术, 但是仍然有觉得它不够好, 劫持代码需要用驱动的方式编译并加载, 能不能通过脚本的方式自动生成劫持代码并自动加载和收集数据, 于是systemtap 出现了. 通过 systemtap 用户只需要编写脚本, 就可以完成调试并动态分析内核
        kgdb && kgtpKGDB 是大名鼎鼎的内核调试工具, KGTP则通过驱动的方式强化了 gdb的功能, 诸如tracepoint, 打印内核变量等.
        perferf Event是一款随 inux内核代码一同发布和维护的性能诊断工具, 核社区维护和发展. Perf 不仅可以用于应用程序的性能统计分析, 也可以应用于内核代码的性能统计和分析. 得益于其优秀的体系结构设计, 越来越多的新功能被加入 Perf, 使其已经成为一个多功能的性能统计工具集
        LTTngLTTng 是一个 Linux 平台开源的跟踪工具, 是一套软件组件, 可允许跟踪 Linux 内核和用户程序, 并控制跟踪会话(开始/停止跟踪、启动/停止事件 等等).

        2 用户空间与内核空间数据交换的文件系统


        内核中有三个常用的伪文件系统: procfs, debugfs和sysfs.

        文件系统描述
        procfsThe proc filesystem is a pseudo-filesystem which provides an interface to kernel data structures.
        sysfsThe filesystem for exporting kernel objects.
        debugfsDebugfs exists as a simple way for kernel developers to make information available to user space.
        relayfsA significantly streamlined version of relayfs was recently accepted into the -mm kernel tree.

        它们都用于Linux内核和用户空间的数据交换, 但是适用的场景有所差异:

        • procfs 历史最早, 最初就是用来跟内核交互的唯一方式, 用来获取处理器、内存、设备驱动、进程等各种信息.

        • sysfskobject 框架紧密联系, 而 kobject 是为设备驱动模型而存在的, 所以 sysfs 是为设备驱动服务的.

        • debugfs 从名字来看就是为 debug 而生, 所以更加灵活.

        • relayfs 是一个快速的转发 (relay) 数据的文件系统, 它以其功能而得名. 它为那些需要从内核空间转发大量数据到用户空间的工具和应用提供了快速有效的转发机制.

        在 Linux 下用户空间与内核空间数据交换的方式, 第 2 部分: procfs、seq_file、debugfs和relayfs

        Linux 文件系统:procfs, sysfs, debugfs 用法简介

        2.1 procfs文件系统


        • ProcFs 介绍`

        procfs 是比较老的一种用户态与内核态的数据交换方式, 内核的很多数据都是通过这种方式出口给用户的, 内核的很多参数也是通过这种方式来让用户方便设置的. 除了 sysctl 出口到 /proc 下的参数, procfs 提供的大部分内核参数是只读的. 实际上, 很多应用严重地依赖于procfs, 因此它几乎是必不可少的组件. 前面部分的几个例子实际上已经使用它来出口内核数据, 但是并没有讲解如何使用, 本节将讲解如何使用procfs.

        • 参考资料

        用户空间与内核空间数据交换的方式(2)——procfs

        2.2 sysfs文件系统


        内核子系统或设备驱动可以直接编译到内核, 也可以编译成模块, 编译到内核, 使用前一节介绍的方法通过内核启动参数来向它们传递参数, 如果编译成模块, 则可以通过命令行在插入模块时传递参数, 或者在运行时, 通过 sysfs 来设置或读取模块数据.

        Sysfs 是一个基于内存的文件系统, 实际上它基于ramfs, sysfs 提供了一种把内核数据结构, 它们的属性以及属性与数据结构的联系开放给用户态的方式, 它与 kobject 子系统紧密地结合在一起, 因此内核开发者不需要直接使用它, 而是内核的各个子系统使用它. 用户要想使用 sysfs 读取和设置内核参数, 仅需装载 sysfs 就可以通过文件操作应用来读取和设置内核通过 sysfs 开放给用户的各个参数:

        mkdir -p /sysfs
        mount -t sysfs sysfs /sysfs

        注意, 不要把 sysfssysctl 混淆, sysctl 是内核的一些控制参数, 其目的是方便用户对内核的行为进行控制, 而 sysfs 仅仅是把内核的 kobject 对象的层次关系与属性开放给用户查看, 因此 sysfs 的绝大部分是只读的, 模块作为一个 kobject 也被出口到 sysfs, 模块参数则是作为模块属性出口的, 内核实现者为模块的使用提供了更灵活的方式, 允许用户设置模块参数在 sysfs 的可见性并允许用户在编写模块时设置这些参数在 sysfs 下的访问权限, 然后用户就可以通过 sysfs 来查看和设置模块参数, 从而使得用户能在模块运行时控制模块行为.

        用户空间与内核空间数据交换的方式(6)——模块参数与sysfs

        2.3 debugfs文件系统


        内核开发者经常需要向用户空间应用输出一些调试信息, 在稳定的系统中可能根本不需要这些调试信息, 但是在开发过程中, 为了搞清楚内核的行为, 调试信息非常必要, printk可能是用的最多的, 但它并不是最好的, 调试信息只是在开发中用于调试, 而 printk 将一直输出, 因此开发完毕后需要清除不必要的 printk 语句, 另外如果开发者希望用户空间应用能够改变内核行为时, printk 就无法实现.

        因此, 需要一种新的机制, 那只有在需要的时候使用, 它在需要时通过在一个虚拟文件系统中创建一个或多个文件来向用户空间应用提供调试信息.

        有几种方式可以实现上述要求:

        • 使用 procfs, 在 /proc 创建文件输出调试信息, 但是 procfs 对于大于一个内存页(对于 x864K)的输出比较麻烦, 而且速度慢, 有时回出现一些意想不到的问题.

        • 使用 sysfs( 2.6 内核引入的新的虚拟文件系统), 在很多情况下, 调试信息可以存放在那里, 但是sysfs主要用于系统管理,它希望每一个文件对应内核的一个变量,如果使用它输出复杂的数据结构或调试信息是非常困难的.

        • 使用 libfs 创建一个新的文件系统, 该方法极其灵活, 开发者可以为新文件系统设置一些规则, 使用 libfs 使得创建新文件系统更加简单, 但是仍然超出了一个开发者的想象.

        为了使得开发者更加容易使用这样的机制, Greg Kroah-Hartman 开发了 debugfs(在 2.6.11 中第一次引入), 它是一个虚拟文件系统, 专门用于输出调试信息, 该文件系统非常小, 很容易使用, 可以在配置内核时选择是否构件到内核中, 在不选择它的情况下, 使用它提供的API的内核部分不需要做任何改动.

        用户空间与内核空间数据交换的方式(1)——debugfs

        Linux内核里的DebugFS

        Linux驱动调试的Debugfs的使用简介

        Linux Debugfs文件系统介绍及使用

        Linux内核里的DebugFS

        Debugging the Linux Kernel with debugfs

        debugfs-seq_file

        Linux Debugfs文件系统介绍及使用

        Linux 文件系统:procfs, sysfs, debugfs 用法简介

        用户空间与内核空间数据交换的方式(1)——debugfs

        Linux 运用debugfs调试方法

        2.4 relayfs文件系统


        relayfs 是一个快速的转发(relay)数据的文件系统, 它以其功能而得名. 它为那些需要从内核空间转发大量数据到用户空间的工具和应用提供了快速有效的转发机制.

        Channelrelayfs 文件系统定义的一个主要概念, 每一个 channel 由一组内核缓存组成, 每一个 CPU 有一个对应于该 channel 的内核缓存, 每一个内核缓存用一个在 relayfs 文件系统中的文件文件表示, 内核使用 relayfs 提供的写函数把需要转发给用户空间的数据快速地写入当前 CPU 上的 channel 内核缓存, 用户空间应用通过标准的文件 I/ O函数在对应的 channel 文件中可以快速地取得这些被转发出的数据 mmap 来. 写入到 channel 中的数据的格式完全取决于内核中创建channel 的模块或子系统.

        relayfs 的用户空间API :

        relayfs 实现了四个标准的文件 I/O 函数, open、mmap、poll和close

        函数描述
        open打开一个 channel 在某一个 CPU 上的缓存对应的文件.
        mmap把打开的 channel 缓存映射到调用者进程的内存空间.
        read读取 channel 缓存, 随后的读操作将看不到被该函数消耗的字节, 如果 channel 的操作模式为非覆盖写, 那么用户空间应用在有内核模块写时仍可以读取, 但是如 channel 的操作模式为覆盖式, 那么在读操作期间如果有内核模块进行写,结果将无法预知, 因此对于覆盖式写的 channel, 用户应当在确认在 channel 的写完全结束后再进行读.
        poll用于通知用户空间应用转发数据跨越了子缓存的边界, 支持的轮询标志有 POLLINPOLLRDNORMPOLLERR
        close关闭 open 函数返回的文件描述符, 如果没有进程或内核模块打开该 channel 缓存, close 函数将释放该channel 缓存

        注意 : 用户态应用在使用上述 API 时必须保证已经挂载了 relayfs 文件系统, 但内核在创建和使用 channel时不需要relayfs 已经挂载. 下面命令将把 relayfs 文件系统挂载到 /mnt/relay.

        用户空间与内核空间数据交换的方式(4)——relayfs

        Relay:一种内核到用户空间的高效数据传输技术

        2.5 seq_file


        一般地, 内核通过在 procfs 文件系统下建立文件来向用户空间提供输出信息, 用户空间可以通过任何文本阅读应用查看该文件信息, 但是 procfs 有一个缺陷, 如果输出内容大于1个内存页, 需要多次读, 因此处理起来很难, 另外, 如果输出太大, 速度比较慢, 有时会出现一些意想不到的情况, Alexander Viro 实现了一套新的功能, 使得内核输出大文件信息更容易, 该功能出现在 2.4.15(包括 2.4.15)以后的所有 2.4 内核以及 2.6 内核中, 尤其是在 2.6 内核中,已经大量地使用了该功能

        用户空间与内核空间数据交换的方式(3)——seq_file

        内核proc文件系统与seq接口(4)—seq_file接口编程浅析

        Linux内核中的seq操作

        seq_file源码分析

        用序列文件(seq_file)接口导出常用数据结构

        seq_file机制

        3 printk


        在内核调试技术之中, 最简单的就是 printk 的使用了, 它的用法和C语言应用程序中的 printf 使用类似, 在应用程序中依靠的是 stdio.h 中的库, 而在 linux 内核中没有这个库, 所以在 linux 内核中, 实现了自己的一套库函数, printk 就是标准的输出函数

        linux内核调试技术之printk

        调整内核printk的打印级别

        linux设备驱动学习笔记–内核调试方法之printk

        4 ftrace && trace-cmd


        4.1 trace && ftrace


        Linux当前版本中, 功能最强大的调试、跟踪手段. 其最基本的功能是提供了动态和静态探测点, 用于探测内核中指定位置上的相关信息.

        静态探测点, 是在内核代码中调用 ftrace 提供的相应接口实现, 称之为静态是因为, 是在内核代码中写死的, 静态编译到内核代码中的, 在内核编译后, 就不能再动态修改. 在开启 ftrace 相关的内核配置选项后, 内核中已经在一些关键的地方设置了静态探测点, 需要使用时, 即可查看到相应的信息.

        动态探测点, 基本原理为 : 利用 mcount 机制, 在内核编译时, 在每个函数入口保留数个字节, 然后在使用 ftrace时, 将保留的字节替换为需要的指令, 比如跳转到需要的执行探测操作的代码。

        ftrace 的作用是帮助开发人员了解 Linux 内核的运行时行为, 以便进行故障调试或性能分析.

        最早 ftrace 是一个 function tracer, 仅能够记录内核的函数调用流程. 如今 ftrace 已经成为一个 framework, 采用 plugin 的方式支持开发人员添加更多种类的 trace 功能.

        FtraceRedHatSteve Rostedt 负责维护. 到 2.6.30 为止, 已经支持的 tracer 包括 :

        Tracer描述
        Function tracer 和 Function graph tracer跟踪函数调用
        Schedule switch tracer跟踪进程调度情况
        Wakeup tracer跟踪进程的调度延迟, 即高优先级进程从进入 ready 状态到获得 CPU 的延迟时间. 该 tracer 只针对实时进程
        Irqsoff tracer当中断被禁止时, 系统无法相应外部事件, 比如键盘和鼠标, 时钟也无法产生 tick 中断. 这意味着系统响应延迟, irqsoff 这个 tracer 能够跟踪并记录内核中哪些函数禁止了中断, 对于其中中断禁止时间最长的, irqsoff 将在 log 文件的第一行标示出来, 从而使开发人员可以迅速定位造成响应延迟的罪魁祸首.
        Preemptoff tracer和前一个 tracer 类似, preemptoff tracer 跟踪并记录禁止内核抢占的函数, 并清晰地显示出禁止抢占时间最长的内核函数.
        Preemptirqsoff tracer同上, 跟踪和记录禁止中断或者禁止抢占的内核函数, 以及禁止时间最长的函数.
        Branch tracer跟踪内核程序中的 likely/unlikely 分支预测命中率情况. Branch tracer 能够记录这些分支语句有多少次预测成功. 从而为优化程序提供线索.
        Hardware branch tracer利用处理器的分支跟踪能力, 实现硬件级别的指令跳转记录. 在 x86 上, 主要利用了 BTS 这个特性.
        Initcall tracer记录系统在 boot 阶段所调用的 init call.
        Mmiotrace tracer记录 memory map IO 的相关信息.
        Power tracer记录系统电源管理相关的信息
        Sysprof tracer缺省情况下, sysprof tracer 每隔 1 msec 对内核进行一次采样,记录函数调用和堆栈信息.
        Kernel memory tracer内存 tracer 主要用来跟踪 slab allocator 的分配情况. 包括 kfree, kmem_cache_allocAPI 的调用情况, 用户程序可以根据 tracer 收集到的信息分析内部碎片情况, 找出内存分配最频繁的代码片断, 等等.
        Workqueue statistical tracer这是一个 statistic tracer, 统计系统中所有的 workqueue 的工作情况, 比如有多少个 work 被插入 workqueue, 多少个已经被执行等. 开发人员可以以此来决定具体的 workqueue 实现, 比如是使用 single threaded workqueue 还是 per cpu workqueue.
        Event tracer跟踪系统事件, 比如 timer, 系统调用, 中断等.

        这里还没有列出所有的 tracer, ftrace 是目前非常活跃的开发领域, 新的 tracer 将不断被加入内核。

        ftrace和它的前端工具trace-cmd(深入了解Linux系统的利器)

        ftrace 简介

        内核性能调试–ftrace

        使用 ftrace 调试 Linux 内核,第 1 部分

        ftrace的使用

        [转]Linux内核跟踪之trace框架分析

        Linux trace使用入门

        4.2 ftrace前端工具trace-cmd


        • trace-cmd 介绍

        trace-cmd 和 开源的 kernelshark 均是内核Ftrace 的前段工具, 用于分分析核性能.

        他们相当于是一个 /sys/kernel/debug/tracing 中文件系统接口的封装, 为用户提供了更加直接和方便的操作.

        • 使用
        #  收集信息
        sudo trace-cmd reord subsystem:tracing 
        
        #  解析结果
        #sudo trace-cmd report

        trace-cmd: A front-end for Ftrace

        其本质就是对/sys/kernel/debug/tracing/events 下各个模块进行操作, 收集数据并解析

        5 Kprobe && systemtap


        5.1 内核kprobe机制


        kprobelinux 内核的一个重要特性, 是一个轻量级的内核调试工具, 同时它又是其他一些更高级的内核调试工具(比如 perfsystemtap)的 “基础设施”, 4.0版本的内核中, 强大的 eBPF 特性也寄生于 kprobe 之上, 所以 kprobe 在内核中的地位就可见一斑了.

        Kprobes 提供了一个强行进入任何内核例程并从中断处理器无干扰地收集信息的接口. 使用 Kprobes 可以收集处理器寄存器和全局数据结构等调试信息。开发者甚至可以使用 Kprobes 来修改 寄存器值和全局数据结构的值.

        如何高效地调试内核?

        printk 是一种方法, 但是 printk 终归是毫无选择地全量输出, 某些场景下不实用, 于是你可以试一下tracepoint, 我使能 tracepoint 机制的时候才输出. 对于傻傻地放置 printk 来输出信息的方式, tracepoint 是个进步, 但是 tracepoint 只是内核在某些特定行为(比如进程切换)上部署的一些静态锚点, 这些锚点并不一定是你需要的, 所以你仍然需要自己部署tracepoint, 重新编译内核. 那么 kprobe 的出现就很有必要了, 它可以在运行的内核中动态插入探测点, 执行你预定义的操作.

        它的基本工作机制是 : 用户指定一个探测点, 并把一个用户定义的处理函数关联到该探测点, 当内核执行到该探测点时, 相应的关联函数被执行,然后继续执行正常的代码路径.

        kprobe 实现了三种类型的探测点 : kprobes, jprobeskretprobes(也叫返回探测点). kprobes 是可以被插入到内核的任何指令位置的探测点, jprobes 则只能被插入到一个内核函数的入口, 而 kretprobes 则是在指定的内核函数返回时才被执行.

        kprobe工作原理

        随想录(强大的kprobe)

        kprobe原理解析(一)

        5.2 前端工具systemtap


        SystemTap 是监控和跟踪运行中的 Linux 内核的操作的动态方法. 这句话的关键词是动态, 因为 SystemTap 没有使用工具构建一个特殊的内核, 而是允许您在运行时动态地安装该工具. 它通过一个 Kprobes 的应用编程接口 (API) 来实现该目的.

        SystemTap 与一种名为 DTrace 的老技术相似,该技术源于 Sun Solaris 操作系统. 在 DTrace 中, 开发人员可以用 D 编程语言(C 语言的子集, 但修改为支持跟踪行为)编写脚本. DTrace 脚本包含许多探针和相关联的操作, 这些操作在探针 “触发” 时发生. 例如, 探针可以表示简单的系统调用,也可以表示更加复杂的交互,比如执行特定的代码行

        DTraceSolaris 最引人注目的部分, 所以在其他操作系统中开发它并不奇怪. DTrace 是在 Common Development and Distribution License (CDDL) 之下发行的, 并且被移植到 FreeBSD 操作系统中.

        另一个非常有用的内核跟踪工具是 ProbeVue, 它是 IBMIBM® AIX® 操作系统 6.1 开发的. 您可以使用 ProbeVue 探查系统的行为和性能, 以及提供特定进程的详细信息. 这个工具使用一个标准的内核以动态的方式进行跟踪.

        考虑到 DTraceProbeVue 在各自的操作系统中的巨大作用, 为 Linux 操作系统策划一个实现该功能的开源项目是势不可挡的. SystemTap2005 年开始开发, 它提供与 DTraceProbeVue 类似的功能. 许多社区还进一步完善了它, 包括 Red HatIntelHitachiIBM 等.

        这些解决方案在功能上都是类似的, 在触发探针时使用探针和相关联的操作脚本.

        SystemTap 学习笔记 - 安装篇

        Linux 自检和 SystemTap 用于动态内核分析的接口和语言

        Brendan’s blog Using SystemTap

        内核调试神器SystemTap — 简介与使用(一)

        内核探测工具systemtap简介

        SystemTap Beginner

        使用systemtap调试linux内核

        Ubuntu Kernel Debuginfo

        Linux 下的一个全新的性能测量和调式诊断工具 Systemtap, 第 3 部分: Systemtap

        6 kgdb && kgtp


        6.1 kgdb


        • KDB 和 KGDB 合并, 并进入内核

        KGDB 是大名鼎鼎的内核调试工具, 他是由 KDBKGDB 项目合并而来.

        kdb 是一个Linux系统的内核调试器, 它是由SGI公司开发的遵循GPL许可证的开放源码调试工具. kdb 嵌入在Linux 内核中. 为内核&&驱动程序员提供调试手段. 它适合于调试内核空间的程序代码. 譬如进行设备驱动程序调试. 内核模块的调试等.

        kgdbkdb 现在已经合并了. 对于一个正在运行的kgdb 而言, 可以使用 gdbmonitor 命令来使用 kdb 命令. 比如

        (gdb)gdb monitor ps -A

        就可以运行 kdbps 命令了.

        分析一下 kdb 补丁和合入主线的 kdb 有啥不同

        kdbkgdb 合并之后, 也可以使用 kgdbIO 驱动(比如键盘), 但是同时也 kdb也丧失了一些功能. 合并之后的kdb不在支持汇编级的源码调试. 因此它现在也是平台独立的.

        1. kdump和kexec已经被移除。

        2. 从/proc/meninfo中获取的信息比以前少了。

        3. bt命令现在使用的是内核的backtracer,而不是kdb原来使用的反汇编。

        4. 合并之后的kdb不在具有原来的反汇编(id命令)

        总结一下 : kdbkgdb 合并之后,系统中对这两种调试方式几乎没有了明显的界限,比如通过串口进行远程访问的时候,可以使用 kgdb 命令, 也可以使用 kdb 命令(使用gdb monitor实现)

        6.2 KGTP


        KGTP 是一个 实时 轻量级 Linux 调试器 和 跟踪器. 使用 KGTP

        使用 KGTP 不需要在 Linux 内核上打 PATCH 或者重新编译, 只要编译KGTP模块并 insmod 就可以.

        其让 Linux 内核提供一个远程 GDB 调试接口, 于是在本地或者远程的主机上的GDB可以在不需要停止内核的情况下用 GDB tracepoint 和其他一些功能 调试 和 跟踪 Linux.

        即使板子上没有 GDB 而且其没有可用的远程接口, KGTP 也可以用离线调试的功能调试内核(见http://code.google.com/p/kgtp/wiki/HOWTOCN#/sys/kernel/debug/gtpframe和离线调试)。

        KGTP支持 X86-32 , X86-64 , MIPS 和 ARM 。
        KGTP在Linux内核 2.6.18到upstream 上都被测试过。
        而且还可以用在 Android 上(见 HowToUseKGTPinAndroid)

        github-KGTP

        KGTP内核调试使用

        KGTP中增加对GDB命令“set trace-buffer-size”的支持 - Week 5

        7 perf


        Perf 是用来进行软件性能分析的工具。
        通过它, 应用程序可以利用 PMU, tracepoint 和内核中的特殊计数器来进行性能统计. 它不但可以分析指定应用程序的性能问题 (per thread). 也可以用来分析内核的性能问题, 当然也可以同时分析应用代码和内核,从而全面理解应用程序中的性能瓶颈.

        最初的时候, 它叫做 Performance counter, 在 2.6.31 中第一次亮相. 此后他成为内核开发最为活跃的一个领域. 在 2.6.32 中它正式改名为 Performance Event, 因为 perf 已不再仅仅作为 PMU 的抽象, 而是能够处理所有的性能相关的事件.

        使用 perf, 您可以分析程序运行期间发生的硬件事件,比如 instructions retired , processor clock cycles 等; 您也可以分析软件事件, 比如 Page Fault 和进程切换。
        这使得 Perf 拥有了众多的性能分析能力, 举例来说,使用 Perf 可以计算每个时钟周期内的指令数, 称为 IPC, IPC 偏低表明代码没有很好地利用 CPU.

        Perf 还可以对程序进行函数级别的采样, 从而了解程序的性能瓶颈究竟在哪里等等. Perf 还可以替代 strace, 可以添加动态内核 probe 点. 还可以做 benchmark 衡量调度器的好坏.

        人们或许会称它为进行性能分析的”瑞士军刀”, 但我不喜欢这个比喻, 我觉得 perf 应该是一把世间少有的倚天剑.
        金庸笔下的很多人都有对宝刀的癖好, 即便本领低微不配拥有, 但是喜欢, 便无可奈何. 我恐怕正如这些人一样, 因此进了酒馆客栈, 见到相熟或者不相熟的人, 就要兴冲冲地要讲讲那倚天剑的故事.

        Perf – Linux下的系统性能调优工具,第 1 部分

        perf Examples

        改进版的perf, Performance analysis tools based on Linux perf_events (aka perf) and ftrace

        Perf使用教程

        linux下的内核测试工具——perf使用简介

        perf 移植

        8 其他Tracer工具


        8.1 LTTng


        LTTng 是一个 Linux 平台开源的跟踪工具, 是一套软件组件, 可允许跟踪 Linux 内核和用户程序, 并控制跟踪会话(开始/停止跟踪、启动/停止事件 等等). 这些组件被绑定如下三个包 :

        描述
        LTTng-tools库和用于跟踪会话的命令行接口
        LTTng-modules允许用 LTTng 跟踪 LinuxLinux 内核模块
        LTTng-UST用户空间跟踪库


        Linux 平台开源的跟踪工具:LTTng

        用 lttng 跟踪内核

        LTTng and LTTng project

        8.2 eBPF


        extended Berkeley Packet Filter(eBPF)是一个可以在事件上运行程序的高效内核虚拟机(JIT)。它可能最终会提供 ftrace 和 perf_events 的内核编程,并强化其他的 tracer。这是 Alexei Starovoitov 目前正在开发的,还没有完全集成,但是从4.1开始已经对一些优秀的工具有足够的内核支持了,如块设备I/O的延迟热图。可参考其主要作者 Alexei Starovoitov 的BPF slides和eBPF samples。

        8.3 Ktap


        ktap 在过去是一款前景很好的 tracer,它使用内核中的 lua 虚拟机处理,在没有调试信息的情况下在嵌入式设备上运行的很好。它分为几个步骤,并在有一段时间似乎超过了 Linux 上所有的追踪器。然后 eBPF 开始进行内核集成,而 ktap 的集成在它可以使用 eBPF 替代它自己的虚拟机后才开始。因为 eBPF 仍将持续集成几个月,ktap 开发者要继续等上一段时间。我希??今年晚些时候它能重新开发。

        8.4 dtrace4linux


        dtrace4linux 主要是 Paul Fox 一个人在业余时间完成的,它是 Sun DTrace 的 Linux 版本。它引入瞩目,还有一些 provider 可以运行,但是从某种程度上来说还不完整,更多的是一种实验性的工具(不安全)。我认为,顾忌到许可问题,人们会小心翼翼的为 dtrace4linux 贡献代码:由于当年 Sun 开源DTrace 使用的是 CDDL 协议,而 dtrace4linux 也不大可能最终进入 Linux kernel。Paul 的方法很可能会使其成为一个 add-on。我很乐意看到 Linux 平台上的 DTrace 和这个项目的完成,我认为当我加入 Netflix 后将会花些时间来协助完成这个项目。然而,我还是要继续使用内置的 tracers,如 ftrace 和 perf_events。

        8.5 OL DTrace


        Oracle Linux DTrace为了将 DTrace 引入 Linux,特别是 Oracle Linux,做出了很大的努力。这些年来发布的多个版本表明了它的稳定进展。开发者们以一种对这个项目的前景看好的态度谈论着改进 DTrace 测试套件。很多有用的 provider 已经完成了,如:syscall, profile, sdt, proc, sched 以及 USDT。我很期待 fbt(function boundary tracing, 用于内核动态跟踪)的完成,它是 Linux 内核上非常棒的 provider。OL DTrace 最终的成功将取决于人们对运行 Oracle Linux(为技术支持付费)有多大兴趣,另一方面取决于它是否完全开源:它的内核元件是开源的,而我没有看到它的用户级别代码。

        8.6 sysdig


        sysdig是一个使用类tcpdump语法来操作系统事件的新tracer,它使用lua提交进程。它很优秀,它见证了系统跟踪领域的变革。它的局限性在于它只在当前进行系统调用,在提交进行时将所有事件转储为用户级别。你可以使用系统调用做很多事情,然而我还是很希望它能支持跟踪点、kprobe和uprobe。我还期待它能支持eBPF做内核摘要。目前,sysdig开发者正在增加容器支持。留意这些内容。


        知识共享许可协议本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可, 转载请注明出处, 谢谢合作.
        因本人技术水平和知识面有限, 内容如有纰漏或者需要修正的地方, 欢迎大家指正, 也欢迎大家提供一些其他好的调试工具以供收录, 鄙人在此谢谢啦

        展开全文
      • sysctl:LinuxBSD内核调整和网络安全强化优化,通过优化的sysctl调整提高了服务器系统的性能
      • Linux 内核调优

        2020-07-19 16:36:16
        /proc目录下存放着大多数的内核参数,并且可以在系统运行的同时进行更改, 但是,重新启动机器后就会失效,怎么解决呢,我们可以通过将更改的内核参数写入 /etc/sysctl.conf文件中实现永久更改,在/etc/sysctl.conf...

        单进程最大打开文件数限制

        一般的发行版,限制单进程最大可以打开1024个文件,这是远远不能满足高并发需求的,调整过程如下:在#号提示符下敲入:

        # ulimit –n 65535
        

        将root启动的单一进程的最大可以打开的文件数设置为65535个。如果系统回显类似于“Operation not permitted”之类的话,说明上述限制修改失败,实际上是因为指定的数值超过了Linux系统对该用户打开文件数的软限制或硬限制。因此,就需要修改Linux系统对用户的关于打开文件数的软限制和硬限制。

        第一步,修改limits.conf文件,并添加:

        # vim /etc/security/limits.conf
        * softnofile 65536
        * hard nofile 65536
        

        其中’*'号表示修改所有用户的限制;soft或hard指定要修改软限制还是硬限制;65536则指定了想要修改的新的限制值,即最大打开文件数(请注意软限制值要小于或等于硬限制)。修改完后保存文件。第二步,修改/etc/pam.d/login文件,在文件中添加如下行:

        # vim /etc/pam.d/login
        sessionrequired /lib/security/pam_limits.so
        

        这是告诉Linux在用户完成系统登录后,应该调用pam_limits.so模块来设置系统对该用户可使用的各种资源数量的最大限制(包括用户可打开的最大文件数限制),而pam_limits.so模块就会从/etc/security/limits.conf文件中读取配置来设置这些限制值。修改完后保存此文件。

        第三步,查看Linux系统级的最大打开文件数限制,使用如下命令:

        # cat/proc/sys/fs/file-max
        32568
        

        这表明这台Linux系统最多允许同时打开(即包含所有用户打开文件数总和)32568个文件,是Linux系统级硬限制,所有用户级的打开文件数限制都不应超过这个数值。通常这个系统级硬限制是Linux系统在启动时根据系统硬件资源状况计算出来的最佳的最大同时打开文件数限制,如果没有特殊需要,不应该修改此限制,除非想为用户级打开文件数限制设置超过此限制的值。修改此硬限制的方法是修改/etc/sysctl.conf文件内fs.file-max= 131072

        这是让Linux在启动完成后强行将系统级打开文件数硬限制设置为131072。修改完后保存此文件。

        完成上述步骤后重启系统

        内核TCP参数方面

        Linux系统下,TCP连接断开后,会以TIME_WAIT状态保留一定的时间,然后才会释放端口。当并发请求过多的时候,就会产生大量的TIME_WAIT状态的连接,无法及时断开的话,会占用大量的端口资源和服务器资源。这个时候我们可以优化TCP的内核参数,来及时将TIME_WAIT状态的端口清理掉。

        下面介绍的方法只对拥有大量TIME_WAIT状态的连接导致系统资源消耗有效,如果不是这种情况下,效果可能不明显。可以使用netstat命令去查TIME_WAIT状态的连接状态,输入下面的组合命令,查看当前TCP连接的状态和对应的连接数量:

        # netstat-n | awk ‘/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}
        

        这个命令会输出类似下面的结果:

        LAST_ACK16
        SYN_RECV348
        ESTABLISHED70
        FIN_WAIT1229
        FIN_WAIT230
        CLOSING33
        TIME_WAIT18098
        

        我们只用关心TIME_WAIT的个数,在这里可以看到,有18000多个TIME_WAIT,这样就占用了18000多个端口。要知道端口的数量只有65535个,占用一个少一个,会严重的影响到后继的新连接。这种情况下,我们就有必要调整下Linux的TCP内核参数,让系统更快的释放TIME_WAIT连接。

        编辑配置文件:/etc/sysctl.conf,在这个文件中,加入下面的几行内容:

        # vim /etc/sysctl.conf
        net.ipv4.tcp_syncookies= 1
        net.ipv4.tcp_tw_reuse= 1
        net.ipv4.tcp_tw_recycle= 1
        net.ipv4.tcp_fin_timeout= 30
        

        输入下面的命令,让内核参数生效:

        # sysctl-p
        

        简单的说明上面的参数的含义:

        • net.ipv4.tcp_syncookies= 1
          表示开启SYNCookies。当出现SYN等待队列溢出时,启用cookies来处理,可防范少量SYN攻击,默认为0,表示关闭;
        • net.ipv4.tcp_tw_reuse= 1
          表示开启重用。允许将TIME-WAITsockets重新用于新的TCP连接,默认为0,表示关闭;
        • net.ipv4.tcp_tw_recycle= 1 表示开启TCP连接中TIME-WAITsockets的快速回收,默认为0,表示关闭;
        • net.ipv4.tcp_fin_timeout 修改系統默认的TIMEOUT 时间。

        如果你的连接数本身就很多,可以再优化一下TCP的可使用端口范围,进一步提升服务器的并发能力。依然是往上面的参数文件中,加入下面这些配置:

        net.ipv4.tcp_keepalive_time= 1200
        net.ipv4.ip_local_port_range= 1024 65535
        net.ipv4.tcp_max_syn_backlog= 8192
        net.ipv4.tcp_max_tw_buckets= 5000
        

        注意 :这几个参数,建议只在流量非常大的服务器上开启,会有显著的效果。一般的流量小的服务器上,没有必要去设置这几个参数。

        • net.ipv4.tcp_keepalive_time= 1200
          表示当keepalive起用的时候,TCP发送keepalive消息的频度。缺省是2小时,改为20分钟。
        • ip_local_port_range= 1024 65535 表示用于向外连接的端口范围。缺省情况下很小,改为1024到65535。
        • net.ipv4.tcp_max_syn_backlog= 8192
          表示SYN队列的长度,默认为1024,加大队列长度为8192,可以容纳更多等待连接的网络连接数。
        • net.ipv4.tcp_max_tw_buckets= 5000
          表示系统同时保持TIME_WAIT的最大数量,如果超过这个数字,TIME_WAIT将立刻被清除并打印警告信息。默认为180000,改为5000。此项参数可以控制TIME_WAIT的最大数量,只要超出了。内核其他TCP参数说明
        • net.ipv4.tcp_max_syn_backlog= 65536
          记录的那些尚未收到客户端确认信息的连接请求的最大值。对于有128M内存的系统而言,缺省值是1024,小内存的系统则是128。
        • net.core.netdev_max_backlog= 32768
          每个网络接口接收数据包的速率比内核处理这些包的速率快时,允许送到队列的数据包的最大数目。
        • net.core.somaxconn= 32768
          例如web应用中listen函数的backlog默认会给我们内核参数的net.core.somaxconn限制到128,而nginx定义的NGX_LISTEN_BACKLOG默认为511,所以有必要调整这个值。
        • net.core.wmem_default= 8388608
        • net.core.rmem_default= 8388608
        • net.core.rmem_max= 16777216 #最大socket读buffer,可参考的优化值:873200
        • net.core.wmem_max= 16777216 #最大socket写buffer,可参考的优化值:873200
        • net.ipv4.tcp_timestsmps= 0
          时间戳可以避免序列号的卷绕。一个1Gbps的链路肯定会遇到以前用过的序列号。时间戳能够让内核接受这种“异常”的数据包。这里需要将其关掉。
        • net.ipv4.tcp_synack_retries= 2
          为了打开对端的连接,内核需要发送一个SYN并附带一个回应前面一个SYN的ACK。也就是所谓三次握手中的第二次握手。这个设置决定了内核放弃连接之前发送SYN+ACK包的数量。
        • net.ipv4.tcp_syn_retries= 2 在内核放弃建立连接之前发送SYN包的数量。
        • #net.ipv4.tcp_tw_len= 1
        • net.ipv4.tcp_tw_reuse= 1 开启重用。允许将TIME-WAITsockets重新用于新的TCP连接。
        • net.ipv4.tcp_wmem= 8192 436600 873200 TCP写buffer,可参考的优化值:8192 436600
          873200
        • net.ipv4.tcp_rmem = 32768 436600 873200 TCP读buffer,可参考的优化值:32768
          436600 873200
        • net.ipv4.tcp_mem= 94500000 91500000 92700000 同样有3个值,意思是:
        • net.ipv4.tcp_mem[0]:低于此值,TCP没有内存压力。
        • net.ipv4.tcp_mem[1]:在此值下,进入内存压力阶段。
        • net.ipv4.tcp_mem[2]:高于此值,TCP拒绝分配socket。上述内存单位是页,而不是字节。可参考的优化值是:7864321048576 1572864
        • net.ipv4.tcp_max_orphans= 3276800
          系统中最多有多少个TCP套接字不被关联到任何一个用户文件句柄上。如果超过这个数字,连接将即刻被复位并打印出警告信息。这个限制仅仅是为了防止简单的DoS攻击,不能过分依靠它或者人为地减小这个值,
          更应该增加这个值(如果增加了内存之后)。
        • net.ipv4.tcp_fin_timeout= 30
          如果套接字由本端要求关闭,这个参数决定了它保持在FIN-WAIT-2状态的时间。对端可以出错并永远不关闭连接,甚至意外当机。缺省值是60秒。2.2内核的通常值是180秒,你可以按这个设置,但要记住的是,即使你的机器是一个轻载的WEB服务器,也有因为大量的死套接字而内存溢出的风险,FIN-WAIT-2的危险性比FIN-WAIT-1要小,因为它最多只能吃掉1.5K内存,但是它们的生存期长些。

        以nginx 10k并发连接为优化目标,附简单介绍,不一一解释。

        tcp容量规划

        net.ipv4.tcp_mem  = 262144  524288 786432
        net.core.wmem_max = 16777216
        net.core.wmem_default = 131072
        net.core.rmem_max = 16777216
        net.core.rmem_default = 131072
        net.ipv4.tcp_wmem = 4096    131072  16777216
        net.ipv4.tcp_rmem = 4096    131072  16777216
        

        *net.ipv4.tcp_mem * 单位是内存页,一般是4k,三个值分别代表tcp内存使用的水平,低、中、高, 低表示无内存压力,中级表示内存压力状态,高表示内存吃紧,最高峰时系统将会拒绝分配内存。262144 代表1G内存,即(262144x4/1024/1024),其他类推。

        下面的参数单位都是字节 net.core.wmem_max 和net.core.wmem_default 会覆盖net.ipv4.tcp_wmem 的第二第三个值, 同理,net.core.rmem_max 和 net.core.rmem_default 会覆盖net.ipv4.tcp_rmem 的第二第三个值。稍微提高tcp读写缓冲区的容量,可以增加tcp传输效率,比如上文默认值131072=128k,现有一个1M的文件传输,只需8次传输即可,比较适合图片类传输。但也不是越大越好,比如一个文字页面只有15k,使用128k的内存显然有些浪费。上文tcp压力状态下的容量为2G,对应tcp读写缓冲区128k,可应对的连接数为16384 (2048x1024/128),可满足10k要求。

        tcp连接行为管理

        net.ipv4.tcp_tw_reuse = 1
        net.ipv4.tcp_tw_recycle = 1
        net.ipv4.tcp_timestamps = 1
        net.ipv4.tcp_fin_timeout = 30
        net.ipv4.tcp_max_tw_buckets = 8192
        net.ipv4.tcp_retries1 = 3
        net.ipv4.tcp_retries2 = 5
        net.ipv4.tcp_keepalive_time = 1800
        net.ipv4.tcp_keepalive_probes = 5
        net.ipv4.tcp_keepalive_intvl = 30
        net.ipv4.tcp_max_syn_backlog = 8192
        net.ipv4.tcp_max_orphans = 262144
        

        上面主要是tcp连接行为的伴随的参数,主要是tcp重用,增加队列,减少等待重试频率等等来提升效率。

        内存管理

        vm.swappiness = 5
        vm.dirty_ratio = 40
        vm.min_free_kbytes = 524288
        vm.vfs_cache_pressure = 100
        

        •vm.swappiness = 5 表示物理内存剩余5%时,才考虑使用swap,默认60,这显然非常不合理
        •vm.dirty_ratio = 40 表示拿出物理内存的40%用于写缓存,而不立即将数据写入硬盘。由于硬盘是众所周知的瓶颈,扩大它可提升写的效率,40%是个比较合适的比例。
        •vm.min_free_kbytes = 524288 这个用于控制剩余内存的大小,524288=512M,可根据需要调整。如果某些任务临时需要大量内存,可临时将它调大然后调小,回收页面缓存。它比vm.drop_caches 要温和得多,后者更粗暴。
        •vm.vfs_cache_pressure = 100 ,如果要尽快将脏数据刷进硬盘,提高它,比如150 。

        内核其他行为

        net.core.somaxconn = 8192
        net.core.netdev_max_backlog = 8192
        net.ipv4.ip_local_port_range = 15000 65000
        net.netfilter.nf_conntrack_max = 131072
        net.nf_conntrack_max = 131072
        net.ipv6.conf.all.disable_ipv6 = 1
        net.netfilter.nf_conntrack_tcp_timeout_established = 3600
        net.core.rps_sock_flow_entries = 32768
        

        net.core.somaxconn 表示socket的最大连接数,默认128,对于php-fpm使用unix socket情况下,需要调大。

        net.netfilter.nf_conntrack_tcp_timeout_established = 3600 默认2天时间,多数情况下,调小这个参数是有益的,如果是tcp长连接,这个参数可能不太合适。

        net.core.rps_sock_flow_entries 这个参数启用RPS,自动将网卡中断均匀分配到多个CPU,改进网卡性能和系统负载。

        RPS还需要脚本配合

        for fileRfc in $(ls /sys/class/net/eth*/queues/rx-*/rps_flow_cnt);do echo 2048 > $fileRfc;done
        

        原创地址:https://blog.51cto.com/purplegrape/1353861
        原创作者:紫色葡萄

        linux内核tcp调优规范与方案

        1、TCP常用内核参数优化
        上一篇我们介绍了服务器上有大量的TIME_WAIT等待,可能造成的危害,以及给web服务器带来负担。如何解决这个问题呢,其实,解决思路很简单,就是让服务器能够快速回收和重用那些TIME_WAIT的资源即可。这就是对tcp调优。
        在linux系统上,对tcp调优主要是通过调整Linux内核参数来实现的,其实主要是对/proc文件系统进行设置,/proc文件系统是一种内核和内核模块用来向进程(process) 发送信息的机制(所以叫做/proc)。通过这个伪文件系统我们可以和内核内部数据结构进行交互,在运行中改变内核参数。 与其他文件系统不同,/proc存在于内存之中而不是硬盘上。proc文件系统以文件的形式向用户空间提供了访问接口,这些接口可以用于在运行时获取相关信息或者修改参数配置,因而它是非常方便的一个接口。
        /proc目录下存放着大多数的内核参数,并且可以在系统运行的同时进行更改, 但是,重新启动机器后就会失效,怎么解决呢,我们可以通过将更改的内核参数写入 /etc/sysctl.conf文件中实现永久更改,在/etc/sysctl.conf文件中添加或者修改如何设置:
        #对于一个新建连接,内核要发送多少个SYN连接请求才决定放弃,不应该大于255,默认值是5,这里设置为2.

        net.ipv4.tcp_syn_retries=2
        

        #表示当keepalive启用的时候,TCP发送keepalive消息的频度。缺省是7200秒,改为300秒

        net.ipv4.tcp_keepalive_time=300
        

        #表示孤儿socket废弃前重试的次数,重负载web服务器建议调小。

        net.ipv4.tcp_orphan_retries=1
        

        #表示如果套接字由本端要求关闭,这个参数决定了它保持在FIN-WAIT-2状态的时间

        net.ipv4.tcp_fin_timeout=30
        

        #表示SYN队列的长度,默认为1024,加大队列长度为8192,可以容纳更多等待连接的网络连接数。
        net.ipv4.tcp_max_syn_backlog = 8192 (注意:这个队列大小除了系统设置外,程序里面也要设置)
        #表示开启SYN Cookies。当出现SYN等待队列溢出时,启用cookies来处理,可防范少量SYN攻 击,默认为0,表示关闭

        net.ipv4.tcp_syncookies = 1
        

        #表示开启重用。允许将TIME-WAIT sockets重新用于新的TCP连接,默认为0,表示关闭

        net.ipv4.tcp_tw_reuse = 1
        

        #表示开启TCP连接中TIME-WAIT sockets的快速回收,默认为0,表示关闭

        net.ipv4.tcp_tw_recycle = 1
        

        修改完之后执行/sbin/sysctl -p让参数生效。
        其实TIME-WAIT的问题还是比较好处理的,可以通过调节服务器参数实现,有时候还会出现CLOSE_WAIT很多的情况,CLOSE_WAIT是在对方关闭连接之后服务器程序自己没有进一步发出ACK信号。换句话说,就是在对方连接关闭之后,程序里没有检测到,或者程序压根就忘记了这个时候需要关闭连接,于是这个资源就一直被程序占着。所以解决CLOSE_WAIT过多的方法还需要检查程序,检查代码,因为问题很大程度上出在服务器程序中。
        到此为止,TCP优化到一段落。

        2、TCP洪水攻 击(SYN Flood)的诊断和处理

        SYN Flood是当前最流行的DoS(拒绝服务)与DDoS(分布式拒绝服务)的方式之一,这是一种利用TCP协议缺陷,发送大量伪造的TCP连接请求,常用假冒的IP或IP号段发来海量的请求连接第一个握手包(SYN包),被攻 击服务器回应第二个握手包(SYN+ACK包),因为对方是假冒IP,对方永远收不到包且不会回应第三个握手包。导致被攻 击服务器保持大量SYN_RECV状态的“半连接”,并且会重试默认5次回应第二个握手包,直到塞满TCP等待连接队列,资源耗尽(CPU满负荷或内存不足),让正常的业务请求连接不进来。
        那么如何诊断SYN Flood问题呢,一般情况下如果发现网站打开缓慢、CPU负载高、ssh登陆慢甚至登陆不上,同时在系统日志中发现如下信息:

        [root@test ~]# tail -f /var/log/messages 
        Mar 12 02:38:03 test kernel: possible SYN flooding on port 80. Sending cookies.
        Mar 12 02:39:04 test kernel: possible SYN flooding on port 80. Sending cookies.
        Mar 12 02:40:04 test kernel: possible SYN flooding on port 80. Sending cookies.
        

        如果出现类似这种情况,那可能就是遭遇了TCP洪水

        此时,通过如下命令检查TCP连接状态:

        [root@localhost ~]# netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'
        TIMEWAIT 7807
        FINWAIT1 59
        ESTABLISHED 8112
        FINWAIT2 809
        SYNRECV 198098
        CLOSING 27
        LASTACK 36
        

        检查发现,SYNRECV连接数会非常多。
        针对这个问题,首先要做应急处理,那就是找到请求数请最多的IP地址,查找攻 击来源,使用如下命令组合:

        [root@localhost ~]# netstat -anlp|grep 80|grep tcp|awk '{print $5}'|awk -F: '{print $1}'|sort|uniq -c|sort -nr|head -n3
        36.171.242
        149.130.152
        149.130.18
        

        查到可疑的IP后,利用iptables临时封掉最大嫌疑攻 击的IP或IP号段。
        接着,还需要调整系统内核参数,来抵挡这种攻 击,根据上面对SYN Flood攻 击的特点,我们只需修改操作系统内核参数即可有效缓解。主要参数如下

        net.ipv4.tcpsyncookies = 1
        net.ipv4.tcpmaxsynbacklog = 81920
        net.ipv4.tcpsynackretries = 2
        

        三个参数的含义分别为启用SYN Cookie、设置SYN最大队列长度以及设置SYN+ACK最大重试次数。
        SYN Cookie的作用是缓解服务器资源压力。启用之前,服务器在接到SYN数据包后,会立即分配存储空间,并随机化一个数字作为SYN号发送SYN+ACK数据包。然后保存连接的状态信息等待客户端确认。而在启用SYN Cookie之后,服务器不再马上分配存储空间,而且通过基于时间种子的随机数算法设置一个SYN号,替代完全随机的SYN号。发送完SYN+ACK确认报文之后,清空资源不保存任何状态信息。直到服务器接到客户端的最终ACK包。同时,通过Cookie检验算法鉴定是否与发出去的SYN+ACK报文序列号匹配,匹配则通过完成握手,失败则丢弃。

        tcpmaxsynbacklog则是使用服务器的内存资源,换取更大的等待队列长度,让攻 击数据包不至于占满所有连接而导致正常用户无法完成握手。

        net.ipv4.tcpsynackretries是降低服务器SYN+ACK报文重试次数(默认是5次),尽快释放等待资源。
        这三种措施与攻 击的三种危害一一对应,完完全全是对症下药。但这些措施也是双刃剑,设置过大可能消耗服务器更多的内存资源,甚至影响正常用户建立TCP连接,因此,需要评估服务器硬件资源和大小谨慎设置。

        参考连接 :

        Linux 内核调优 : https://mp.weixin.qq.com/s/sfl6tm8bgczRwneSR_ehVw

        linux内核tcp调优规范与方案 : https://blog.51cto.com/11110720/2510719

        高并发情况下 Linux 系统及 kernel 参数优化 :https://mp.weixin.qq.com/s/r5wTwgbjKMkLkdTs3ejazg

        Linux 系统安全强化指南(建议收藏的教程)
        https://mp.weixin.qq.com/s/2uALhEKAXOKa8YGyPNkRyQ

        Linux服务器高并发调优实战 :https://mp.weixin.qq.com/s/oAQAtmFHNrZ_j1soxxLyTA

        展开全文
      • 1,升级内核的具体步骤 2,更新GCC 3,使用glibc2。3。5 4,使用NPTL线程进行编程 在此之前,先简要地介绍一下Linux内核2。6所做的改进及新增功能。Linux2。6主要在以下的10个方面作了很大的改进,简单概括如下,...
      • 目前采用的挤压强化法有三种,分别为()、()和()。 客户网上办卡不可通过在线() 采用带压不置换焊补管道或容器时,发现含氧量明显增加时应()。 细菌接种时,接种环用火焰烧灼是为了() 核心系统的合同...
      • Linux 内核主线总体而言兼具了性能、稳定和安全于一身,不过总有些 Geek 不满足主线中的种种限制,使用各自社区的补丁为它添砖加瓦。概述pf内核,这算是一个非常为人熟知的内核。包含了ck补丁(兼容4.8版本将是最后一...
      • 强化学习如何让机器玩游戏

        千次阅读 多人点赞 2019-07-04 09:06:14
        强化学习 强化学习是代理面临的学习问题,它通过与动态环境反复交互试验从而学习到某种行为。它是机器学习的主要学习方法之一,智能体从环境到行为的学习,也就是如何在环境中采取一些列行为,才能使得回报信号函数...
      • 读了这本书上的东西,把觉得好的东西写下来,已备不时之用,也强化记忆。7。2。1内核模块的概念介绍内核模块的同时,也说明一下和应用程序的区别。虽然内容很多,但觉得都很有用。1、内核模块是一些可以让操作系统.....
      • 网络结构搜索之强化学习

        千次阅读 2019-07-30 14:36:26
        算力和需求的增长使得神经架构搜索( Neural Architecture Search,NAS)重回人们的视线...强化学习(RL)可谓 NAS 中的核武器,谷歌开启并引领该方向的工作。由初期燃烧的显卡到专用硬件,对效率的追求犹如挖矿一般。
      • 基于BLINK深度优化和合理扩展的腾讯X5内核,全面整合腾讯公司在云安全、云加速和大数据分析应用等相关领域的研发和运营能力,一统App浏览江湖。目前大部分App的功能以浏览为主,然而由于App开发水平参差不齐,在浏览...
      • 此外,稳定的内核还包括更新的强化功能,以减轻LTS内核没有的某些利用。此类功能的一些示例是Lockdown LSM和STACKLEAK GCC插件。 总而言之,在选择稳定或LTS内核时需要权衡取舍。LTS内核具有较少的强化功能,并且...
      • 内核模块的初始化module_init

        千次阅读 2018-10-19 15:22:11
        关于模块的初始化网上讲解的有很多,但是有些讲的不是特别全面,有些讲的不是特别的深入,所以我在博客上找了一些可以供参考的,给大家同时也是对于自己的一个强化记忆如下链接: ... ... 其中第二条链接更加详细参考...
      • 关于Linux内核利用Linux内核利用思考Linux漏洞检测工具Linux提权辅助工具Linux内核利用任意内核读写问题内存损坏漏洞问题1-内核栈漏洞:2-内核堆漏洞:竞争条件地址空间布局随机化缓冲区溢出防御技术空指针引用问题...
      • 操作系统内核的绝佳学习材料——JOS 前言:关于JOS和一些经验之谈 这一学期的操作系统课使用的是MIT用于教学的JOS操作系统,并且StonyBrook在其基础上做了大量改动,最重要的变化就是从32位移植到了64位。因为...
      • 读了这本书上的东西,把觉得好的东西写下来,已备不时之用,也强化记忆。7。2。1内核模块的概念介绍内核模块的同时,也说明一下和应用程序的区别。虽然内容很多,但觉得都很有用。1、内核模块是一些可以让操作系统.....
      • 浏览器内核

        2019-04-30 09:38:44
        一、浏览器内核 (排版引擎/渲染引擎) 首先解释一下浏览器内核是什么东西。英文叫做:Rendering Engine,中文翻译很多,排版引擎、解释引擎、渲染引擎,现在流行称为浏览器内核,至于为什么流行这么称呼,请自行领悟...
      • 在react-native中使用crosswalk webview内核来增强安卓webview体验流畅性 最近使用react-native开发安卓app,由于我们要在webview中运行白鹭引擎开发的游戏,这样就对webview性能有了要求,安卓手机内置的webview性能...
      • 点上方人工智能算法与Python大数据获取更多干货在右上方···设为星标★,第一时间获取资源仅做学术分享,如有侵权,联系删除转载于 :机器之心很多机器人强化学习任务都面临计算需求和仿...
      • 强化学习

        千次阅读 2017-10-19 10:23:01
        前言机器学习可以大致分为四类: 监督学习 无监督学习 半监督学习 强化学习 监督学习是利用标记了的样本进行学习,无监督学习则是使用未标记的样本进行学习,这...什么是强化学习《最强大脑》曾经有个挑战项目叫蜂巢迷
      • 一、简单介绍一下什么是浏览器内核。 浏览器最重要或者说核心的部分是“Rendering Engine”,可大概译为“解释引擎”,不过我们一般习惯将之称为“浏览器内核”。负责对网页语法的解释(如HTML、JavaScript)并...
      • 关于浏览器内核你不得不了解的事

        千次阅读 2016-12-04 11:24:28
        浏览器是我们每天几乎都必须使用的软件产品,可是对于自己每天都接触的浏览器,很多同学其实对其一无所知。今天就跟大家说说关于浏览器内核的一些事儿吧,好让你了解多一点稍微内在的东西。

      空空如也

      空空如也

      1 2 3 4 5 ... 20
      收藏数 11,527
      精华内容 4,610
      关键字:

      内核强化