Вопрос

Я пишу код для модуля ядра 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);. Анкет Когда вы добавляете звонок в printk() Компилятор не уверен, что data не изменяется и поэтому проверяет значение каждый раз через петлю.

Вы можете вставить барьер в петлю, что заставляет компилятор перенаправить data на каждой итерации. например:

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

        barrier();
}

Другие советы

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

Компилятор может обнаружить, что значение данных никогда не изменяется в цикле при этом. Поэтому он может полностью переместить чек из цикла, и вы получите простые

 while (1) {} 

Если вы вкладываете Printk, компилятор должен предположить, что глобальные данные переменной могут измениться (в конце концов - компилятор не имеет представления о том, что распечатано детально), поэтому ваш код снова начнет работать (в неопределенном поведении.

Как это исправить:

Используйте правильные примитивы синхронизации ниток. Если вы охватываете доступ к данным в раздел кода, защищенного Mutex, код будет работать. Вы можете также заменить данные переменных и вместо этого используйте подсчитанный семафор.

Редактировать:

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

Nils Pipenbrinck Ответ на месте. Я просто добавлю несколько указателей.

(Каждый хакер ядра должен прочитать это).
Прощай, семафоры?, Mutex API (lwn.net.

Кроме того, поскольку ваши общие данные являются простым счетчиком, вы можете просто использовать атомный API (в основном, объявить свой счетчик как Atomic_t и получить к нему доступ, используя функции Atomic_*).

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top