2013-07-15 2 views
1

Я пытался выяснить, как работают файловые операции в драйверах. Я знаю, что существует несколько операций с файлами, но функции для этих операций вызывают несколько аргументов, а сами операции определяются без каких-либо.Операции с файлами в драйверах

Так что, если я это -

static const struct file_operations proc_myled_operations = { 
    .open = proc_myled_open, 
    .read = seq_read, 
    .write = proc_myled_write, 
    .llseek = seq_lseek, 
    .release = single_release 
}; 

Теперь я знаю, что драйвера уровня ядра могут быть доступны только в виде файлов из пользовательского приложения. Это встроенная система, поэтому у меня есть некоторые светодиоды, которые я могу включить, записав в свои регистры с отображением памяти.

Таким образом вызов .write или "proc_myled_write" будет выполняться, когда я поворачиваю светодиод, на котором я могу сделать, открыв этот файл, используя fopen, а затем записывая его с помощью fputs. Но если .WRITE отображается как «proc_myled_write и эта функция имеет аргументы, как так? -.

static ssize_t proc_myled_write(struct file *file, const char __user * buf, 
size_t count, loff_t * ppos) 

Что происходит с аргументами Там нет вызова функции для вышеупомянутой функции с теми аргументами, я видел это в несколько Я просто использовал это, потому что это был простой пример. Как операции с файлами сопоставляются с этими функциями? Как, например, «записывать» на трассе пользовательского пространства на запись в драйвере?

Thank вы

ответ

5

Я не совсем уверен, что вы имеете в виду, когда говорите: «Нет функции вызова вышеуказанной функции с этими аргументами ts. "

Прототип этих функций определен в declaration for struct file_operations itself.

Вот первые несколько строк из декларации STRUCT:

struct file_operations { 
    struct module *owner; 
    loff_t (*llseek) (struct file *, loff_t, int); 
    ssize_t (*read) (struct file *, char __user *, size_t, loff_t *); 
    ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *); 
    ... 

Хотя аргументы не названы в объявлении, вы можете ясно видеть, что функция write() объявляется с 4 параметрами сопоставления типов, которые вы упоминание в вашем вопросе.

Когда вы назначаете функцию в соответствующее поле (proc_myled_operations.write = proc_myled_write), вы просто передаете указатель на функцию записи, объявленную и определенную в вашем модуле. Указатели на сами функции не нуждаются в параметрах.


Итак, вы действительно задаетесь вопросом: «Как вызов системы пользовательского пространства в конечном итоге вызывает функцию записи в вашем модуле?» Хороший вопрос! Я рекомендую отредактировать ваш вопрос, чтобы сделать это более четким для будущих читателей.

Хорошо, давайте посмотрим, смогу ли я следовать бумажной тропе. Я открыл this document, чтобы дать мне исходное местоположение, чтобы посмотреть в коде для системного вызова write(). Это очень очень старый, но эй, не все меняется в ядре! Мы начинаем наше путешествие в объявлении вызова в write() системы в fs/read_write.c:

SYSCALL_DEFINE3(write, unsigned int, fd, const char __user *, buf, 
      size_t, count) 

Он использует дескриптор файла fd получить struct file созданные при регистрации драйвера вашего персонажа. Затем он получает текущую позицию в файле и вызывает vfs_write().

ssize_t vfs_write(struct file *file, const char __user *buf, size_t count, loff_t *pos) 

И он в этой функции см the following line:

ret = file->f_op->write(file, buf, count, pos); 

Там это!

Чтобы рассеять любые сомнения относительно типа file->f_op, мы посмотрим на the definition of struct file и посмотреть the following definition for the f_op field:

const struct file_operations *f_op; 

Так должно быть struct file_operations вы прошли, когда вы зарегистрировали свой драйвер. Уф!

Надеемся, что все эти ссылки покажут вам, как следует следить за другими системными вызовами, если вам интересно.

+0

Да точно! Вот как я думал, что понял. Но тогда что-то нужно вызвать функцию записи где-нибудь с аргументами? Я знаю, что структура файла уникальна для драйверов пространства ядра, а приложения для приложений пользователей не видят/не могут использовать его, но как насчет остальных трех аргументов? Как функция записи (или proc_myled_write, в любом случае) знает, в какой памяти хранятся аргументы? – maverick1989

+0

Взгляните на мое обновление выше. Ура! –

+0

Спасибо, Бен! Могу я назвать тебя Беном? Это было действительно хорошее объяснение! Я также принял ваше предложение и отредактировал мой вопрос. Еще раз спасибо ... – maverick1989

1

@Maverick, прототип записи или подпись в ядре - ssize_t (* write) (struct file *, const char __user *, size_t, loff_t *). Из пользовательского пространства вы получите , Системный вызов для включения/выключения светодиода. Записать системную подпись в пользовательском пространстве - int write (int fd, const char * buf, size_t count). Поэтому, когда вы звоните записи из пользовательского пространства, Fd (дескриптор файла) передается достигает файловую систему виртуальной (VFS), поддерживает связанный список дескрипторов таблицы открытого файла (OFDT), таким образом, в соответствии с Fd, OFDT имеет указатель filp (указатель файла), указывающий на файл, открытый для ex: device node "/ dev/xxx" или любой другой файл, если на то пошло. Остальные buf и count - те же аргументы, переданные из пользовательского пространства в пространство ядра. Последний loff_t * FPOS входит в картину, если вы хотите искать файл для ех: использование lseek или FSEEK на открытый файл, если искать, то указатель файла (loff_t FPOS) позиция получает соответственно меняется. Надеюсь, я очистил ваши сомнения :-)

+0

Большинство моих сомнения, да. Тем не менее, один оператор в вашем ответе - «Запись сигнатуры системного вызова в пространстве пользователя - это int write (int fd, const char * buf, size_t count)». Этот вызов не существует в файле примера, который я просматриваю. Мой примерный код имеет вызов драйвера и пользователя, чтобы открыть файл драйвера и написать ему. Тем не менее, он делает это, используя fopen, чтобы открыть файл под/dev/myled (myled - это имя объекта драйвера) для записи (в режиме «w»), а затем делает puts для записи на него. Вот и все. Существует не фактическая функция CALL, как вы сказали. Это источник моей путаницы. – maverick1989

+0

@Maverick, fopen turn, чтобы открыть системный вызов для вашей информации, аналогично fread/fwrite превращается в системный вызов для чтения/записи до достижения уровня vfs или пространства ядра. –

+0

Хорошо, но независимо, где-то, что-то нужно вызвать, что операции с файлами записывают функцию с этими аргументами правильно? – maverick1989