简体   繁体   English

mmap比ioremap慢

[英]mmap slower than ioremap

I am developing for an ARM device running Linux 2.6.37. 我正在为运行Linux 2.6.37的ARM设备开发。 I am trying to toggle an IO pin as fast as possible. 我试图尽可能快地切换IO引脚。 I made a little kernel module and a user space application. 我制作了一个小内核模块和一个用户空间应用程序。 I tried two things : 我尝试了两件事:

  1. Manipulate the GPIO control registers directly from the kernel space using ioremap . 使用ioremap直接从内核空间处理GPIO控制寄存器。
  2. mmap() the GPIO control registers without caching and using them from user space. mmap() GPIO控制寄存器无需缓存并在用户空间中使用它们。

Both methods work, but the second is about 3 times slower than the first (observed on oscilloscope). 两种方法都有效,但第二种方法比第一种方法慢3倍(在示波器上观察)。 I think I disabled all caching mechanisms. 我想我禁用了所有缓存机制。

Of course I'd like to get the best of the two worlds : flexibility and ease of development from user space with the speed of kernel space. 当然,我想要充分利用这两个领域:从内核空间的速度来看,用户空间的灵活性和易开发性。

Does anybody know why the mmap() could be slower than the ioremap() ? 有人知道为什么mmap()可能比ioremap()慢吗?

Here's my code : 这是我的代码:

Kernel module code 内核模块代码

static int ti81xx_usmap_mmap(struct file* pFile, struct vm_area_struct* pVma)
{
  pVma->vm_flags |= VM_RESERVED;
  pVma->vm_page_prot = pgprot_noncached(pVma->vm_page_prot);

  if (io_remap_pfn_range(pVma, pVma->vm_start, pVma->vm_pgoff,
                          pVma->vm_end - pVma->vm_start, pVma->vm_page_prot))
     return -EAGAIN;

  pVma->vm_ops = &ti81xx_usmap_vm_ops;
  return 0;
}

static void ti81xx_usmap_test_gpio(void)
{
  u32* pGpIoRegisters = ioremap_nocache(TI81XX_GPIO0_BASE, 0x400);
  const u32 pin = 1 << 24;
  int i;

  /* I should use IO read/write functions instead of pointer deferencing, 
   * but portability isn't the issue here */

  pGpIoRegisters[OMAP4_GPIO_OE >> 2] &= ~pin;    /* Set pin as output*/

  for (i = 0; i < 200000000; ++i)
  {
     pGpIoRegisters[OMAP4_GPIO_SETDATAOUT >> 2] = pin;
     pGpIoRegisters[OMAP4_GPIO_CLEARDATAOUT >> 2] = pin;
  }

  pGpIoRegisters[OMAP4_GPIO_OE >> 2] |= pin;    /* Set pin as input*/

  iounmap(pGpIoRegisters);
}

User space application code 用户空间应用代码

int main(int argc, char** argv)
{
   int file, i;
   ulong* pGpIoRegisters = NULL;
   ulong pin = 1 << 24;

   file = open("/dev/ti81xx-usmap", O_RDWR | O_SYNC);

   if (file < 0)
   {
      printf("open failed (%d)\n", errno);
      return 1;
   }


   printf("Toggle from kernel space...");
   fflush(stdout);

   ioctl(file, TI81XX_USMAP_IOCTL_TEST_GPIO);

   printf(" done\n");    

   pGpIoRegisters = mmap(NULL, 0x400, PROT_READ | PROT_WRITE, MAP_SHARED, file, TI81XX_GPIO0_BASE);
   printf("Toggle from user space...");
   fflush(stdout);

   pGpIoRegisters[OMAP4_GPIO_OE >> 2] &= ~pin;

   for (i = 0; i < 30000000; ++i)
   {
      pGpIoRegisters[OMAP4_GPIO_SETDATAOUT >> 2] = pin;
      pGpIoRegisters[OMAP4_GPIO_CLEARDATAOUT >> 2] = pin;
   }

   pGpIoRegisters[OMAP4_GPIO_OE >> 2] |= pin;

   printf(" done\n");
   fflush(stdout);
   munmap(pGpIoRegisters, 0x400);    

   close(file);    
   return 0;
}

This is because ioremap_nocache() still enables the CPU write buffer in your VM mapping whereas pgprot_noncached() disables both bufferability and cacheability. 这是因为ioremap_nocache()仍然在VM映射中启用CPU写入缓冲区,而pgprot_noncached()禁用了可缓冲性和可缓存性。

Apples to apples comparison would be to use ioremap_strongly_ordered() instead. 苹果与苹果的比较将是使用ioremap_strongly_ordered()代替。

My guess would be that since mmap has to check to make sure you're writing to memory you're allowed to write to, it's going to be slower than the kernel version (which I believe/assume doesn't do that kind of checking--with a kernel module you're responsible for testing until you're very sure you're not breaking things). 我的猜测是,因为mmap必须检查以确保你写入你可以写入的内存,它会比内核版本慢(我相信/假设没有做那种检查 - 使用内核模块,你负责测试,直到你确定你没有破坏东西为止。

Try using do_mmap (I believe that's the one) to use mmap from kernel space, and see how that compares. 尝试使用do_mmap (我相信就是那个)从内核空间使用mmap ,看看它是如何比较的。 If it's comparably faster, then I'm right. 如果速度相对较快,那我就是对的。 If it's not, it's something else. 如果不是,那就是别的了。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM