Запись в определенную область памяти

Я пытаюсь отредактировать файл внутри /proc/devices- если быть точным, и я не могу этого сделать, я получаю:

msgstr "разрешение отклонено" или "ошибка ввода / вывода".

Я перепробовал все возможные комбинации редакторов, chown, chmod и даже sudo dd, Я также знаю точное место в памяти для записи 7000c400 в шестнадцатеричном виде Мне нужно заменить 4 байта там, есть ли способ, который может помочь мне достичь этого.

Изменить: Что я пытаюсь достичь, пытаясь это?

  • У меня плата Jetson-TK1, и для шины i2c по умолчанию установлено значение 400kHz, но я хочу запустить его в 100kHz, Я думаю, что могу сделать это, изменив древовидную структуру устройства и перекомпиляцию, но перекомпиляция - намного большая головная боль, поскольку ядро, которое я использую, не является стандартным (nvidia этого не обеспечивает).

    Я где-то читал, что в Linux почти все в форме файла. Итак, ища его, я нашел файл, который содержит 4 байта, который оценивает 400000Я думаю, что изменение этого файла изменит частоту.

  • Теперь настоящая проблема в том, что я не смог изменить его (я думаю, что я достаточно порядочный пользователь, и, насколько я понимаю, если в памяти что-то есть и у меня есть все виды паролей, я должен иметь возможность изменить это. Дело в том, что я что-то испортил, это не вопрос). Я перепробовал все возможные методы, известные мне (как я добавил в вопросе). Так как мне это сделать.

3 ответа

Решение

Я смотрел на это в основном для удовольствия и для обучения (и, надеюсь, для представителя!). Я хотел бы иметь больше времени, чтобы поиграть с ioctl (спасибо Sneetsher за предложение) и с тем, что я сделал до сих пор, чтобы сделать более элегантное решение, но щедрость истекает, и вряд ли я смогу сделать все вовремя, поэтому я публикую это решение "как есть" (по крайней мере пока).

Отказ от ответственности:

Я не знаю, каковы последствия изменения чего-либо в /proc/device-tree , так что если вы действительно знаете, что делаете, продолжайте читать.

Эта конкретная реализация этого решения требует работающего ядра> 3.10. Он включает в себя компиляцию пользовательского модуля ядра и выполнение bash скрипт для выполнения своего рода горячего переключения между /proc/device-tree и пользовательский файл device-tree_new,

Пределы:

  1. При удалении модуля кастом /proc/device-tree это удалено! Еще одна причина, чтобы прочитать отказ от ответственности снова.
  2. Обычай /proc/device-tree Буфер имеет предел 65535 персонажи. Все над 65535 символ усекается. Чтобы настроить размер буфера, измените следующее определение константы и объявление переменной в исходном коде модуля:

    1. #define MAX_BUFFER_SIZE 65535
    2. static unsigned int proc_buffer_length_v; (чтобы он мог содержать число> 65535)

Как это устроено:

Сам модуль:

  • удалений /proc/device-tree
  • создает новый пробел /proc/device-tree с разрешениями 0666

bash сам скрипт:

  1. Загружает модуль
  2. Пишет в /proc/device-tree содержание device-tree_new

Это " Makefile " Makefile для модуля (обратите внимание, что все пробелы в начале каждого make линия должна быть заменена на TAB характер):

obj-m += proc_module.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

Это " proc_module.c "исходный файл модуля:

#include <linux/module.h>
#include <linux/init.h>
#include <linux/proc_fs.h>
#include <linux/slab.h>
#include <linux/uaccess.h>

#define DEBUG 1
#define MAX_BUFFER_SIZE 65535

static struct proc_dir_entry* proc_dir_entry_p;
static struct file_operations file_operations_s;
static char* proc_buffer_p;
static unsigned int proc_buffer_length_v;
static unsigned short int read_flag;

int read_proc(struct file* file, char* buffer, size_t count, loff_t* offset) {
    if(DEBUG) printk(KERN_INFO "read_proc() called.\n");
    if(read_flag)
        read_flag = 0;
    else {
        read_flag = 1;
        return 0;
    }
    copy_to_user(buffer, proc_buffer_p, proc_buffer_length_v);
    if(DEBUG) printk(KERN_INFO "Ok. (count = %zu)\n", count);
    return proc_buffer_length_v;
}

