1. 程式人生 > >linux系統虛擬地址 實體地址 匯流排地址

linux系統虛擬地址 實體地址 匯流排地址

在linux核心書籍中,介紹記憶體管理的部分,頻繁出現三個概念,實體地址、虛擬地址、匯流排地址

他們區別如下:

實體地址:MMU看到的記憶體的地址

虛擬地址:cpu,程式設計師操作的地址

匯流排地址:裝置看到的地址


struct pci_device_id結構體用於定義該驅動程式支援的不同型別的pci裝置列表

PCI_DEVICE(vendor, device)建立一個僅和vid did相匹配的struct pci_device_id,這個巨集把struct pci_device_id的subvendor和subdevice欄位設定為PCI_ANY_ID

MODULE_DEVICE_TABLE(pci,pci_ids)該語句建立一個名為_mod_pci_device_table的區域性變數,指向struct pci_device_id陣列,在depmod中會告知作業系統該驅動模組支援的所有pci裝置,當核心告知熱插播系統一個新的pci裝置被發現時,熱插拔系統會使用modules.pcimap檔案尋找恰當的驅動程式

struct pci_driver結構體代表了一個pci裝置的驅動程式

在硬體加電初始化時,BIOS韌體同統一檢查了所有的PCI裝置, 並統一為他們分配了一個和其他互不衝突的地址,讓他們的驅動程式可以向這些地址對映他們的暫存器,這些地址被BIOS寫進了各個裝置的配置空間,因為這個 活動是一個PCI的標準的活動,所以自然寫到各個裝置的配置空間裡而不是他們風格各異的控制暫存器空間裡。當然只有BIOS可以訪問配置空間。當作業系統 初始化時,他為每個PCI裝置分配了pci_dev結構,並且把BIOS獲得的並寫到了配置空間中的地址讀出來寫到了pci_dev中的resource 欄位中。這樣以後我們在讀這些地址就不需要在訪問配置空間了,直接跟pci_dev要就可以了,我們這裡的四個函式就是直接從pci_dev讀出了相關數 據,程式碼在include/linux/pci.h中。定義如下:



#define pci_resource_start(dev,bar) ((dev)->resource[(bar)].start)
#define pci_resource_end(dev,bar) ((dev)->resource[(bar)].end)

這裡需要說明一下,每個PCI裝置有0-5一共6個地址空間,我們通常只使用前兩個,這裡我們把引數1傳給了bar就是使用記憶體對映的地址空間。

void * __ioremap(unsigned long phys_addr, unsigned long size, unsigned long flags)

phys_addr:要對映的起始的IO地址; 
size:要對映的空間的大小; 
flags:要對映的IO空間的和許可權有關的標誌; 

功能: 將一個IO地址空間對映到核心的虛擬地址空間上去,便於訪問;

核心會為每一個物理頁幀建立一個struct page結構體,頁幀大小一般會4096位元組,可以自定義大小

struct page* virt_to_page(void *kaddr):負責將核心邏輯地址轉換成相應的page結構指標

struct page*pfn_to_page(int pfn):針對給定的頁幀號返回page結構體指標

void *page_address(struct page *page):如果地址存在,則返回頁的核心虛擬地址

int remap_pfn_range(structvm_area_struct *vma, unsigned long virt_add, unsigned long pfn, unsigned long size, pgport_t port):對映實體地址中從pfn表示的頁號開始的size個位元組到虛擬地址virt_add上

alloc_chrdev_region(dev_t *dev, unsigned int firstminor, unsigned int count, char *name)動態獲取裝置編號,主裝置號標識裝置對應的驅動程式,次裝置號由核心使用,用於正確確定裝置檔案所指的裝置。

int MAJOR(dev_t dev)從dev中獲取主裝置號

dev_t MKDEV(unsigned int major, unsigned int minor)這個巨集根據主次裝置號構造一個dev_t的結構體

class_create()
-------------------------------------------------
linux-2.6.22/include/linux/device.h
struct class *class_create(struct module *owner, const char *name)
    class_create - create a struct class structure
    @owner: pointer to the module that is to "own" this struct class
    @name: pointer to a string for the name of this class.

在/sys/class/下建立類目錄

class_device_create()
-------------------------------------------------
linux-2.6.22/include/linux/device.h
struct class_device *class_device_create(struct class        *cls,
                                         struct class_device *parent,
                                         dev_t               devt,
                                         struct device       *device,
                                         const char          *fmt, ...)

    class_device_create - creates a class device and registers it with sysfs
    @cls: pointer to the struct class that this device should be registered to.
    @parent: pointer to the parent struct class_device of this new device, if any.
    @devt: the dev_t for the char device to be added.
    @device: a pointer to a struct device that is assiociated with this class device.
    @fmt: string for the class device's name
在驅動模組初始化函式中實現裝置節點的自動建立 函式定義:      函式位置: src/drivers/base/core.c      函式格式:
  1. extern struct device *device_create(struct class *cls, struct device *parent,dev_t devt, void *drvdataconst char *fmt, ...)
函式功能:     函式device_create()用於動態的建立邏輯裝置,並對新的邏輯裝置類進行相應初始化,將其與函式的第一個引數所代表的邏輯類關聯起來,然後將此邏輯裝置加到linux核心系統的裝置驅動程式模型中。函式能夠自動在/sys/devices/virtual目錄下建立新的邏輯裝置目錄,在/dev目錄下創建於邏輯類對應的裝置檔案


int cdev_add(struct cdev *dev, dev_t num, unsigned int count) 把dev代表的裝置新增到系統核心中