English

内核锁压力测试操作

CONFIG_LOCK_TORTURE_TEST

CONFIG_LOCK_TORTURE_TEST 配置选项提供了一个内核模块,用于对核心内核锁原语运行压力测试。如果需要,可以在要测试的正在运行的内核上事后构建内核模块“locktorture”。这些测试通过 printk() 定期输出状态消息,可以通过 dmesg 查看(也许可以通过 grep 查找“torture”)。加载模块时开始测试,卸载模块时停止测试。该程序基于 RCU 接受压力测试的方式(通过 rcutorture)。

这个压力测试包括创建多个内核线程,它们获取锁并将其保持特定时间,从而模拟不同的临界区行为。可以通过延长该临界区的保持时间和/或创建更多内核线程来模拟对锁的竞争程度。

模块参数

该模块具有以下参数

Locktorture 特定参数

nwriters_stress

将对排他锁所有权(写者)进行压力测试的内核线程数。默认值为在线 CPU 数量的两倍。

nreaders_stress

将对共享锁所有权(读者)进行压力测试的内核线程数。默认值与写者锁的数量相同。如果用户未指定 nwriters_stress,则读者和写者都将是在线 CPU 的数量。

torture_type

要进行压力测试的锁类型。默认情况下,只对自旋锁进行压力测试。该模块可以对以下锁进行压力测试,其字符串值如下

  • “lock_busted”

    模拟一个有 bug 的锁实现。

  • “spin_lock”

    spin_lock()spin_unlock() 对。

  • “spin_lock_irq”

    spin_lock_irq()spin_unlock_irq() 对。

  • “rw_lock”

    读/写 lock()unlock() rwlock 对。

  • “rw_lock_irq”

    读/写 lock_irq()unlock_irq() rwlock 对。

  • “mutex_lock”

    mutex_lock()mutex_unlock() 对。

  • “rtmutex_lock”

    rtmutex_lock()rtmutex_unlock() 对。内核必须配置 CONFIG_RT_MUTEXES=y。

  • “rwsem_lock”

    读/写 down()up() 信号量对。

压力测试框架(RCU + 锁)

shutdown_secs

在终止测试并关闭系统之前运行测试的秒数。默认值为零,这会禁用测试终止和系统关机。此功能对于自动化测试非常有用。

onoff_interval

每次尝试执行随机选择的 CPU 热插拔操作之间的秒数。默认为零,这会禁用 CPU 热插拔。在 CONFIG_HOTPLUG_CPU=n 的内核中,无论为 onoff_interval 指定什么值,locktorture 都会默默地拒绝执行任何 CPU 热插拔操作。

onoff_holdoff

等待开始 CPU 热插拔操作的秒数。这通常仅在 locktorture 被内置到内核中并在引导时自动启动时使用,在这种情况下,它可以避免用上线和下线的 CPU 混淆引导时代码。此参数仅在启用了 CONFIG_HOTPLUG_CPU 时有用。

stat_interval

与统计相关的 printk() 之间的秒数。默认情况下,locktorture 每 60 秒报告一次统计信息。将间隔设置为零会导致-仅-在卸载模块时打印统计信息。

stutter

运行测试的时长,然后暂停相同的时间段。默认为 “stutter=5”,即运行和暂停(大约)五秒钟的间隔。指定 “stutter=0” 会使测试连续运行而不暂停。

shuffle_interval

保持测试线程绑定到 CPU 的特定子集的秒数,默认为 3 秒。与 test_no_idle_hz 结合使用。

verbose

通过 printk() 启用详细的调试打印。默认启用。这些额外的信息主要与来自主“torture”框架的高级错误和报告有关。

统计数据

统计信息以以下格式打印

spin_lock-torture: Writes:  Total: 93746064  Max/Min: 0/0   Fail: 0
   (A)                    (B)            (C)            (D)          (E)

(A): Lock type that is being tortured -- torture_type parameter.

(B): Number of writer lock acquisitions. If dealing with a read/write
     primitive a second "Reads" statistics line is printed.

(C): Number of times the lock was acquired.

(D): Min and max number of times threads failed to acquire the lock.

(E): true/false values if there were errors acquiring the lock. This should
     -only- be positive if there is a bug in the locking primitive's
     implementation. Otherwise a lock should never fail (i.e., spin_lock()).
     Of course, the same applies for (C), above. A dummy example of this is
     the "lock_busted" type.

用法

可以使用以下脚本来对锁进行压力测试

#!/bin/sh

modprobe locktorture
sleep 3600
rmmod locktorture
dmesg | grep torture:

可以手动检查输出中的错误标志 “!!!”。当然,人们也可以创建一个更复杂的脚本来自动检查此类错误。“rmmod” 命令会强制通过 printk() 输出 “SUCCESS”(成功)、“FAILURE”(失败)或 “RCU_HOTPLUG” 指示。前两个是不言自明的,而最后一个表明虽然没有锁失败,但检测到了 CPU 热插拔问题。

另请参见:RCU 压力测试操作