15.5. 快速參考

2018-02-24 15:50 更新

15.5.?快速參考

本章介紹了下列關(guān)于內(nèi)存處理的符號:

15.5.1.?介紹性材料

#include <linux/mm.h>
#include <asm/page.h>

和內(nèi)存管理相關(guān)的大部分函數(shù)和結(jié)構(gòu), 原型和定義在這些頭文件.

void *__va(unsigned long physaddr);
unsigned long __pa(void *kaddr);

在內(nèi)核邏輯地址和物理地址之間轉(zhuǎn)換的宏定義.

PAGE_SIZE
PAGE_SHIFT 

常量, 給出底層硬件的頁的大小(字節(jié))和一個(gè)頁面號必須被移位來轉(zhuǎn)變?yōu)橐粋€(gè)物理地址的位數(shù).

struct page
在系統(tǒng)內(nèi)存映射中表示一個(gè)硬件頁的結(jié)構(gòu).

struct page *virt_to_page(void *kaddr);
void *page_address(struct page *page);
struct page *pfn_to_page(int pfn);

宏定義, 在內(nèi)核邏輯地址和它們相關(guān)的內(nèi)存映射入口之間轉(zhuǎn)換的. page_address 只用在低地址頁或者已被明確映射的高地址頁. pfn_to_page 轉(zhuǎn)換一個(gè)頁面號到它的相關(guān)的 struct page 指針.

unsigned long kmap(struct page *page);
void kunmap(struct page *page);

kmap 返回一個(gè)內(nèi)核虛擬地址, 被映射到給定頁, 如果需要并創(chuàng)建映射. 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 的高性能版本; 結(jié)果的映射只能被原子代碼持有. 對于驅(qū)動, type 應(yīng)當(dāng)是 KM_USER1, KM_USER1, KM_IRQ0, 或者 KM_IRQ1.

struct vm_area_struct;
描述一個(gè) VMA 的結(jié)構(gòu).

15.5.2.?實(shí)現(xiàn) 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 核心的函數(shù). 它們映射 size 字節(jié)的物理地址, 從 pfn 指出的頁號開始到虛擬地址 virt_add. 和虛擬空間相關(guān)聯(lián)的保護(hù)位在 prot 里指定. io_remap_page_range 應(yīng)當(dāng)在目標(biāo)地址在 I/O 內(nèi)存空間里時(shí)被使用.

struct page *vmalloc_to_page(void *vmaddr);

轉(zhuǎn)換一個(gè)由 vmalloc 獲得的內(nèi)核虛擬地址到它的對應(yīng)的 struct page 指針.

15.5.3.?實(shí)現(xiàn)直接 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);

函數(shù), 加鎖一個(gè)用戶空間緩沖到內(nèi)存并且返回對應(yīng)的 struct page 指針. 調(diào)用者必須持有 mm->mmap_sem.

SetPageDirty(struct page *page);

宏定義, 標(biāo)識給定的頁為"臟"(被修改)并且需要寫到它的后備存儲, 在它被釋放前.

void page_cache_release(struct page *page);

釋放給定的頁從頁緩存中.

int is_sync_kiocb(struct kiocb *iocb);

宏定義, 返回非零如果給定的 IOCB 需要同步執(zhí)行.

int aio_complete(struct kiocb *iocb, long res, long res2);

函數(shù), 指示一個(gè)異步 I/O 操作完成.

15.5.4.?直接內(nèi)存存取

#include <asm/io.h>
unsigned long virt_to_bus(volatile void * address);
void * bus_to_virt(unsigned long address);

過時(shí)的不好的函數(shù), 在內(nèi)核, 虛擬, 和總線地址之間轉(zhuǎn)換. 總線地址必須用來和外設(shè)通訊.

#include <linux/dma-mapping.h>

需要來定義通用 DMA 函數(shù)的頭文件.

int dma_set_mask(struct device *dev, u64 mask);

對于無法尋址整個(gè) 32-位范圍的外設(shè), 這個(gè)函數(shù)通知內(nèi)核可尋址的地址范圍并且如果可進(jìn)行 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 映射, 對一個(gè)將持續(xù)在驅(qū)動的生命周期中的緩沖.

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

創(chuàng)建, 銷毀, 和使用 DMA 池來管理小 DMA 區(qū)的函數(shù).

enum dma_data_direction;
DMA_TO_DEVICE
DMA_FROM_DEVICE
DMA_BIDIRECTIONAL
DMA_NONE

符號, 用來告知流映射函數(shù)在什么方向數(shù)據(jù)移入或出緩沖.

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

創(chuàng)建和銷毀一個(gè)單使用, 流 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);

同步一個(gè)由一個(gè)流映射的緩沖. 必須使用這些函數(shù), 如果處理器必須存取一個(gè)緩沖當(dāng)使用流映射時(shí).(即, 當(dāng)設(shè)備擁有緩沖時(shí)).

#include <asm/scatterlist.h>
struct scatterlist { /* ... */ };
dma_addr_t sg_dma_address(struct scatterlist *sg);
unsigned int sg_dma_len(struct scatterlist *sg);

這個(gè)散布表結(jié)構(gòu)描述一個(gè)涉及不止一個(gè)緩沖的 I/O 操作. 宏 sg_dma_address he sg_dma_len 可用來抽取總線地址和緩沖長度來傳遞給設(shè)備, 當(dāng)實(shí)現(xiàn)發(fā)散/匯聚操作時(shí).

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 映射一個(gè) 發(fā)散/匯聚 操作, 并且 dma_unmap_sg 恢復(fù)這些映射. 如果在這個(gè)映射被激活時(shí)緩沖必須被存取, dma_syncsg* 可用來同步.

/proc/dma
包含在 DMA 控制器中的被分配的通道的文本快照的文件. 基于 PCI 的 DMA 不顯示, 因?yàn)槊總€(gè)板獨(dú)立工作, 不需要分配一個(gè)通道在 DMA 控制器中.

#include <asm/dma.h>

定義或者原型化所有和 DMA 相關(guān)的函數(shù)和宏定義. 它必須被包含來使用任何下面符號.

int request_dma(unsigned int channel, const char *name);
void free_dma(unsigned int channel);

存取 DMA 注冊. 注冊必須在使用 ISA DMA 通道之前進(jìn)行.

unsigned long claim_dma_lock( );
void release_dma_lock(unsigned long flags);

獲取和釋放 DMA 自旋鎖, 它必須被持有, 在調(diào)用其他的在這個(gè)列表中描述的 ISA DMA 函數(shù)之前. 它們在本地處理器上也關(guān)閉和重新使能中斷

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 是一個(gè)總線地址.

void disable_dma(unsigned int channel);
void enable_dma(unsigned int channel);

一個(gè) DMA 通道必須被關(guān)閉在配置期間. 這些函數(shù)改變 DMA 通道的狀態(tài).

int get_dma_residue(unsigned int channel);

如果這驅(qū)動需要知道一個(gè) DMA 傳送在進(jìn)行, 它可調(diào)用這個(gè)函數(shù), 返回尚未完成的數(shù)據(jù)傳輸?shù)臄?shù)目. 在成功的 DMA 完成后, 這個(gè)函數(shù)返回 0; 值是不可預(yù)測的當(dāng)數(shù)據(jù)仍然在傳送時(shí).

void clear_dma_ff(unsigned int channel);

DMA flip-flop 被控制器用來傳送 16-位值, 通過 2 個(gè) 8 位操作. 它必須被清除, 在發(fā)送任何數(shù)據(jù)給處理器之前.

以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號