search
LoginSignup
9

More than 5 years have passed since last update.

posted at

Golangから物理メモリを読み書きする

Golangではシステムコールのmmapを使用することができるので、/dev/mem かUIOで作成した/dev/uioX をmmapすれば物理メモリを読み書きすることができます。
ここではUIOを使った例を紹介します。

UIOのデバイスを登録する

UIOについてはこの記事を参照してください。
LinuxのUIO(User space I/O) その1
この記事に従って、/dev/uio0 が作成できたとして、次にそれをGolangで書かれたプログラムからアクセスする方法を示します。

Golangのサンプルプログラム

ソースコードはgistに置きました。ここ

func mmapRegs32(addr uint32, n int) []uint32 {
    file := "/dev/uio0"

    f, err := os.Open(file)
    if err != nil {
        log.Fatal(err)
    }

    offset := int64(addr) &^ 0xfff
    data, err := syscall.Mmap(int(f.Fd()), offset, (n+0xfff)&^0xfff, syscall.PROT_READ, syscall.MAP_SHARED)
    if err != nil {
        log.Fatalf("mmap %s: %v", f.Name(), err)
    }
    f.Close()

    map_array := (*[math.MaxInt32 / 4]uint32)(unsafe.Pointer(&data[0]))
    return map_array[(addr&0xfff)/4 : ((int(addr)&0xfff)+n)/4]
}

Cのプログラムと同様のパラメータでSyscall.Mmap()を使用します。このメソッドは戻り値が[]byte です。
バイト単位でアクセスしたい場合はこれをこのまま使用すればよいです。
今回は4バイト単位でアクセスしたいので、[]uintの型で欲しいところです。
そのためには、一度大きなサイズのuint32の配列のポインタに変換してから、それをベースにする[]int のスライスを作成すればよいです。

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
What you can do with signing up
9