web-dev-qa-db-ja.com

特定のメモリ位置への書き込み

/proc/devices- tree内のファイルを正確に編集しようとしていますが、編集できません。

「許可が拒否されました」または「入出力エラー」。

chownchmod、さらにはSudo ddのエディターのすべての可能な組み合わせを試しました。 16進数で7000c400に書き込む正確なメモリの場所も知っています。私はそこに4バイトを置き換える必要がありますが、これを達成するのに役立つ方法がありますか?.

編集:これを試して達成しようとしていることは何ですか?

  • Jetson-TK1ボードがあり、i2cバスが設定されています400kHzのデフォルトに設定しますが、100kHzで実行したいです。デバイスツリー構造と再コンパイルを変更することでそれができると思いますが、使用しているカーネルは標準のものではないため、再コンパイルは非常に大きな頭痛の種です(nvidiaはそれを提供していません)。

    Linuxでは、ほとんどすべてのものがファイルの形であると読んでいた。それを探して、400000と評価される4バイトを含むファイルを見つけました。このファイルを変更すると頻度が変わると思います。

  • 今、本当の問題は、それを変更できなかったことです(私はまともなユーザーだと思います、そして私が理解する限り、メモリに何かがあり、あらゆる種類のパスワードを持っているなら、私はそれを変更できるはずです。私が何かを台無しにするという事実は問題ではありません)。私が知っているすべての可能な方法を試しました(質問に追加しました)。だから私はそれをどのように行うのですか?.

5
Rishabh

私はこれを主に楽しみと学習のために(そしてできれば担当者のために!)調べました。 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-treedevice-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.shbashスクリプトです。

#!/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. 二重引用符で囲まれたまったく同じ名前を使用して、上記の3つのファイルを作成します
  5. カスタムdevice-treeファイルを作成し、device-tree_newという名前を付けます
  6. switch.sh」を実行可能としてマーク:chmod a+x switch.sh
  7. モジュールをコンパイルします:makegccによって2つの警告がスローされます)
  8. bashスクリプトを起動します:./switch.sh
  9. cat /proc/device-treeは結果を見るために
3
kos

/proc/は擬似ファイルシステムです。/proc/fileで読み取り/書き込みを行う場合、実際のファイルまたは実際のメモリにはアクセスしませんが、機能する特定のカーネル関数(ファイルに応じて)を呼び出しますファイルとして。ファイルを読み取るとデータを返し、ファイルに書き込むとデータを設定します。また、特定のファイルに対して書き込み関数が定義されていない場合、ファイルへの書き込みは何も変更しません。

この場合、/proc/device-treeは、起動中に実行中のカーネルに提供されたデバイスツリーを読み取る方法です。 (書き込み許可なし)

また、現在、デバイスツリーは読み取り専用の構成であり、起動後に更新することはできません。また、特定のケースでは、i2cがプローブ(「インストール」)されたときに、i2cを構成する値が読み取られて使用されます。 i2cを再構成する場合は、前述のjoshumaxで、i2cデバイスで特定の[ドライバーエントリ]が定義されている/dev/デバイスで正しいioctlを使用する必要があります。 )

他の解決策の1つは、I2Cデバイスを必要に応じて構成し、新しいデバイスツリーを構築することです。そして、コンパイルしたデバイスツリーを使用するようにカーネルに依頼します(使用しているブートローダーを確認します)。

2
Nimlar

そのためには、Sudoを使用するルート権限が必要です。これを試してください:rootとして実行されているgdb(GNUデバッガー)を使用して、メモリの内容を操作できます。これらはあなたに興味があるかもしれません:

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

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

1
j0h