私の理解では、ユーザー空間プログラムは非特権モードで実行されるため、メモリや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アドレスへの直接の読み取り/ I/Oアドレスからの書き込みなどの特権操作は、システムコールを介してプロセッサを特権モードにすることによってのみ可能です。
ソース 。
権限のないプロセスによる/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
の権限をチェックして、安全であることを確認してください!
ユーザープロセスに表示されるアドレス(rootとして実行されているか、特権のないユーザーとして実行されているかに関係なく)は仮想アドレスであり、ページテーブルを通じてMMUによって物理アドレスにマップされます。ページテーブルの設定は特権操作であり、カーネルコードによってのみ実行できますが、ページテーブルが設定されると、ユーザーモードでメモリへのアクセスが許可されます。
具体的には、コードはmmap
を使用して、カーネルが特定の範囲の物理メモリにアクセスできるようにページテーブルを設定するように要求します。カーネルは、プロセスの特権(/dev/mem
への読み取り/書き込みアクセス権を持っている)をチェックし、物理メモリにアクセスできるようにページテーブルを設定します。
leds
の値は仮想アドレスです。現在のプロセスのユーザー空間にある限り、プロセスはRAMのどこにあるかに関係なく、特権モードである必要なく、leds[0] = val
のような命令を介して直接アクセスできます。仮想アドレスはマッピングされます