mmap比ioremap慢

时间:2012-06-07 09:18:31

标签: linux kernel mmap gpio

我正在开发运行Linux 2.6.37的ARM设备。我试图尽可能快地切换IO引脚。我制作了一个小内核模块和一个用户空间应用程序。我尝试了两件事:

  1. 使用ioremap直接从内核空间处理GPIO控制寄存器。
  2. mmap() GPIO控制寄存器无需缓存并在用户空间中使用它们。
  3. 两种方法都有效,但第二种方法比第一种方法慢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;
    }
    

2 个答案:

答案 0 :(得分:7)

这是因为ioremap_nocache()仍然在VM映射中启用CPU写缓冲区,而pgprot_noncached()则禁用了可缓冲性和可缓存性。

苹果与苹果的比较将改为使用ioremap_strongly_ordered()。

答案 1 :(得分:3)

我的猜测是,因为mmap必须检查以确保你写入你可以写入的内存,它会比内核版本慢(我认为/假设没有做那种检查 - 使用内核模块,你负责测试,直到你确定你没有破坏它为止。

尝试使用do_mmap(我相信是那个)从内核空间使用mmap,看看它是如何比较的。如果速度相对较快,那我就是对的。如果不是,那就是别的了。