2015-05-20 3 views
0

Я пытаюсь написать простые debugfs с операциями чтения и записи файлов. Код выглядит следующим образом.deadlock using read write lock в ядре

static ssize_t foo_read(struct file *fp, char __user *user, 
        size_t size, loff_t *loff) 
{ 
    ssize_t retval; 

    up_read(&foo_sem); 
    retval = simple_read_from_buffer(user, size, loff, fooBuffer, 
            fooBufferSize); 
    down_read(&foo_sem); 
    return retval; 
} 

static ssize_t foo_write(struct file *fp, const char __user *data, 
          size_t size, loff_t *loff) 
{ 
    ssize_t retval; 

    pr_debug("foo Write Funcion data %s=,size=%zu\n", data, size); 
    up_write(&foo_sem); 
    retval = simple_write_to_buffer(fooBuffer, sizeof(fooBuffer)-1, loff, 
              data, size); 
    if (retval > 0) { 
      fooBufferSize = size + *loff; 
      fooBuffer[fooBufferSize] = '\0'; 
    } 
    down_write(&foo_sem); 
    return retval; 
} 

И блокировка чтения записи инициализируется как

static DECLARE_RWSEM(foo_sem); 

Когда я скомпилировать код и запустить без замков он работает нормально.

Однако, когда я запускаю с блокировкой, программа, похоже, убита планировщиком.

[ 8640.104388] INFO: task a.out:6387 blocked for more than 120 seconds. 
[ 8640.104398]  Tainted: G   OE 3.17.0-rc5+ #1 
[ 8640.104402] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message. 
[ 8640.104407] a.out   D ffff88007fc14580  0 6387  1 0x00000004 
[ 8640.104415] ffff880075497df0 0000000000000002 ffff88007a0e9900 ffff880075497fd8 
[ 8640.104422] 0000000000014580 0000000000014580 ffffffff81c1d480 ffff88007a0e9900 
[ 8640.104428] ffff88007a0e9900 ffffffffa013b018 ffffffffa013b000 ffffffff00000000 
[ 8640.104434] Call Trace: 
[ 8640.104450] [<ffffffff8174a8a9>] schedule+0x29/0x70 
[ 8640.104460] [<ffffffff8174d62d>] rwsem_down_write_failed+0x1ed/0x390 
[ 8640.104472] [<ffffffff81381d03>] call_rwsem_down_write_failed+0x13/0x20 
[ 8640.104482] [<ffffffff8174cf7d>] ? down_write+0x2d/0x40 
[ 8640.104492] [<ffffffffa013906e>] foo_write+0x6e/0xa0 [firstmodule] 
[ 8640.104503] [<ffffffff811d42f7>] vfs_write+0xb7/0x1f0 
[ 8640.104513] [<ffffffff811d4e96>] SyS_write+0x46/0xb0 
[ 8640.104523] [<ffffffff8174f47f>] tracesys+0xe1/0xe6 
+0

Вы реверсирование использования '' up' и down' операций. Если вы хотите получить доступ к ресурсу, вызовите 'down', затем вызовите' up', когда вы закончите доступ. –

+0

Я думаю, что это моя ошибка, позвольте мне попробовать и вернуться. – Pradheep

ответ

3

Вы реверсирование использования up и down операций. Вызовите down, когда вы хотите получить доступ к ресурсу, затем вызовите up, когда вы закончите доступ.

Например:

down_read(&foo_sem); 
retval = simple_read_from_buffer(user, size, loff, fooBuffer, 
           fooBufferSize); 
up_read(&foo_sem); 
+0

Кажется, я запутался в методах вверх и вниз. Спасибо – Pradheep

+1

Да, мне сначала не нравились имена (я бы выбрал 'приобрести' и' релиз'). Я обнаружил, что мышление об этом как: «' down' == decred resource count »и« up' == increment resource count »помогло мне в начале. После того, как вы использовали семафоры в Linux несколько раз, вам больше не нужно об этом думать. –