【问题标题】:A assertion succeed in userspace but failed in kernel断言在用户空间成功但在内核中失败
【发布时间】:2021-08-06 13:57:25
【问题描述】:

我是 linux 内核的新手,我在使用“BUG_ON”时发现了一个奇怪的行为。

这是我在用户空间的示例代码,对 16 位整数进行比较:

#include <stdio.h>
#include <assert.h>

typedef unsigned short digit;

int main(){
#define Bn_SHIFT ((sizeof(digit) << 3) - 1)
#define Bn_MASK ((digit)((1 << Bn_SHIFT) - 1))
       digit carry = 3694;
       printf("Assert(carry <= Bn_MASK), carry=%d, Bn_MASK=%d ", carry, Bn_MASK);
       assert(carry <= Bn_MASK);
#undef Bn_SHIFT
#undef Bn_MASK
    return 0;
}

使用以下命令运行良好:

~$ gcc userspace.c -o userspace -O0 -Werror -Wall -g
~$ ./userspace
Assert(carry <= Bn_MASK), carry=3694, Bn_MASK=32767

为了在内核模块中实现上述功能,我 fork kobject-example.c 并对其进行了修改:

--- kobject-example-original.c    2021-05-17 16:02:15.952798660 +0800
+++ kobject-example.c   2021-05-17 14:45:00.851229416 +0800
@@ -10,6 +10,7 @@
 #include <linux/sysfs.h>
 #include <linux/module.h>
 #include <linux/init.h>
+#include <linux/bug.h>
 
 /*
  * This module shows how to create a simple subdirectory in sysfs called
@@ -22,12 +23,23 @@
 static int baz;
 static int bar;
 
+typedef unsigned short digit;
+
 /*
  * The "foo" file where a static variable is read from and written to.
  */
 static ssize_t foo_show(struct kobject *kobj, struct kobj_attribute *attr,
                        char *buf)
 {
+
+
+#define Bn_SHIFT ((sizeof(digit) << 3) - 1)
+#define Bn_MASK ((digit)((1 << Bn_SHIFT) - 1))
+       digit carry = 3694;
+       printk("BUG_ON(carry <= Bn_MASK), carry=%d, Bn_MASK=%d ", carry, Bn_MASK);
+       BUG_ON(carry <= Bn_MASK);
+#undef Bn_SHIFT
+#undef Bn_MASK
        return sprintf(buf, "%d\n", foo);
 }

生成文件:

CONFIG_MODULE_SIG = n
TARGET_MODULE := kobject-example

obj-m := $(TARGET_MODULE).o
ccflags-y := -std=gnu99 -Wno-declaration-after-statement -g -O0

KDIR := /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)

all:
    $(MAKE) -C $(KDIR) M=$(PWD) modules

但是,当我运行它时,BUG_ON 被触发了。

~$ make && sudo ismod kobject-example.ko
~$ cat /sys/kernel/kobject_example/foo
Segmentation fault

我认为这个问题与整数转换无关,因为carry的秩小于Bn_MASK(32位整数),而carry在进行比较时会隐式转换为32位整数.

有人可以给我一个提示吗?

【问题讨论】:

  • 那么printk(... 打印了什么?你没有收到来自 BUG_ON 的消息吗?
  • 我试图弄清楚从dmesg 打印的堆栈跟踪,直到@dratenik 提醒我。

标签: c kernel-module


【解决方案1】:

assert 在条件为假时失败

BUG_ON 在条件为真时失败,参见https://kernelnewbies.org/FAQ/BUG

你的条件是真的。

【讨论】:

  • 我没有注意到是我的错。
  • @5f3759df0x 有时人们会因为过于关注复杂的细节而错过了基本的东西:) 发生在我们所有人身上......
  • @5f3759df0x,你可以使用static_assert(),它的结果与assert()相同。
  • @0andriy 感谢您的建议。
猜你喜欢
  • 1970-01-01
  • 2020-08-20
  • 1970-01-01
  • 1970-01-01
  • 2015-05-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多