/
bvs22
/
draft
Обзор
Документация
Войти
/
bvs22
/
draft
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
kernel/proc
336 строк
12 KB
Batomunkuev Vladimir
1
01 фев 2025, 12:14
01 фев 2025, 12:14
0c256c5
Код
Авторство
О чём код?
### Конспект по Файловой Системе proc в Ядре Linux #### Введение Файловая система `proc` (процессов) предоставляет интерфейс для взаимодействия с ядром операционной системы. Она позволяет пользовательским программам получать информацию о состоянии ядра и управлять некоторыми его аспектами. В этом конспекте рассмотрим основы использования файловой системы `proc`, API для создания и управления файлами в этой системе, а также примеры их использования. ### Основные аспекты работы с файловой системой proc 1. **Создание файла в `/proc`** - Используйте функцию `proc_create()` для создания файла в `/proc`. - Удаляйте файл с помощью функции `remove_proc_entry()`. 2. **Обработка чтения и записи** - Для обработки чтения и записи используйте структуру `file_operations`, которая содержит указатели на функции для различных операций файлов. 3. **Регистрация и удаление файлов** - Регистрируйте файлы при инициализации модуля и удаляйте их при завершении работы модуля. ### Основные API для работы с файловой системой proc 1. **`proc_create()`** - Создает новый файл в `/proc`. - Прототип: `struct proc_dir_entry *proc_create(const char *name, umode_t mode, struct proc_dir_entry *parent, const struct file_operations *proc_fops)` - Аргументы: - `name`: Имя файла. - `mode`: Разрешения доступа к файлу. - `parent`: Указатель на родительский каталог (например, `NULL` для корневого каталога `/proc`). - `proc_fops`: Указатель на структуру `file_operations`, содержащую функции для обработки файловых операций. 2. **`remove_proc_entry()`** - Удаляет файл из `/proc`. - Прототип: `void remove_proc_entry(const char *name, struct proc_dir_entry *parent)` - Аргументы: - `name`: Имя файла. - `parent`: Указатель на родительский каталог. 3. **Структура `file_operations`** - Содержит указатели на функции для различных операций файлов. - Пример структуры: ```c static const struct file_operations my_fops = { .owner = THIS_MODULE, .read = my_read, .write = my_write, }; ``` 4. **Функции для обработки чтения и записи** - Реализуйте функции для чтения и записи, которые будут вызываться при выполнении соответствующих операций над файлом. - Примеры функций: ```c static ssize_t my_read(struct file *file, char __user *ubuf, size_t count, loff_t *ppos) { // Обработка чтения } static ssize_t my_write(struct file *file, const char __user *ubuf, size_t count, loff_t *ppos) { // Обработка записи } ``` ### Пример: Создание простого файла в `/proc` #### Шаг 1: Создание исходного файла Создайте файл `proc_example.c` с содержимым: ```c #include <linux/module.h> #include <linux/kernel.h> #include <linux/init.h> #include <linux/proc_fs.h> // Для работы с файловой системой proc #include <linux/uaccess.h> // Для copy_to_user и copy_from_user MODULE_LICENSE("GPL"); MODULE_AUTHOR("Your Name"); MODULE_DESCRIPTION("A simple example of /proc file in Linux kernel"); MODULE_VERSION("0.1"); #define PROC_NAME "example" static int value = 0; // Функция для чтения из файла static ssize_t my_read(struct file *file, char __user *ubuf, size_t count, loff_t *ppos) { char buf[32]; int len; if (*ppos > 0) return 0; len = sprintf(buf, "%d\n", value); if (copy_to_user(ubuf, buf, len)) return -EFAULT; *ppos = len; return len; } // Функция для записи в файл static ssize_t my_write(struct file *file, const char __user *ubuf, size_t count, loff_t *ppos) { char buf[32]; if (count >= sizeof(buf)) return -EINVAL; if (copy_from_user(buf, ubuf, count)) return -EFAULT; buf[count] = '\0'; sscanf(buf, "%d", &value); return count; } static const struct file_operations my_fops = { .owner = THIS_MODULE, .read = my_read, .write = my_write, }; static int __init proc_init(void) { proc_create(PROC_NAME, 0666, NULL, &my_fops); printk(KERN_INFO "Module loaded: created /proc/%s\n", PROC_NAME); return 0; } static void __exit proc_exit(void) { remove_proc_entry(PROC_NAME, NULL); printk(KERN_INFO "Module unloaded: removed /proc/%s\n", PROC_NAME); } module_init(proc_init); module_exit(proc_exit); ``` #### Шаг 2: Создание Makefile Создайте файл `Makefile` рядом с исходным файлом: ```makefile obj-m += proc_example.o all: make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules clean: make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean ``` #### Шаг 3: Компиляция модуля Выполните команду `make` для компиляции модуля. Будет создан файл `proc_example.ko`. #### Шаг 4: Загрузка и выгрузка модуля - Загрузите модуль командой: `sudo insmod proc_example.ko` - Проверьте логи ядра: `dmesg | tail` - Выгрузите модуль командой: `sudo rmmod proc_example` #### Шаг 5: Работа с файлом в `/proc` - После загрузки модуля создается файл `/proc/example`. - Чтение значения: ```bash cat /proc/example ``` - Запись значения: ```bash echo 42 > /proc/example ``` ### Пример более сложного использования файла в `/proc` #### Шаг 1: Создание исходного файла Создайте файл `complex_proc_example.c` с содержимым: ```c #include <linux/module.h> #include <linux/kernel.h> #include <linux/init.h> #include <linux/proc_fs.h> #include <linux/uaccess.h> MODULE_LICENSE("GPL"); MODULE_AUTHOR("Your Name"); MODULE_DESCRIPTION("A more complex example of /proc file in Linux kernel"); MODULE_VERSION("0.1"); #define PROC_NAME "complex_example" static int values[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; // Функция для чтения из файла static ssize_t my_read(struct file *file, char __user *ubuf, size_t count, loff_t *ppos) { char buf[128]; int len, i; if (*ppos > 0) return 0; len = 0; for (i = 0; i < 10; i++) { len += sprintf(buf + len, "%d ", values[i]); } len += sprintf(buf + len, "\n"); if (copy_to_user(ubuf, buf, len)) return -EFAULT; *ppos = len; return len; } // Функция для записи в файл static ssize_t my_write(struct file *file, const char __user *ubuf, size_t count, loff_t *ppos) { char buf[128]; int val, i; if (count >= sizeof(buf)) return -EINVAL; if (copy_from_user(buf, ubuf, count)) return -EFAULT; buf[count] = '\0'; for (i = 0; i < 10; i++) { if (sscanf(buf, "%d", &val) != 1) break; values[i] = val; while (*buf && *buf != ' ') buf++; if (*buf) buf++; } return count; } static const struct file_operations my_fops = { .owner = THIS_MODULE, .read = my_read, .write = my_write, }; static int __init proc_init(void) { proc_create(PROC_NAME, 0666, NULL, &my_fops); printk(KERN_INFO "Module loaded: created /proc/%s\n", PROC_NAME); return 0; } static void __exit proc_exit(void) { remove_proc_entry(PROC_NAME, NULL); printk(KERN_INFO "Module unloaded: removed /proc/%s\n", PROC_NAME); } module_init(proc_init); module_exit(proc_exit); ``` #### Шаг 2: Создание Makefile Используйте тот же Makefile, что и в предыдущем примере. #### Шаг 3: Компиляция модуля Выполните команду `make` для компиляции модуля. Будет создан файл `complex_proc_example.ko`. #### Шаг 4: Загрузка и выгрузка модуля - Загрузите модуль командой: `sudo insmod complex_proc_example.ko` - Проверьте логи ядра: `dmesg | tail` - Выгрузите модуль командой: `sudo rmmod complex_proc_example` #### Шаг 5: Работа с файлом в `/proc` - После загрузки модуля создается файл `/proc/complex_example`. - Чтение значений: ```bash cat /proc/complex_example ``` - Запись значений: ```bash echo "10 20 30 40 50 60 70 80 90 100" > /proc/complex_example ``` ### Обработка ошибок и отладка 1. **Проверка ошибок** - Используйте `printk()` для вывода сообщений в журнал ядра. - Используйте макросы `pr_info()`, `pr_warn()`, `pr_err()` для более удобного вывода. 2. **Отладка** - Используйте `dmesg` для просмотра сообщений ядра. - Используйте `lsmod` для проверки загруженных модулей. - Используйте `modinfo` для получения информации о модуле. ### Дополнительные функции API 1. **`single_open()` и `single_release()`** - Используются для обработки файлов, которые содержат только одну строку данных. - Прототипы: - `int single_open(struct file *file, int (*show)(struct seq_file *m, void *v), void *data)` - `int single_release(struct inode *inode, struct file *file)` 2. **`seq_file` интерфейс** - Предоставляет удобный способ работы с файлами, которые содержат последовательность данных. - Пример использования: ```c static int my_seq_show(struct seq_file *m, void *v) { seq_printf(m, "Value: %d\n", value); return 0; } static int my_open(struct inode *inode, struct file *file) { return single_open(file, my_seq_show, NULL); } static const struct file_operations my_seq_fops = { .owner = THIS_MODULE, .open = my_open, .read = seq_read, .llseek = seq_lseek, .release = single_release, }; ``` ### Заключение Файловая система `proc` предоставляет мощный инструмент для взаимодействия с ядром операционной системы. Она позволяет пользовательским программам получать информацию о состоянии ядра и управлять некоторыми его аспектами. Правильное использование файловой системы `proc` позволяет эффективно управлять ресурсами и обеспечивать надежную работу драйверов и других компонентов ядра. Разработка и управление файлами в файловой системе `proc` требует понимания особенностей ядра и его взаимодействия с пользовательскими процессами. Правильное использование файловой системы `proc` позволяет избежать блокировок и обеспечить высокую производительность и стабильность системы.