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代表的设备添加到系统内核中

猜你喜欢

转载自blog.csdn.net/hobertony_7/article/details/81014933