×ðÁú¿­Ê±

LinuxÇý¶¯IOƪ¡ª¡ªmmap²Ù×÷

Ç°ÑÔ

ƽʱÎÒÃÇдLinuxÇý¶¯ºÍÓû§¿Õ¼ä½»»¥Ê±£¬¶¼ÊÇͨ¹ýcopy_from_user°ÑÓû§¿Õ¼ä´«¹ýÀ´µÄÊý¾Ý¾ÙÐп½±´£¬ÎªÊ²Ã´ÒªÕâô×öÄØ £¿

ÓÉÓÚÓû§¿Õ¼äÊDz»¿ÉÖ±½ÓÄں˿ռäÊý¾ÝµÄ£¬ËûÃÇÓ³ÉäµÄÊDzî±ðµÄµØµã¿Õ¼ä£¬Ö»ÄÜÏȽ«Êý¾Ý¿½±´¹ýÀ´£¬È»ºóÔÙ²Ù×÷¡£

ÈôÊÇÓû§¿Õ¼äÐèÒª´«¼¸MBµÄÊý¾Ý¸øÄںˣ¬ÄÇôԭÀ´µÄ¿½±´·½·¨ÏÔȻЧÂÊÌØÊâµÍ£¬Ò²²»Ì«ÏÖʵ£¬ÄÇÔõô°ìÄØ £¿

ÏëÏ룬֮ÒÔÊÇÒª¿½±´ÊÇÓÉÓÚÓû§¿Õ¼ä²»¿ÉÖ±½Ó»á¼ûÄں˿ռ䣬ÄÇÈôÊÇ¿ÉÒÔÖ±½Ó»á¼ûÄں˿ռäµÄbuffer£¬ÊDz»ÊǾͽâ¾öÁË¡£

¼òÆÓÀ´Ëµ£¬¾ÍÊÇÈÃÒ»¿éÎïÀíÄÚ´æÓµÓÐÁ½·ÝÓ³É䣬¼´ÓµÓÐÁ½¸öÐéÄâµØµã£¬Ò»¸öÔÚÄں˿ռ䣬һ¸öÔÚÓû§¿Õ¼ä¡£¹ØϵÈçÏ£º

ͨ¹ýmmapÓ³Éä¾Í¿ÉÒÔʵÏÖ¡£

Ó¦Óòã

Ó¦Óòã´úÂëºÜ¼òÆÓ£¬Ö÷Òª¾ÍÊÇͨ¹ýmmapϵͳŲÓþÙÐÐÓ³É䣬Ȼºó¾Í¿ÉÒÔ¶Ô·µ»ØµÄµØµã¾ÙÐвÙ×÷¡£

char * buf;
/* 1. ·­¿ªÎļþ */
 fd = open("/dev/hello", O_RDWR);
 if (fd == -1)
 {
      printf("can not open file /dev/hello\n");
      return -1;
 }

/* 2. mmap
       * MAP_SHARED  : ¶à¸öAPP¶¼Å²ÓÃmmapÓ³Éäͳһ¿éÄÚ´æʱ, ¶ÔÄÚ´æµÄÐ޸ĸ÷È˶¼¿ÉÒÔ¿´µ½¡£
       *               ¾ÍÊÇ˵¶à¸öAPP¡¢Çý¶¯³ÌÐòÏÖʵÉÏ»á¼ûµÄ¶¼ÊÇͳһ¿éÄÚ´æ
       * MAP_PRIVATE : ½¨ÉèÒ»¸öcopy on writeµÄ˽ÓÐÓ³Éä¡£
       *               µ±APP¶Ô¸ÃÄÚ´æ¾ÙÐÐÐÞ¸Äʱ£¬ÆäËû³ÌÐòÊÇ¿´²»µ½ÕâЩÐ޸ĵÄ¡£
       *               ¾ÍÊǵ±APPдÄÚ´æʱ, Äں˻áÏȽ¨ÉèÒ»¸ö¿½±´¸øÕâ¸öAPP,
       *               Õâ¸ö¿½±´ÊÇÕâ¸öAPP˽ÓеÄ, ÆäËûAPP¡¢Çý¶¯ÎÞ·¨»á¼û¡£
       */
