写入特定内存位置

Ris*_*abh 5 permissions nvidia kernel drivers io

我正在尝试在/proc/devices-tree 中编辑一个文件,确切地说,我无法这样做,我得到:

“权限被拒绝”或“输入/输出错误”。

我已经尝试了所有可能的编辑器组合chownchmod甚至sudo dd. 我也知道以7000c400十六进制写入的确切内存位置。我需要在那里替换 4 个字节,是否有任何方法可以帮助我实现这一目标。

编辑:我试图通过尝试实现什么?

  • 我有一个Jetson-TK1板,一个i2c总线设置为默认值400kHz,但我想在100kHz. 我想我可以通过更改设备树结构和重新编译来做到这一点,但重新编译是一个更大的麻烦,因为我使用的内核不是标准内核(nvidia 不提供)。

    我在某处读到过,在 Linux 中几乎所有东西都以文件的形式存在。所以在寻找它时,我发现了一个包含 4 个字节的文件,其计算结果为400000,我认为更改此文件会更改频率。

  • 现在真正的问题是我无法更改它(我认为我是一个足够体面的用户,据我所知,如果内存中有东西并且我有各种密码,我应该能够更改它。那事实上,我搞砸了一些事情不是问题)。我尝试了我已知的所有可能的方法(正如我在问题中添加的那样)。那我该怎么做。

kos*_*kos 3

我研究这个主要是为了乐趣和学习(希望是为了代表!)。我希望我能有更多的时间来玩ioctl(感谢 Sneetsher 的建议)以及我迄今为止所做的事情,以便做出更优雅的解决方案,但是赏金即将到期,我不太可能可以及时完成所有事情,因此我“按原样”发布此解决方案(至少目前如此)。

免责声明:

我不知道将某些内容更改为 的后果是什么/proc/device-tree,所以如果您真的知道自己在做什么,请继续阅读。

此解决方案的特定实现需要运行 > 3.10 的内核。它涉及自定义内核模块的编译和脚本的执行,以在自定义文件bash之间执行某种热切换。/proc/device-treedevice-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” (请注意,每行开头的所有空格都必须替换为一个字符):MakefilemakeTAB

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
Run Code Online (Sandbox Code Playgroud)

这是proc_module.c模块的“”源文件:

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
Run Code Online (Sandbox Code Playgroud)

这是“ switch.shbash脚本:

#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");
Run Code Online (Sandbox Code Playgroud)

指示:

  1. TerminalCtrl+ 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查看结果