当前位置: 首页 > news >正文

Linux 内核测试与调试(3)

Linux 内核测试与调试(3)

基本测试

安装好内核后,试试能不能启动它。能启动的话,检查 dmesg 看看有没有隐藏的错误。试试下面的功能:

  • 网络(Wifi 或者网线)是否可用?
  • ssh 是否可用?
  • 使用 ssh 远程传输文件。
  • 使用 git clone 和 git pull 命令。
  • 用用网络浏览器。
  • 查看 email。
  • 使用 ftp, wget 等软件下载文件。
  • 播放音频视频文件。
  • 连上 USB 鼠标等设备。

检查内核日志

使用 dmesg 查看隐藏的问题,对于定位新代码带来的 bug 是一个好方法。一般来说,dmesg 不会输出新的 crit, alert, emerg 级别的错误信息,也不应该出现新的 err 级别的信息。你要注意的是那些 warn 级别的日志信息。请注意 warn 这个级别的信息并不是坏消息,新代码带来新的警告信息,不会给内核带去严重的影响。

  • dmesg -t -l emerg
  • dmesg -t -l crit
  • dmesg -t -l alert
  • dmesg -t -l err
  • dmesg -t -l warn
  • dmesg -t -k
  • dmesg -t

下面的脚本运行了上面的命令,并且将输出保存起来,以便与老的内核的 dmesg 输出作比较(LCTT:老内核的 dmesg 输出在本系列的第二篇文章中有介绍)。然后运行 diff 命令,查看新老内核 dmesg 日志之间的不同。这个脚本需要输入老内核版本号,如果不输入参数,它只会生成新内核的 dmesg 日志文件后直接退出,不再作比较(LCTT:话是这么说没错,但点开脚本一看,没输参数的话,这货会直接退出,连新内核的 dmesg 日志也不会保存的)。如果 dmesg 日志有新的警告信息,表示新发布的内核有漏网之“虫”,这些 bug 逃过了自测和系统测试。你要看看,那些警告信息后面有没有栈跟踪信息?也许这里有很多问题需要你进一步调查分析。

  • dmesg 测试脚本

压力测试

执行压力测试的一个好办法是同时跑三四个内核编译任务。下载各种版本的内核,同时编译它们,并记录时间。比较新内核跑压力测试和老内核跑压力测试所花的时间,然后可以定位新内核的性能。如果新内核跑压力测试的时间比老内核的更长,说明新内核的部分模块性能退步了。性能问题很难调试出来。第一步是找出哪里导致的性能退步。同时跑多个内核编译任务对检测内核整体性能来说是个好方法,但是这种方法涵盖了多个内核模块,比如内存管理、文件系统、DMA、驱动等(LCTT:也就是说,这种压力测试没办法定位到是哪个模块造成了性能的下降)。

 
  
  1. time make all

内核测试工具

我们可以在 Linux 内核本身找到多种测试方法。下面介绍一个很好用的功能测试工具集: ktest 套件

ktest 是一个自动测试套件,它可以提供编译安装启动内核一条龙测试服务,也可以跑交叉编译测试,前提是你的系统有安装交叉编译所需要的软件。ktest 依赖于 flex 和 bison。详细信息请参考放在 tools/testing/ktest 目录下的文档,你可以自学成材。另外还有一些参考资料教你怎么使用 ktest:

  • ktest-eLinux.org

tools/testing/selftests 套件

我们来玩玩自测吧。内核源码的多个子系统都有自己的自测工具,到目前为止,断点、cpu热插拔、efivarfs、IPC、KCMP、内存热插拔、mqueue、网络、powerpc、ptrace、rcutorture、定时器和虚拟机子系统都有自测工具。另外,用户态内存的自测工具可以利用 testusercopy 模块来测试用户态内存到内核态的拷贝过程。下面的命令演示了如何使用这些测试工具:

编译测试:

 
  
  1. make -C tools/testing/selftests

测试全部:(有些测试需要 root 权限,你需要以 root 用户登入系统然后运行命令)

 
  
  1. make -C tools/testing/selftests run_tests

只测试单个子系统:

 
  
  1. make -C tools/testing/selftests TARGETS=vm run_tests

tools/testing/fault-injection 套件

在 tools/testing 目录下的另一个测试套件是 fault-injection。failcmd.sh 脚本用于检测 slab 和内存页分配器的错误。这些工具可以测试内核能否很好地从错误状态中恢复回来。这些测试需要用到 root 权限。下面简单介绍了一些当前能提供的错误检测方法。随着错误检测方法的增加,这份名单也会不断增长。最新的名单请参考 Documentation/fault-injection/fault-injection.txt 文档。

failslab (默认选项)

产生 slab 分配错误。作用于 kmalloc(), kmemcachealloc() 等函数(LCTT:产生的结果是调用这些函数就会返回失败,可以模拟程序分不到内存时是否还能稳定运行下去)。

fail_page_alloc

产生内存页分配的错误。作用于 allocpages(), getfree_pages() 等函数(LCTT:同上,调用这些函数,返回错误)。

fail_make_request