buf =  mmap(NULL, 1024*8, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);

µÇ¼ºó¸´ÖÆ

mmapµÄµÚÒ»¸ö²ÎÊýÊÇÏëÒªÓ³ÉäµÄÆðʼµØµã£¬Í¨³£ÉèÖÃΪNULL£¬ÌåÏÖÓÉÄÚºËÀ´¾öÒé¸ÃÆðʼµØµã¡£

µÚ¶þ²ÎÊýÊÇÒªÓ³ÉäµÄÄÚ´æ¿Õ¼äµÄ¾Þϸ¡£

µÚÈý¸ö²ÎÊýPROT_READ | PROT_WRITEÌåÏÖÓ³ÉäºóµÄ¿Õ¼äÊǿɶÁ¿ÉдµÄ¡£

µÚËĸö²ÎÊý¿ÉÌîMAP_SHARED»òMAP_PRIVATE£º

MAP_SHARED£º¶à¸öAPP¶¼Å²ÓÃmmapÓ³Éäͳһ¿éÄÚ´æʱ, ¶ÔÄÚ´æµÄÐ޸ĸ÷È˶¼¿ÉÒÔ¿´µ½¡£¾ÍÊÇ˵¶à¸öAPP¡¢Çý¶¯³ÌÐòÏÖʵÉÏ »á¼ûµÄ¶¼ÊÇͳһ¿éÄÚ´æ¡£

MAP_PRIVATE£º½¨ÉèÒ»¸öcopy on writeµÄ˽ÓÐÓ³Éä¡£µ±APP¶Ô¸ÃÄÚ´æ¾ÙÐÐÐÞ¸Äʱ£¬ÆäËû³ÌÐòÊÇ¿´²»µ½ÕâЩÐ޸ĵÄ¡£¾ÍÊǵ±APP дÄÚ´æʱ, Äں˻áÏȽ¨ÉèÒ»¸ö¿½±´¸øÕâ¸öAPP£¬Õâ¸ö¿½±´ÊÇÕâ¸öAPP˽ÓеÄ, ÆäËûAPP¡¢Çý¶¯ÎÞ·¨»á¼û¡£

Çý¶¯²ã

Çý¶¯²ãÖ÷ÒªÊÇʵÏÖmmap½Ó¿Ú£¬¶ømmap½Ó¿ÚµÄʵÏÖ£¬Ö÷ÒªÊÇŲÓÃÁËremap_pfn_rangeº¯Êý£¬º¯ÊýÔ­ÐÍÈçÏ£º

int remap_pfn_range(
  struct vm_area_struct *vma, 
  unsigned long addr, 
  unsigned long pfn, 
  unsigned long size, 
  pgprot_t prot);

µÇ¼ºó¸´ÖÆ

vma£ºÐÎòһƬӳÉäÇøÓòµÄ½á¹¹ÌåÖ¸Õë

addr£ºÒªÓ³ÉäµÄÐéÄâµØµãÆðʼµØµã

pfn£ºÎïÀíÄÚ´æËù¶ÔÓ¦µÄÒ³¿òºÅ£¬¾ÍÊǽ«ÎïÀíµØµã³ýÒÔÒ³¾Þϸ»ñµÃµÄÖµ

size£ºÓ³ÉäµÄ¾Þϸ

prot£º¸ÃÄÚ´æÇøÓòµÄ»á¼ûȨÏÞ

Çý¶¯Ö÷Òª°ì·¨£º

1¡¢Ê¹ÓÃkmalloc»òÕßkzallocº¯Êý·ÖÅÉÒ»¿éÄÚ´ækernel_buf£¬ÓÉÓÚÕâÑù·ÖÅɵÄÄÚ´æÎïÀíµØµãÊÇÒ»Á¬µÄ£¬mmapºóÓ¦Óòã»á¶ÔÕâÒ»¸ö»ùµØµãÈ¥»á¼ûÕâ¿éÄÚ´æ¡£

2¡¢ÊµÏÖmmapº¯Êý

