留下内核模块日志比printk()更好的方法?

时间:2015-06-17 11:08:09

标签: c linux linux-kernel kernel-module

我正在使用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__函数......

1 个答案:

答案 0 :(得分:0)

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

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

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