对满足条件(可以设置 /sys/block//make-it-fail 或 /sys/block///make-it-fail 文件)的磁盘产生 IO 错误,作用于 generic_make_request() 函数(LCTT:所有针对这块磁盘的读或写请求都会出错)。

fail_mmc_request

对满足条件(可以设置 /sys/kernel/debug/mmc0/fail_mmc_request 这个 debugfs 属性)的磁盘产生 MMC 数据错误。

你可以自己配置 fault-injection 套件的功能。fault-inject-debugfs 内核模块在系统运行时会在 debugfs 文件系统下面提供一些属性文件。你可以指定出错的概率,指定两个错误之间的时间间隔,当然本套件还能提供更多其他功能,具体请查看 Documentation/fault-injection/fault-injection.txt。 Boot 选项可以让你的系统在 debugfs 文件系统起来之前就可以产生错误,下面列出几个 boot 选项:

  • failslab=
  • fail_page_alloc=
  • fail_make_request=
  • mmc_core.fail_request=[interval],[probability],[space],[times]

fault-injection 套件提供接口,以便增加新的功能。下面简单介绍下增加新功能的步骤,详细信息请参考上面提到过的文档:

使用 DECLARE_FAULT_INJECTION(name) 定义默认属性;

详细信息可查看 fault-inject.h 中定义的 struct fault_attr 结构体。

配置 fault 属性,新建一个 boot 选项;

这步可以使用 setup_fault_attr(attr, str) 函数完成,为了能在系统启动的早期产生错误,添加一个 boot 选项这一步是必须要有的。

添加 debugfs 属性;

使用 fault_create_debugfs_attr(name, parent, attr) 函数,为新功能添加新的 debugfs 属性。

为模块设置参数;

为模块添加一些参数,对于配置错误属性来说是一个好主意,特别是当新功能的应用范围受限于单个内核模块的时候(LCTT:不同内核,你的新功能可能需要不同的测试参数,通过设置参数,你的功能可以不必为了迎合不同内核而每次都重新编译一遍)。

添加一个钩子函数到错误测试的代码中。

should_fail(attr, size) —— 当这个钩子函数返回 true 时,用户的代码就应该产生一个错误。

应用程序使用这个 fault-injection 套件可以指定某个具体的内核模块产生 slab 和内存页分配的错误,这样就可以缩小性能测试的范围。

原文发布时间:2014-08-19

本文来自云栖合作伙伴“linux中国”

相关文章:

  • 《微信公众平台开发:从零基础到ThinkPHP5高性能框架实践》——3.5 本章小结...
  • 《Adobe Illustrator CS5中文版经典教程》—第0课0.15节创建和编辑渐变
  • 《鸟哥的Linux 私房菜 基础学习篇(第三版)》——1.4 重点回顾
  • 《贝叶斯方法:概率编程与贝叶斯推断》——1.2 我们的贝叶斯框架
  • 《Wireshark网络分析就这么简单》—从一道面试题开始说起
  • jobs 命令示例
  • 《Haskell并行与并发编程》——第2章,第2.4节Deepseq
  • 《C++ AMP:用Visual C++加速大规模并行计算》——3.5 array_view T,N
  • 《用友ERP-U8(V8.72)模拟实战----财务、供应链和生产制造》一1.4 系统管理注册和导入演示账套...
  • 《Unreal Engine 4蓝图可视化编程》一导读
  • 《Splunk智能运维实战》——3.8 使用散点图根据大小和响应时间标识离散的请求...
  • 模块与包
  • 生成模型和判别模型
  • 树莓派+pythonista实时监控系统
  • mysql开发之---使用游标双层嵌套对总表进行拆分为帖子表和回复表
  • @jsonView过滤属性
  • [译]前端离线指南(上)
  • leetcode讲解--894. All Possible Full Binary Trees
  • LintCode 31. partitionArray 数组划分
  • Python中eval与exec的使用及区别
  • Vue2.0 实现互斥
  • vue-cli3搭建项目
  • Webpack 4x 之路 ( 四 )
  • webpack+react项目初体验——记录我的webpack环境配置
  • 从零到一:用Phaser.js写意地开发小游戏(Chapter 3 - 加载游戏资源)
  • 海量大数据大屏分析展示一步到位:DataWorks数据服务+MaxCompute Lightning对接DataV最佳实践...
  • 看域名解析域名安全对SEO的影响
  • 盘点那些不知名却常用的 Git 操作
  • 通过来模仿稀土掘金个人页面的布局来学习使用CoordinatorLayout
  • 问:在指定的JSON数据中(最外层是数组)根据指定条件拿到匹配到的结果
  • ​软考-高级-系统架构设计师教程(清华第2版)【第12章 信息系统架构设计理论与实践(P420~465)-思维导图】​
  • # centos7下FFmpeg环境部署记录
  • #鸿蒙生态创新中心#揭幕仪式在深圳湾科技生态园举行
  • (42)STM32——LCD显示屏实验笔记
  • (附源码)spring boot车辆管理系统 毕业设计 031034
  • (四)七种元启发算法(DBO、LO、SWO、COA、LSO、KOA、GRO)求解无人机路径规划MATLAB
  • (转)Android中使用ormlite实现持久化(一)--HelloOrmLite
  • (轉貼) 寄發紅帖基本原則(教育部禮儀司頒布) (雜項)
  • .Net 6.0 处理跨域的方式
  • .NET CORE Aws S3 使用
  • .Net8 Blazor 尝鲜
  • .NET程序员迈向卓越的必由之路
  • .NET的数据绑定
  • .net项目IIS、VS 附加进程调试
  • @FeignClient 调用另一个服务的test环境,实际上却调用了另一个环境testone的接口,这其中牵扯到k8s容器外容器内的问题,注册到eureka上的是容器外的旧版本...
  • @staticmethod和@classmethod的作用与区别
  • @synthesize和@dynamic分别有什么作用?
  • [Android]一个简单使用Handler做Timer的例子
  • [Apio2012]dispatching 左偏树
  • [C#]C# winform实现imagecaption图像生成描述图文描述生成
  • [C++] Windows中字符串函数的种类
  • [FxCop.设计规则]8. 也许参数类型应该是基类型
  • [GXYCTF2019]BabySQli1
  • [HITCON 2017]SSRFme perl语言的 GET open file 造成rce
  • [HTML]Web前端开发技术6(HTML5、CSS3、JavaScript )DIV与SPAN,盒模型,Overflow——喵喵画网页