Почему эта разыменование к file_operations происходит таким образом? - PullRequest
0 голосов
/ 10 апреля 2020

Я ссылаюсь на эту статью, и я запутался в этом фрагменте кода здесь:

    /* get a copy of file_operations from inode */
    proc_fops = *proc_inode->i_fop;
    /* backup the file_operations */
    backup_proc_fops = proc_inode->i_fop;

file_operations - это структура (хранит функции VFS), а proc_inode будет указывать на inode file_operations (i_fop). Зачем ему это снова почитать? Почему бы не использовать то же самое, что и код backup_proc_fops?

Ссылки на структуры:

1 Ответ

2 голосов
/ 11 апреля 2020

Поскольку i_fop - это указатель на struct file_operations, если вы хотите скопировать структуру, на которую он указывает, вам нужно разыменовать ее.

This:

struct file_operations proc_fops;
proc_fops = *proc_inode->i_fop;

Скопирует весь struct file_operations, указанный i_fop. Другими словами, это целая структура, инициализированная из полей i_fop. Это то же самое, что сделать следующее:

struct mystruct { /*...*/ };

struct mystruct *ptr;
struct mystruct copy;

ptr = malloc(sizeof *ptr);
// ...

copy = *ptr;

С другой стороны, это:

backup_proc_fops = proc_inode->i_fop;

Копирует только указатель в struct file_operations и не его содержание. Это то же самое, что сделать следующее (продолжая из приведенного выше примера):

struct mystruct *another_ptr;
another_ptr = ptr;

В ссылке, на которую вы ссылаетесь, все это сделано, потому что proc_fops будет изменено и затем используется для замены исходного i_fop указателя в proc_inode:

/* modify the copy with out evil function */
proc_fops.iterate_shared = rk_iterate_shared;
/* overwrite the proc entry's file_operations */
proc_inode->i_fop = &proc_fops;

В то время как backup_proc_fops просто будет сохранять исходный указатель для восстановления позже, когда модуль выгружен:

/* get inode and restore file_operations */
proc_inode = p.dentry->d_inode;
proc_inode->i_fop = backup_proc_fops;

Вместо всего этого можно было бы сделать:

proc_inode->i_fop->iterate_shared = rk_iterate_shared;

, но , который изменил бы исходную структуру, сделав изменение необратимым.

...