<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??一站式輕松地調用各大LLM模型接口,支持GPT4、智譜、豆包、星火、月之暗面及文生圖、文生視頻 廣告
                ## 15.5.?快速參考 本章介紹了下列關于內存處理的符號: ### 15.5.1.?介紹性材料 ~~~ #include <linux/mm.h> #include <asm/page.h> ~~~ 和內存管理相關的大部分函數和結構, 原型和定義在這些頭文件. ~~~ void *__va(unsigned long physaddr); unsigned long __pa(void *kaddr); ~~~ 在內核邏輯地址和物理地址之間轉換的宏定義. ~~~ PAGE_SIZE PAGE_SHIFT ~~~ 常量, 給出底層硬件的頁的大小(字節)和一個頁面號必須被移位來轉變為一個物理地址的位數. struct page 在系統內存映射中表示一個硬件頁的結構. ~~~ struct page *virt_to_page(void *kaddr); void *page_address(struct page *page); struct page *pfn_to_page(int pfn); ~~~ 宏定義, 在內核邏輯地址和它們相關的內存映射入口之間轉換的. page_address 只用在低地址頁或者已被明確映射的高地址頁. pfn_to_page 轉換一個頁面號到它的相關的 struct page 指針. ~~~ unsigned long kmap(struct page *page); void kunmap(struct page *page); ~~~ kmap 返回一個內核虛擬地址, 被映射到給定頁, 如果需要并創建映射. kunmap 為給定頁刪除映射. ~~~ #include <linux/highmem.h> #include <asm/kmap_types.h> void *kmap_atomic(struct page *page, enum km_type type); void kunmap_atomic(void *addr, enum km_type type); ~~~ kmap 的高性能版本; 結果的映射只能被原子代碼持有. 對于驅動, type 應當是 KM_USER1, KM_USER1, KM_IRQ0, 或者 KM_IRQ1. struct vm_area_struct; 描述一個 VMA 的結構. ### 15.5.2.?實現 mmap ~~~ int remap_pfn_range(struct vm_area_struct *vma, unsigned long virt_add, unsigned long pfn, unsigned long size, pgprot_t prot); int io_remap_page_range(struct vm_area_struct *vma, unsigned long virt_add, unsigned long phys_add, unsigned long size, pgprot_t prot); ~~~ 位于 mmap 核心的函數. 它們映射 size 字節的物理地址, 從 pfn 指出的頁號開始到虛擬地址 virt_add. 和虛擬空間相關聯的保護位在 prot 里指定. io_remap_page_range 應當在目標地址在 I/O 內存空間里時被使用. ~~~ struct page *vmalloc_to_page(void *vmaddr); ~~~ 轉換一個由 vmalloc 獲得的內核虛擬地址到它的對應的 struct page 指針. ### 15.5.3.?實現直接 I/O ~~~ int get_user_pages(struct task_struct *tsk, struct mm_struct *mm, unsigned long start, int len, int write, int force, struct page **pages, struct vm_area_struct **vmas); ~~~ 函數, 加鎖一個用戶空間緩沖到內存并且返回對應的 struct page 指針. 調用者必須持有 mm->mmap_sem. ~~~ SetPageDirty(struct page *page); ~~~ 宏定義, 標識給定的頁為"臟"(被修改)并且需要寫到它的后備存儲, 在它被釋放前. ~~~ void page_cache_release(struct page *page); ~~~ 釋放給定的頁從頁緩存中. ~~~ int is_sync_kiocb(struct kiocb *iocb); ~~~ 宏定義, 返回非零如果給定的 IOCB 需要同步執行. ~~~ int aio_complete(struct kiocb *iocb, long res, long res2); ~~~ 函數, 指示一個異步 I/O 操作完成. ### 15.5.4.?直接內存存取 ~~~ #include <asm/io.h> unsigned long virt_to_bus(volatile void * address); void * bus_to_virt(unsigned long address); ~~~ 過時的不好的函數, 在內核, 虛擬, 和總線地址之間轉換. 總線地址必須用來和外設通訊. ~~~ #include <linux/dma-mapping.h> ~~~ 需要來定義通用 DMA 函數的頭文件. ~~~ int dma_set_mask(struct device *dev, u64 mask); ~~~ 對于無法尋址整個 32-位范圍的外設, 這個函數通知內核可尋址的地址范圍并且如果可進行 DMA 返回非零. ~~~ void *dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *bus_addr, int flag); void dma_free_coherent(struct device *dev, size_t size, void *cpuaddr, dma_handle_t bus_addr); ~~~ 分配和釋放一致 DMA 映射, 對一個將持續在驅動的生命周期中的緩沖. ~~~ #include <linux/dmapool.h> struct dma_pool *dma_pool_create(const char *name, struct device *dev, size_t size, size_t align, size_t allocation); void dma_pool_destroy(struct dma_pool *pool);void *dma_pool_alloc(struct dma_pool *pool, int mem_flags, dma_addr_t *handle); void dma_pool_free(struct dma_pool *pool, void *vaddr, dma_addr_t handle); ~~~ 創建, 銷毀, 和使用 DMA 池來管理小 DMA 區的函數. ~~~ enum dma_data_direction; DMA_TO_DEVICE DMA_FROM_DEVICE DMA_BIDIRECTIONAL DMA_NONE ~~~ 符號, 用來告知流映射函數在什么方向數據移入或出緩沖. ~~~ dma_addr_t dma_map_single(struct device *dev, void *buffer, size_t size, enum dma_data_direction direction); void dma_unmap_single(struct device *dev, dma_addr_t bus_addr, size_t size, enum dma_data_direction direction); ~~~ 創建和銷毀一個單使用, 流 DMA 映射. ~~~ void dma_sync_single_for_cpu(struct device *dev, dma_handle_t bus_addr, size_t size, enum dma_data_direction direction); void dma_sync_single_for_device(struct device *dev, dma_handle_t bus_addr, size_t size, enum dma_data_direction direction); ~~~ 同步一個由一個流映射的緩沖. 必須使用這些函數, 如果處理器必須存取一個緩沖當使用流映射時.(即, 當設備擁有緩沖時). ~~~ #include <asm/scatterlist.h> struct scatterlist { /* ... */ }; dma_addr_t sg_dma_address(struct scatterlist *sg); unsigned int sg_dma_len(struct scatterlist *sg); ~~~ 這個散布表結構描述一個涉及不止一個緩沖的 I/O 操作. 宏 sg_dma_address he sg_dma_len 可用來抽取總線地址和緩沖長度來傳遞給設備, 當實現發散/匯聚操作時. ~~~ dma_map_sg(struct device *dev, struct scatterlist *list, int nents, enum dma_data_direction direction); dma_unmap_sg(struct device *dev, struct scatterlist *list, int nents, enum dma_data_direction direction); void dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, int nents, enum dma_data_direction direction); void dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, int nents, enum dma_data_direction direction); ~~~ dma_map_sg 映射一個 發散/匯聚 操作, 并且 dma_unmap_sg 恢復這些映射. 如果在這個映射被激活時緩沖必須被存取, dma_sync_sg_* 可用來同步. /proc/dma 包含在 DMA 控制器中的被分配的通道的文本快照的文件. 基于 PCI 的 DMA 不顯示, 因為每個板獨立工作, 不需要分配一個通道在 DMA 控制器中. ~~~ #include <asm/dma.h> ~~~ 定義或者原型化所有和 DMA 相關的函數和宏定義. 它必須被包含來使用任何下面符號. ~~~ int request_dma(unsigned int channel, const char *name); void free_dma(unsigned int channel); ~~~ 存取 DMA 注冊. 注冊必須在使用 ISA DMA 通道之前進行. ~~~ unsigned long claim_dma_lock( ); void release_dma_lock(unsigned long flags); ~~~ 獲取和釋放 DMA 自旋鎖, 它必須被持有, 在調用其他的在這個列表中描述的 ISA DMA 函數之前. 它們在本地處理器上也關閉和重新使能中斷 ~~~ void set_dma_mode(unsigned int channel, char mode); void set_dma_addr(unsigned int channel, unsigned int addr); void set_dma_count(unsigned int channel, unsigned int count); ~~~ 編程 DMA 信息在 DMA 控制器中. addr 是一個總線地址. ~~~ void disable_dma(unsigned int channel); void enable_dma(unsigned int channel); ~~~ 一個 DMA 通道必須被關閉在配置期間. 這些函數改變 DMA 通道的狀態. ~~~ int get_dma_residue(unsigned int channel); ~~~ 如果這驅動需要知道一個 DMA 傳送在進行, 它可調用這個函數, 返回尚未完成的數據傳輸的數目. 在成功的 DMA 完成后, 這個函數返回 0; 值是不可預測的當數據仍然在傳送時. ~~~ void clear_dma_ff(unsigned int channel); ~~~ DMA flip-flop 被控制器用來傳送 16-位值, 通過 2 個 8 位操作. 它必須被清除, 在發送任何數據給處理器之前.
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看