【问题标题】:A better way than printk() to leave a kernel module log?比 printk() 留下内核模块日志的更好方法?
【发布时间】:2015-06-17 19:24:17
【问题描述】:

我正在使用printk() 留下内核模块的日志消息。我已经修改了ath9k_htc WLAN 卡模块,以便在 WLAN 卡发送或接收数据或确认帧时留下日志消息。日志消息包含帧类型和时钟周期。

printk(KERN_DEBUG "MyModule: DATA at %llu\n", get_ccnt());

get_ccnt() 在哪里:

static __inline__ long long int get_ccnt(void)
{
#if defined(__i386__)
    long long int x;
    __asm__ volatile (".byte 0x0f, 0x31" : "=A" (x));
    return x;

#elif defined(__x86_64__)
    unsigned int hi, lo;
    __asm__ __volatile__ ("rdtsc" : "=a"(lo), "=d"(hi));
    return ( (long long int)lo)|( ((long long int)hi)<<32 );

#endif
}

我担心的是,帧的传输和接收非常频繁。但我认为printk() 无法像传输和接收帧一样快地执行和完成。

在我决定使用prinkt() 之前,我已经考虑过使用message queuesignal。但是,我已经放弃了使用它们,因为它们在内核模块中使用起来并不容易,或者我对此知之甚少。

(是的,我想将帧类型和时钟周期从内核模块传递到用户空间应用程序。当我使用printk() 时,我阅读了一条日志消息,其中包含以下内容:)

FILE *fp = popen("dmesg | grep MyModule");
char linebuff[512];
while (fgets(linebuff, 512, fp) != NULL) {
    do_something();
}

那么,当消息包含时间关键数据时,使用printk() 将消息从内核模块传递到用户空间应用程序不是很好吗?

一个微不足道的问题是,调用get_ccnt() 函数会使时钟周期的测量不准确?我不这么认为,因为它是一个__inline__ 函数...

【问题讨论】:

  • 规范的方法是 debugfs。
  • 我使用了netlink libnl库infradead.org/~tgr/libnl在用户空间应用程序和内核模块之间发送和接收数据,加上来自内核模块的一些通知,很容易实现
  • @sim,你的意思是libnl 可以测量帧被发送或接收的时间吗?或者你的意思是它具有触发int数据传输和接收的能力?
  • @Jeon 这是一个简化 netlink 协议使用的库,主要目标是在用户空间和内核空间之间进行通信,使用 netlink,您可以在内核模块中创建事件并为它们订阅用户空间应用程序
  • @sim,哦,直到现在我才知道libnl 是一个用于通信的库(例如以太网、wifi ......)。我在这里学到了一些新东西。非常感谢。

标签: c linux linux-kernel kernel-module


【解决方案1】:

尚不完全清楚您要做什么,但您要编写代码来运行 dmesggrep 其内容的事实意味着这不仅仅是为了调试。在这种情况下,printk 不是正确的解决方案。您应该使用设备接口将信息从模块传递到用户空间。这就是它的用途。然后你的用户空间代码就可以打开/dev/mydevice 并从中读取数据。

printk 用于调试和诊断,而不是用于内核空间和用户空间之间的普通通信。如果有大量网络流量,您将完全淹没printk 缓冲区。

使用时间戳计数器可以很好地进行调试,但通常不适合稳定的长期时间测量(除其他外,处理器频率不同,并且多个处理器可能不同步)。最好使用ktime_getdo_gettimeofday 或其他内核时间接口之一。

【讨论】:

    猜你喜欢
    • 2014-11-29
    • 2014-12-12
    • 1970-01-01
    • 1970-01-01
    • 2016-12-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多