2013-07-05 5 views
4

Я пытаюсь скопировать значение из пользовательского пространства в пространство ядра с помощью функции:Как правильно использовать copy_from_user?

static ssize_t device_write(struct file *filp, const char *buff, size_t len, loff_t *off) 
{ 

    unsigned long copy=0; 
    int desp=0; 

    copy = copy_from_user(&desp, &len, 4); 

    printk(KERN_ALERT "copy: %lx\n", copy);  
    printk(KERN_ALERT "desp: %d\n", desp); 
} 

где «Len» является переменной, которая существует в пользовательском пространстве, и я хочу, чтобы скопировать его в «Desp» в пространстве ядра

вызова функции Я делаю из пользовательского пространства (запись является device_write согласно file_operations структуре):

write (fd,buffer,8, &off); 

при печати значения, которое должно быть сохранено в «ДЭСПЕ» всегда 0 (должно быть 8). В чем проблема с кодом? Я видел несколько примеров, и я реализовал множество вариантов, но никто не работает.

ответ

4

write прототип функции в руководстве:

ssize_t write(int fd, const void *buf, size_t count);

Так что вам нужно только пройти 3 значения write, а именно: дескриптор файла fd, buffer, где ваши данные ложь и count байтов вы хотите написать.

Это касается пространства пользователя. Теперь перейдем к функции записи пространства ядра, то есть к вашему device_write.

Аргумент buf этой функции - это тот, который содержит данные, которые вы хотите записать из пользовательского пространства, count - это длина данных, отправляемых для записи ядром. Таким образом, вы должны скопировать данные с указателя buf, а не len.

Таким образом, правильный путь будет:

char *desp; //allocate memory for this in kernel using malloc 
copy_from_user (desp, buff, len); 

Это должно сделать.

+0

проблема заключалась в том, что системный вызов имеет только 3 параметра, и я хотел использовать 4, которые находятся в методе структуры файловых операций (device_read/write). Таким образом, при размещении в пространстве ядра компилятор не дает никаких предупреждений о числе параметров, которые имеют методы (это разные) Я пробовал сделать систему llamdas 5 параметров! и компиляция и выполнение не предупреждаются о какой-либо проблеме ... Спасибо за ваши ответы !!! – eduardosufan

4

lenне есть в пользовательском пространстве. Он передается по значению, поэтому len доступен как обычная переменная в пространстве ядра. desp = (int)len - это все, что вам нужно. Обратите внимание, однако, что size_t не совпадает с int, а на 64-битных платформах size_t - 8 байт.

copy_from_user() предназначен для буфера, который вы пытаетесь написать (в коде вашего пользователя-пространства buffer и buff в списке аргументов ядра). То, что передано, является указателем на адрес памяти, который существует только в пользовательском пространстве, поэтому copy_from_user() копирует этот буфер в буфер пространства ядра.

+0

уверен, но моя идея состоит в том, чтобы передать 4-й параметр, offset (loff_t *) и не достигает пространства ядра при выполнении вызовов из пользовательского пространства. Итак, я вижу эти переменные как пространство пользователя. С другой стороны, если я могу получить доступ непосредственно к «buff» из пространства ядра ... – eduardosufan

+1

Как вы можете сделать этот вызов из пользовательского пространства? 'write()' - это определенный интерфейс системного вызова, который принимает 3 параметра. Библиотека C и слой VFS ядра преобразуют этот вызов в свой обработчик 'device_write()'. Вы не можете просто добавить 4-й аргумент, и компилятор не позволит вам. Вы ищете 'pwrite' вместо этого? В любом случае, что это имеет отношение к вашему вопросу, на что я ответил? Если вы хотите спросить что-то другое, исправьте свой вопрос – Peter

+0

«прочитайте о pwrite/read, чтобы попытаться реализовать этот системный вызов, огромное спасибо! – eduardosufan