multithreading - Linux 内核模块中 printk 的奇怪行为

标签 multithreading linux-kernel printk

我正在为 Linux 内核模块编写代码,并遇到了奇怪的行为。 这是我的代码:

int data = 0;
void threadfn1()
{
    int j;
    for( j = 0; j < 10; j++ )
        printk(KERN_INFO "I AM THREAD 1 %d\n",j);   
    data++;
}

void threadfn2()
{
    int j;
    for( j = 0; j < 10; j++ )
        printk(KERN_INFO "I AM THREAD 2 %d\n",j);
    data++; 
}
static int __init abc_init(void)
{
        struct task_struct *t1 = kthread_run(threadfn1, NULL, "thread1");
        struct task_struct *t2 = kthread_run(threadfn2, NULL, "thread2");
        while( 1 )
        {
        printk("debug\n"); // runs ok
            if( data >= 2 )
            {
                kthread_stop(t1);
                kthread_stop(t2);
                break;
            }
        }
        printk(KERN_INFO "HELLO WORLD\n");

 }

基本上,我试图等待线程完成,然后再打印一些内容。 上面的代码确实实现了该目标,但没有注释 "printk("debug\n");" 。一旦我注释掉 printk("debug\n"); 以在不调试的情况下运行代码并通过 insmod 命令加载模块,该模块就会挂起,并且似乎在递归中丢失了。我不明白为什么 printk 对我的代码影响这么大?

如有任何帮助,我们将不胜感激。

问候。

最佳答案

您没有同步对数据变量的访问。发生的情况是,编译器将生成无限循环。原因如下:

  while( 1 )
        {
            if( data >= 2 )
            {
                kthread_stop(t1);
                kthread_stop(t2);
                break;
            }
        }

编译器可以检测到 data 的值在 while 循环内永远不会改变。因此,它可以完全将检查移出循环,您最终会得到一个简单的

 while (1) {} 

如果你插入 printk ,编译器必须假设全局变量数据可能会改变(毕竟 - 编译器不知道 printk 详细做什么),因此你的代码将再次开始工作(以一种未定义的行为方式) ..)

如何解决这个问题:

使用正确的线程同步原语。如果将对数据的访问包装到受互斥锁保护的代码部分中,则代码将起作用。您还可以替换变量数据并使用计数信号量。

编辑:

此链接解释了 Linux 内核中的锁定如何工作:

http://www.linuxgrill.com/anonymous/fire/netfilter/kernel-hacking-HOWTO-5.html

关于multithreading - Linux 内核模块中 printk 的奇怪行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4113176/

相关文章:

c++ - volatile 和多线程 : is the following thread-safe?

java - 线程等待时出现大量 IllegalMonitorStateException

Linux I2C 内核驱动绑定(bind)

linux - IA32 IDT 和 linux 中断处理程序

linux - 在内核代码中获取当前工作目录

c - 如何在printk中使用变量作为格式字符串?

c - 为什么 printk 不在内核日志中打印消息(dmesg)

linux - Linux 内核中的 printk 时间戳解析

java - NIO 选择器 : How to properly register new channel while selecting

multithreading - WCF 中的 UnitOfWork 与 Quartz(线程)