Драйвер устройства Linux - что не так с моим device_read ()? - PullRequest
0 голосов
/ 14 апреля 2010

Я писал устройство dev / my_inc , которое должно принимать положительное целое число N , представленное в виде строки ASCII, и хранить его внутри. Любое чтение с устройства должно привести к строковому представлению ASCII целого числа (N + 1) .

Однако, когда я cat /dev/my_inc, мне кажется, что только первая половина буфера сообщений myinc_value возвращается в пространство пользователя.

  • Если myinc_value равно 48, cat /dev/my_inc дает 4.

  • Если myinc_value равно 489324, cat /dev/my_inc yields 489.

Однако bytes_read указывает, что все сообщение было скопировано в пространство пользователя. Вот вывод из dmesg :

[54471.381170] my_inc opened with initial value 489324 = 489324.
[54471.381177] my_inc device_read() called with value 489325 and msg 489324.
[54471.381179] my_inc device_read() read 4.
[54471.381182] my_inc device_read() read 8.
[54471.381183] my_inc device_read() read 9.
[54471.381184] my_inc device_read() read 3.
[54471.381185] my_inc device_read() read 2.
[54471.381186] my_inc device_read() read 5. my_inc device_read() returning 7.
[54471.381192] my_inc device_read() called with value 489325 and msg 489325.

А при вызове из оболочки:

root@rbst:/home/rob/myinc_mod# cat /dev/my_inc
489

И источник:

// Read from the device
//
static ssize_t device_read(struct file * filp, char * buffer, 
    size_t length, loff_t * offset)
{
    char c;
    int bytes_read = 0;
    int value = myinc_value + 1;

    printk(KERN_INFO "my_inc device_read() called with value %d and msg %s.\n", 
        value, msg);

    // Check for zero pointer
    if (*msg_ptr == 0) 
    {
        return 0;
    }
    // Put the incremented value in msg 
    snprintf(msg, MAX_LENGTH, "%d", value);

    // Copy msg into user space
    while (length && *msg_ptr) 
    {
        c = *(msg_ptr++);
        printk(KERN_INFO "%s device_read() read %c. ", DEV_NAME, c);
        if(put_user(c, buffer++))
        {
            return -EFAULT;
        }
        length--;
        bytes_read++;
    }

    // Nul-terminate the buffer
    if(put_user('\0', buffer++))
    {
        return -EFAULT;
    }
    bytes_read++;
    printk("my_inc device_read() returning %d.\n", bytes_read);
    return bytes_read;
}

Ответы [ 2 ]

2 голосов
/ 15 апреля 2010

Возможно, что put_user () определен как макрос, так что оператор постинкремента в

if(put_user(c, buffer++))

облажался - хотя я не понимаю, как это объясняет то, что вы видите.

В любом случае было бы удобнее и эффективнее использовать copy_to_user () для копирования всего сообщения.

1 голос
/ 14 апреля 2010

Причина, по которой он показывает только 1 байт, заключается в том, что вы увеличиваете msg_ptr перед тем, как установить его равным c. Это должно быть c = * msg_ptr ++; или c = * msg_ptr; msg_ptr ++; так что приращение происходит после присваивания

...