【问题标题】:Access /dev/mem from Linux kernel module从 Linux 内核模块访问 /dev/mem
【发布时间】:2014-10-16 19:25:27
【问题描述】:

我正在研究 Raspberry PI (Linux rpi 3.12.28+),我有以下 C 代码可用于操作 GPIO 端口:

// IO Acces
struct bcm2835_peripheral {
unsigned long addr_p;
int mem_fd; // memory file descriptor
void *map;
volatile unsigned int *addr;
};

struct bcm2835_peripheral gpio = {0x40000000};

// Exposes the physical address defined in the passed structure using mmap on /dev/mem
int map_peripheral(struct bcm2835_peripheral *p)
{
   // Open /dev/mem
   if ((p->mem_fd = open("/dev/mem", O_RDWR | O_SYNC) ) < 0) {
      return -1;
   }

   p->map = mmap(
      NULL,
      BLOCK_SIZE,
      PROT_READ | PROT_WRITE,
      MAP_SHARED,
      p->mem_fd,  // File descriptor to physical memory virtual file '/dev/mem'
      p->addr_p   // Address in physical map that we want this memory block to expose
   );

   if (p->map == MAP_FAILED) {
        return -1;
   }

   p->addr = (volatile unsigned int *)p->map;

   return 0;
}

以上代码适用于普通程序(用户空间)。但我需要创建一个 Linux 内核模块来做同样的事情。问题是编译器无法识别 open() 或 mmap() 等方法。将此代码转换为内核模块(驱动程序)的合适方法是什么?这些函数可用于内核编程还是我应该以不同的方式进行?我见过像 syscall_open()、filp​​_open()、sys_mmap2() 这样的方法,但我很困惑。我将不胜感激。

【问题讨论】:

  • 内核代码已经可以访问所有内存,不需要打开/dev/mem。请注意物理地址与虚拟地址。

标签: c linux kernel raspberry-pi driver


【解决方案1】:

您在内核空间中没有系统调用(打开、关闭、读取、写入等),相反,您必须使用模块提供的内部接口,但似乎不是您的情况.

考虑到您正在访问/dev/mem,我想您正在尝试读取 RaspberyPi 的物理内存。由于没有内存保护,您可以从内核空间直接访问它,但是您必须使用phys_to_virt 函数来转换地址。

【讨论】:

    【解决方案2】:

    确实不需要在内核模块中访问/dev/mem。使用phys_to_virt 直接访问内存是一种操作内存的解决方案,但如果目标是操作 GPIO 端口,则它不适用于 Raspberry PI。

    解决方案是访问硬件寄存器。我在这里找到了很好的教程:

    Creating a Basic LED Driver for Raspberry Pi

    【讨论】:

      猜你喜欢
      • 2012-08-07
      • 2015-07-08
      • 1970-01-01
      • 1970-01-01
      • 2015-10-05
      • 1970-01-01
      • 2011-09-02
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多