GNU/Linux >> Belajar Linux >  >> Linux

Bagaimana cara mengakses alamat fisik dari ruang pengguna di Linux?

Anda dapat memetakan file perangkat ke memori proses pengguna menggunakan mmap(2) panggilan sistem. Biasanya, file perangkat memetakan memori fisik ke sistem file. Jika tidak, Anda harus menulis modul kernel yang membuat file tersebut atau menyediakan cara untuk memetakan memori yang diperlukan ke proses pengguna.

Cara lain adalah memetakan ulang bagian /dev/mem ke memori pengguna.

Sunting:Contoh mmaping /dev/mem (program ini harus memiliki akses ke /dev/mem, misalnya memiliki hak root):

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <unistd.h>

int main(int argc, char *argv[]) {
    if (argc < 3) {
        printf("Usage: %s <phys_addr> <offset>\n", argv[0]);
        return 0;
    }

    off_t offset = strtoul(argv[1], NULL, 0);
    size_t len = strtoul(argv[2], NULL, 0);

    // Truncate offset to a multiple of the page size, or mmap will fail.
    size_t pagesize = sysconf(_SC_PAGE_SIZE);
    off_t page_base = (offset / pagesize) * pagesize;
    off_t page_offset = offset - page_base;

    int fd = open("/dev/mem", O_SYNC);
    unsigned char *mem = mmap(NULL, page_offset + len, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, page_base);
    if (mem == MAP_FAILED) {
        perror("Can't map memory");
        return -1;
    }

    size_t i;
    for (i = 0; i < len; ++i)
        printf("%02x ", (int)mem[page_offset + i]);

    return 0;
}

busybox devmem

busybox devmem adalah utilitas CLI mungil yang mmaps /dev/mem .

Anda bisa mendapatkannya di Ubuntu dengan:sudo apt-get install busybox

Penggunaan:baca 4 byte dari alamat fisik 0x12345678 :

sudo busybox devmem 0x12345678

Tulis 0x9abcdef0 ke alamat itu:

sudo busybox devmem 0x12345678 w 0x9abcdef0

Sumber:https://github.com/mirror/busybox/blob/1_27_2/miscutils/devmem.c#L85

mmap MAP_SHARED

Saat memetakan /dev/mem , Anda mungkin ingin menggunakan:

open("/dev/mem", O_RDWR | O_SYNC);
mmap(..., PROT_READ | PROT_WRITE, MAP_SHARED, ...)

MAP_SHARED membuat penulisan langsung masuk ke memori fisik, yang membuatnya lebih mudah untuk diamati, dan lebih masuk akal untuk penulisan register perangkat keras.

CONFIG_STRICT_DEVMEM dan nopat

Untuk menggunakan /dev/mem untuk melihat dan memodifikasi RAM biasa pada kernel v4.9, Anda harus mengepal:

  • nonaktifkan CONFIG_STRICT_DEVMEM (ditetapkan secara default di Ubuntu 17.04)
  • teruskan nopat opsi baris perintah kernel untuk x86

Port IO masih berfungsi tanpa itu.

Lihat juga:mmap dari /dev/mem gagal dengan argumen yang tidak valid untuk alamat virt_to_phys, tetapi alamatnya selaras dengan halaman

Pembersihan cache

Jika Anda mencoba menulis ke RAM alih-alih register, memori mungkin di-cache oleh CPU:Bagaimana cara mengosongkan cache CPU untuk wilayah ruang alamat di Linux? dan saya tidak melihat cara yang sangat portabel/mudah untuk membersihkannya atau menandai wilayah sebagai tidak dapat di-cache:

  • Bagaimana cara menulis memori ruang kernel (alamat fisik) ke file menggunakan O_DIRECT?
  • Bagaimana cara mengosongkan cache CPU untuk wilayah ruang alamat di Linux?
  • Apakah mungkin mengalokasikan, di ruang pengguna, blok memori yang tidak dapat di-cache di Linux?

Jadi mungkin /dev/mem tidak dapat digunakan dengan andal untuk meneruskan buffer memori ke perangkat?

Sayangnya, hal ini tidak dapat diamati di QEMU, karena QEMU tidak mensimulasikan cache.

Cara mengujinya

Sekarang untuk bagian yang menyenangkan. Berikut ini beberapa penyiapan keren:

  • Memori pengguna
    • alokasikan volatile variabel pada proses userland
    • dapatkan alamat fisik dengan /proc/<pid>/maps + /proc/<pid>/pagemap
    • ubah nilai di alamat fisik dengan devmem , dan saksikan proses userland bereaksi
  • Memori kernelland
    • alokasikan memori kernel dengan kmalloc
    • dapatkan alamat fisik dengan virt_to_phys dan meneruskannya kembali ke userland
    • ubah alamat fisik dengan devmem
    • kueri nilai dari modul kernel
  • IO mem dan perangkat platform virtual QEMU
    • buat perangkat platform dengan alamat register fisik yang diketahui
    • gunakan devmem untuk menulis ke register
    • tonton printf s keluar dari perangkat virtual sebagai tanggapan

Bonus:tentukan alamat fisik untuk alamat virtual

Apakah ada API untuk menentukan alamat fisik dari alamat virtual di Linux?


Linux
  1. Linux – Bagaimana Cara Masuk Pengguna Ke Tty Dari Ssh?

  2. Cara Menghapus Pengguna Dari Grup di Linux [Kiat Singkat]

  3. Cara mengatur alamat IP dari C di linux

  1. Cara Menambah atau Menghapus Pengguna dari Grup di Linux

  2. Bagaimana Mengakses Folder Bersama Windows dari Linux?

  3. Bagaimana cara mengakses (jika mungkin) ruang kernel dari ruang pengguna?

  1. Bagaimana menemukan alamat IP Anda di Linux

  2. Bagaimana cara memetakan buffer kernel Linux ke ruang pengguna?

  3. Cara mengetahui penggunaan memori pengguna di linux