static int hello_drv_mmap(struct file *file, struct vm_area_struct *vma)
{
 /* »ñµÃÎïÀíµØµã */
 unsigned long phy = virt_to_phys(kernel_buf);//kernel_bufÊÇÄں˿ռä·ÖÅɵÄÒ»¿éÐéÄâµØµã¿Õ¼ä
    
    /* ÉèÖÃÊôÐÔ£ºcache, buffer*/
 vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
    
    /* map */
    if(remap_pfn_range(vma, vma->vm_start, phy>>PAGE_SHFIT,
                      vma->vm_end - vma->start, vma->vm_page_prot)){
 printk("mmap remap_pfn_range failed\n");
    return -ENOBUFS;
 }
 return 0;
}

static struct file_operations my_fops = {
 .mmap = hello_drv_mmap,
};

µÇ¼ºó¸´ÖÆ

1¡¢Í¨¹ývirt_to_phys½«ÐéÄâµØµãתΪÎïÀíµØµã£¬ÕâÀïµÄkernel_bufÊÇÄں˿ռäµÄÒ»¿éÐéÄâµØµã¿Õ¼ä

2¡¢ÉèÖÃÊôÐÔ£º²»Ê¹ÓÃcache£¬Ê¹ÓÃbuffer

3¡¢Ó³É䣺ͨ¹ýremap_pfn_rangeº¯ÊýÓ³É䣬phy>>PAGE_SHIFT×Åʵ¾ÍÊÇ°´pageÓ³É䣬³ýÁËÕâ¸ö²ÎÊý£¬ÆäËûµÄÆðʼµØµã¡¢¾ÞϸºÍȨÏÞ¶¼¿ÉÒÔÓÉÓû§ÔÚϵͳŲÓú¯ÊýÖÐÖ¸¶¨¡£

µ±Ó¦ÓòãŲÓÃmmapºó£¬¾Í»áŲÓõ½Çý¶¯²ãµÄmmapº¯Êý£¬×îÖÕÓ¦ÓòãµÄÐéÄâµØµãºÍÇý¶¯ÖеÄÎïÀíµØµã¾Í½¨ÉèÁËÓ³Éä¹Øϵ£¬Ó¦ÓòãÒ²¾Í¿ÉÒÔÖ±½Ó»á¼ûÇý¶¯µÄbufferÁË¡£

ÒÔÉϾÍÊÇLinuxÇý¶¯IOƪ¡ª¡ªmmap²Ù×÷µÄÏêϸÄÚÈÝ£¬¸ü¶àÇë¹Ø×¢±¾ÍøÄÚÆäËüÏà¹ØÎÄÕ£¡

ÃâÔð˵Ã÷£ºÒÔÉÏչʾÄÚÈÝȪԴÓÚÏàÖúýÌå¡¢ÆóÒµ»ú¹¹¡¢ÍøÓÑÌṩ»òÍøÂçÍøÂçÕûÀí£¬°æȨÕùÒéÓë±¾Õ¾Î޹أ¬ÎÄÕÂÉæ¼°¿´·¨Óë¿´·¨²»´ú±í×ðÁú¿­Ê±ÂËÓÍ»úÍø¹Ù·½Ì¬¶È£¬Çë¶ÁÕß½ö×ö²Î¿¼¡£±¾ÎĽӴýתÔØ£¬×ªÔØÇë˵Ã÷À´ÓÉ¡£ÈôÄúÒÔΪ±¾ÎÄÇÖÕ¼ÁËÄúµÄ°æȨÐÅÏ¢£¬»òÄú·¢Ã÷¸ÃÄÚÈÝÓÐÈκÎÉæ¼°ÓÐÎ¥¹«µÂ¡¢Ã°·¸Ö´·¨µÈÎ¥·¨ÐÅÏ¢£¬ÇëÄúÁ¬Ã¦ÁªÏµ×ðÁú¿­Ê±ÊµÊ±ÐÞÕý»òɾ³ý¡£

Ïà¹ØÐÂÎÅ

ÁªÏµ×ðÁú¿­Ê±

18523999891

¿É΢ÐÅÔÚÏß×Éѯ

ÊÂÇéʱ¼ä£ºÖÜÒ»ÖÁÖÜÎ壬9:30-18:30£¬½ÚãåÈÕÐÝÏ¢

QR code
¡¾ÍøÕ¾µØͼ¡¿¡¾sitemap¡¿