int write_proc(struct file* file, char* buffer, size_t count, loff_t* offset) {
    size_t n;
    if(DEBUG) printk(KERN_INFO "write_proc() called.\n");
    if(count >= MAX_BUFFER_SIZE) {
        if(DEBUG) printk(KERN_INFO "write_proc(): Buffer exceeded!\n");
        n = MAX_BUFFER_SIZE;
    }
    else
        n = count;
    kfree(proc_buffer_p);
    if(DEBUG) printk(KERN_INFO "kfree() called.\n");
    if(!(proc_buffer_p = (char*)kmalloc(MAX_BUFFER_SIZE*sizeof(char), GFP_KERNEL))) {
        if(DEBUG) printk(KERN_INFO "kmalloc() ko.\n");
        return count;
    }
    if(DEBUG) printk(KERN_INFO "kmalloc() ok.\n");
    copy_from_user(proc_buffer_p, buffer, n);
    proc_buffer_length_v = n;
    if(DEBUG) printk(KERN_INFO "Ok. (count = %zu)\n", count);
    return count;
}

static int __init init_f(void) {
    if(DEBUG) printk(KERN_INFO "Module inserted.\n");
    remove_proc_entry("device-tree", NULL);
    if(!(proc_dir_entry_p = proc_create("device-tree", 0666, NULL, &file_operations_s))) {
        if(DEBUG) printk(KERN_INFO "Proc entry not created.\n");
        return -1;
    }
    if(DEBUG) printk(KERN_INFO "Proc entry created.\n");
    file_operations_s.read = read_proc;
    file_operations_s.write = write_proc;
    if(!(proc_buffer_p = (char*)kmalloc(1*sizeof(char), GFP_KERNEL))) {
        if(DEBUG) printk(KERN_INFO "kmalloc() ko.\n");
        return -1;
    }
    if(DEBUG) printk(KERN_INFO "kmalloc() ok.\n");
    proc_buffer_p[0] = '\0';
    proc_buffer_length_v = 0;
    read_flag = 1;
    if(DEBUG) printk(KERN_INFO "Ok.\n");
    return 0;
}

static void __exit exit_f(void) {
    kfree(proc_buffer_p);
    if(DEBUG) printk(KERN_INFO "kfree() called.\n");
    proc_remove(proc_dir_entry_p);
    if(DEBUG) printk(KERN_INFO "Proc entry removal requested.\n");
    if(DEBUG) printk(KERN_INFO "Module removed.\n");
}

module_init(init_f);
module_exit(exit_f);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("kos");
MODULE_DESCRIPTION("proc_module");

Это " switch.sh " bash сценарий:

#!/bin/bash

sudo rmmod proc_module.ko
sudo insmod proc_module.ko && cat device-tree_new > /proc/device-tree

Инструкции:

  1. Открыть Terminal с помощью Ctrl + Alt + t
  2. Создать новую папку: mkdir <folder_name>
  3. Измените текущий рабочий каталог на новую папку: cd <folder_name>
  4. Создайте три файла выше, используя точно такие же имена, заключенные в двойные кавычки
  5. Создать кастом device-tree файл и назовите его device-tree_new
  6. Отметка " switch.sh "как исполняемый файл: chmod a+x switch.sh
  7. Скомпилируйте модуль: make (два предупреждения будут брошены gcc)
  8. Запустите bash сценарий: ./switch.sh
  9. cat /proc/device-tree чтобы увидеть результат

/proc/ такое псевдо файловая система: когда вы читаете / пишете на любом /proc/file у вас нет доступа к реальному файлу или реальной памяти, но вы вызываете некоторую конкретную функцию ядра (в зависимости от файла), которая действует как файл. Он возвращает данные, если вы читаете файл, установите данные, если вы пишете в файл. И если для определенного файла не определена функция записи, запись в файл ничего не изменит.

В этом случае /proc/device-tree способ прочитать дерево устройств, предоставляемое работающему ядру во время его загрузки (без записи)

Более того, в настоящее время дерево устройств доступно только для чтения, его нельзя обновить после загрузки. И для вашего конкретного случая, значения, настраивающие ваш i2c читаются и используются, когда i2c зондируется ("установлен"). Если вы хотите перенастроить i2c, вам нужно, как сказал joshumax, чтобы использовать правильный ioctl на i2c устройство (в /dev/ где определены некоторые конкретные "записи драйвера")

Еще одним решением является создание нового дерева устройств, настройка I2C Устройство, как вы хотите. И попросите ядро ​​(проверьте используемый вами загрузчик) использовать дерево устройств, которое вы только что скомпилировали.

Для этого вам понадобятся полномочия root. Попробуйте это: вы можете использовать gdb (GNU Debugger), работающий от имени пользователя root, для манипулирования содержимым памяти. Это может вас заинтересовать:

http://sourceware.org/gdb/current/onlinedocs/gdb/

https://stackoverflow.com/questions/3305164/how-to-modify-memory-contents-using-gdb

Другие вопросы по тегам