乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      Linux內核開發(fā)之內存與I/O訪問(四)

       看風景D人 2014-07-19

      時間:晚上7點

      地點:寢室中..

      “小王,今天就不多話了,接著昨天沒講完的,不然連不起來了,都..”我催促著。

        上節(jié)講到kmalloc()申請的內存若要被映射到用戶空間可以通過mem_map_reserve()設置為保留后進行。具體怎么操作呢,給你一個模版吧:

      // 內核模塊加載函數
      int __init kmalloc_map_init(void)
      {
          ../申請設備號,添加cedv結構體
        buffer = kmalloc(BUF_SIZE, GFP_KERNEL); //申請buffer
        for(page = virt_to_page(buffer); page< virt_to_page(buffer+BUF_SIZE); page++)
        {
           mem_map_reserve(page);  //置業(yè)為保留
        }
      }
      //mmap()函數
      static int kmalloc_map_mmap(struct file *filp, struct vm_area_struct *vma)
      {
          unsigned long page, pos;
          unsigned long start = (unsigned long)vma->start;
          unsigned long size = (unsigned long)(vma->end - vma->start);
          printk(KERN_INFO, "mmaptest_mmap called\n");
          if(size > BUF_SIZE)  //用戶要映射的區(qū)域太大
              return - EINVAL;
          pos = (unsigned long)buffer;
          while(size > 0)   //映射buffer中的所有頁
          {
              page = virt_to_phys((void *)pos);
              if(remap_page_range(start, page, PAGE_SIZE, PAGE_SHARRED))
                  return -EAGAIN;
              start += PAGE_SIZE;
              pos +=PAGE_SIZE;
              size -= PAGE_SIZE;
          }
          return 0;
      }

      另外通常,IO內存被映射時需要是nocache的,這個時候應該對vma->vm_page_prot設置nocache標志。如下:


      static int xxx_nocache_mmap(struct file *filp, struct vm_area_struct *vma)
      {
        vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);   //賦nocache標志
        vma->vm_pgoff = ((u32)map_start >> PAGE_SHIFT);
        if(rempa_pfn_range(vma, vma->vm_start, vma->vm_pgoff, vma->vm_end - vm_start, vma->vm_page_prot));
           return - EAGGIN;
        return 0;
      }

      這段代碼中的pgprot_noncached()是一個宏,它實際上禁止了相關頁的cache和寫緩沖(write buffer),另外一個稍微少的一些限制的宏是:


      #define pgprot_writecombine(prot)  __pgprot(pgprot_val (prot) & –L_PTE_CACHEABLE);    它則沒有禁止寫緩沖


      而除了rempa_pfn_range()外,在驅動程序中實現(xiàn)VMA的nopage()函數通常可以為設備提供更加靈活的內存映射途徑。當發(fā)生缺頁時,nopage()會被內核自動調用,。這是因為,當發(fā)生缺頁異常時,系統(tǒng)會經過如下處理過程:


      1)找到缺頁的虛擬地址所在的VMA             2)如果必要,分配中間頁目錄表和頁表              


      3)如果頁表項對應的物理頁表不存在,則調用這個VMA的nopage()方法,它返回物理頁面的頁描述符。


      4)將物理頁面的地址填充到頁表中。


      實現(xiàn)nopage后,用戶空間可以通過mremap()系統(tǒng)調用重新綁定映射區(qū)所綁定的地址,下面給出一個在設備驅動中使用nopage()的典型范例:


      static int xxx_mmap(struct file *filp, struct vm_area_struct *vma);
      {
           unsigned long offset = vma->vm_pgoff << PAGE_OFFSET;
           if(offset >= _ _pa(high_memory) || (filp->flags &O_SYNC))
                   vma->vm_flags |=VM_IO;
           vma->vm_ops = &xxx_nopage_vm_ops;
           xxx_vma_open(vma);
           return 0;
      }
      struct page *xxx_vma_nopage(struct vm_area_struct *vma, unsigned long address, int *type)
      {
         struct page *pageptr;
         unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
         unsigned long physaddr = address - vma->vm_start + offset;   //物理內存
         unsigned long pageframe = physaddr >> PAGE_SHIFT;  //頁幀號
         if(!pfn_valid(pageframe))   //頁幀號有效
            return NOPAGE_SIGBUS;
         pageptr = pfn_to_page(pageframe);    //頁幀號->頁描述符
         get_page(pageptr);   //獲得頁,增加頁的使用計數
         if(type)
            *type = VM_FAULT_MINOR;
         return pageptr;    //返回頁描述符
      }

      上述函數對常規(guī)內存進行映射,返回一個頁描述符,可用于擴大或縮小映射的內存區(qū)域,由此可見,nopage()和remap_pfn_range()一個較大的區(qū)別在于remap_pfn


      _range()一般用于設備內存映射,而nopage()還可以用于RAM映射。


       


      小王,這節(jié)和前邊一節(jié)是在一起看的,我也可以喘口氣歇歇了,你慢慢看吧,就不煩你了,晚上吃飯叫上我哈..

        本站是提供個人知識管理的網絡存儲空間,所有內容均由用戶發(fā)布,不代表本站觀點。請注意甄別內容中的聯(lián)系方式、誘導購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權內容,請點擊一鍵舉報。
        轉藏 分享 獻花(0

        0條評論

        發(fā)表

        請遵守用戶 評論公約

        類似文章 更多