
私の理解では、ユーザー空間プログラムは非特権モードで実行されるため、メモリや I/O に直接アクセスすることはできません。
それでは、ユーザー空間プログラムで /dev/mem を mmap するときに、メモリまたは I/O の場所に直接アクセスするにはどうすればよいでしょうか?
例えば:
int fd = 0;
u8 leds = 0;
fd = open("/dev/mem", O_RDWR|O_SYNC);
leds = (u8 *)mmap(0, getpagesize(), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0x80840000);
これは組み込みデバイスで非常によく使用されるハックです。
これで、この変数をleds
オンザフライで使用して、0x80840000 に存在する可能性のある任意のデバイスにアクセスできるようになります。
今後、そのアドレスにアクセスするためにシステム コールを使用することはありません。
こんなものでも
leds[0x20] = val;
動作するでしょう。
しかし、I/O アドレスへの直接の読み取りや書き込みなどの特権操作は、システム コールを通じてプロセッサを特権モードにすることによってのみ可能になるはずです。
ソース。
答え1
権限のないプロセスによるアクセスを許可することは/dev/mem
、確かにセキュリティ上の問題となるため、許可されるべきではありません。
私のシステムではls -l /dev/mem
次のようになります:
crw-r----- 1 root kmem 1, 1 Sep 8 10:12 /dev/mem
つまり、root
読み取りと書き込みは可能ですが、kmem
グループのメンバー (実際には誰もいません) は読み取りはできますが書き込みはできず、他のユーザーはファイルを開くことができません。したがって、これは安全なはずです。
あなたの状況が私の状況と似ているなら/dev/mem
、権限のないプロセスではファイルを開くことすらできないはずですmmap
。
/dev/mem
システムの権限をチェックして、安全であることを確認してください。
答え2
ユーザー プロセス (root として実行されているか、権限のないユーザーとして実行されているかに関係なく) に表示されるアドレスは仮想アドレスであり、ページ テーブルを介して MMU によって物理アドレスにマップされます。ページ テーブルの設定は特権操作であり、カーネル コードによってのみ実行できます。ただし、ページ テーブルが設定されると、ユーザー モードでメモリにアクセスできるようになります。
具体的には、コードでは を使用して、mmap
カーネルがページ テーブルを設定して物理メモリの特定の範囲にアクセスできるように要求します。カーネルはプロセスの権限 ( への読み取り/書き込みアクセス権がある/dev/mem
) をチェックし、ページ テーブルを設定して物理メモリにアクセスできるようにします。
答え3
の値はleds
仮想アドレスです。現在のプロセスのユーザー空間にある限り、leds[0] = val
この仮想アドレスがRAMのどこにマップされているかに関係なく、プロセスは特権モードにならずに、のような命令を介して直接アクセスできます。