linux – mmap比ioremap慢

前端之家收集整理的这篇文章主要介绍了linux – mmap比ioremap慢前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我正在开发运行 Linux 2.6.37的ARM设备.我试图尽可能快地切换IO引脚.我做了一个小内核模块和用户空间应用程序.我尝试了两件事情:

>使用ioremap直接从内核空间处理GPIO控制寄存器.
> mmap()GPIO控制寄存器没有缓存,并从用户空间使用它们.

两种方法都可以工作,但第二种方法比第一种方法慢(比较示例)慢3倍.我觉得我禁用了所有的缓存机制.

当然,我想从两个世界中获得最好的效果:灵活性和用户空间的开发容易度与内核空间的速度.

有人知道为什么mmap()可能比ioremap()慢吗?

这是我的代码

内核模块代码

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);
}

用户空间应用程序代码

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;
}

解决方法

这是因为ioremap_nocache()仍然启用VM映射中的cpu写缓冲区,而pgprot_noncached()禁用缓冲性和可缓存性.

苹果对苹果的比较将是使用ioremap_strongly_ordered()而不是.

猜你在找的Linux相关文章