在内核空间运行的模块,在分配了系统资源后,必须在不再使用前,进行释放,向内核返回所分配的资源。同时,很多模块在实际使用前,必须向内核注册自己,同样,在生命期结束时,必须向内核注销自己。
分配与释放,注册与注销。在内核模块中,经常是成对出现的。在我们前文描述的8139too网卡驱动初始化程序中,就存在很多这样的操作。下面我们一一列出,并作简单分析:
pci_register_driver与pci_unregister_driver
它们是分别在PCI设备驱动模块的初始化函数和清除函数中被调用的函数,都以一个struct pci_driver结构体作为参数。下面是这个结构的定义:
struct
pci_driver
...
{
struct list_head node;
char *name;
struct module *owner;
const struct pci_device_id *id_table;
int (*probe)(struct pci_dev *dev, const struct pci_device_id *id);
void (*remove)(struct pci_dev *dev);
int (*suspend)(struct pci_dev *dev, pm_message_t state);
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
int (*resume)(struct pci_dev *dev); /**//* Device woken up */
int (*enable_wake)(struct pci_dev *dev,pci_power_t state,int enable);
void (*shutdown) (struct pci_dev *dev);
struct device_driver driver;
struct pci_dynids dynids;
}
;
它有一个成员struct device_driver,是一个更为一般化的设备驱动对象,在pci_register_driver函数中,会把pci_driver的很多成员赋给该结构中的相应成员。同时,建立动态PCI的id表(为热插拔设备用)。最后,向总线注册该设备。而在pci_unregister_driver中做的事情就是从总线中注销该设备,同时释放动态的PCI id表。
alloc_etherdev和free_netdev
前文已经描述过,alloc_etherdev是alloc_netdev的封装函数。它们都以struct net_device结构体作为参数,alloc_netdev所做事情就是在内核空间为该结构体kmalloc内存,最后调用它的初始化函数。而 free_netdev则主要是kfree内存。
pci_enable_device和pci_disable_device
在一个pci设备可以被使用之前,必须调用pci_enable_device进行激活,该函数会调用底层代码激活PCI设备上的I/O和内存,使之可用。而pci_disable_device所做的事情刚好相反,告诉系统该PCI设备不再使用,
同时,禁用相关的一些资源。
pci_request_regions和pci_release_regions
这两个函数背后,实际调用的是request_region和release_region,或者request_mem_region和 release_mem_region进行I/O端口的分配与释放,或者I/O内存的分配与释放。
还有关于pci_iomap与pci_iounmap,前文已有介绍
分配与释放,注册与注销。在内核模块中,经常是成对出现的。在我们前文描述的8139too网卡驱动初始化程序中,就存在很多这样的操作。下面我们一一列出,并作简单分析:
pci_register_driver与pci_unregister_driver
它们是分别在PCI设备驱动模块的初始化函数和清除函数中被调用的函数,都以一个struct pci_driver结构体作为参数。下面是这个结构的定义:
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/1327ab569c1ae82736693a50b8e33378.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/7ff8d92cded7e0ce15e7ca1acc870052.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/0196c3df5ea9e936f21e9932cca91014.gif)
它有一个成员struct device_driver,是一个更为一般化的设备驱动对象,在pci_register_driver函数中,会把pci_driver的很多成员赋给该结构中的相应成员。同时,建立动态PCI的id表(为热插拔设备用)。最后,向总线注册该设备。而在pci_unregister_driver中做的事情就是从总线中注销该设备,同时释放动态的PCI id表。
alloc_etherdev和free_netdev
前文已经描述过,alloc_etherdev是alloc_netdev的封装函数。它们都以struct net_device结构体作为参数,alloc_netdev所做事情就是在内核空间为该结构体kmalloc内存,最后调用它的初始化函数。而 free_netdev则主要是kfree内存。
pci_enable_device和pci_disable_device
在一个pci设备可以被使用之前,必须调用pci_enable_device进行激活,该函数会调用底层代码激活PCI设备上的I/O和内存,使之可用。而pci_disable_device所做的事情刚好相反,告诉系统该PCI设备不再使用,
同时,禁用相关的一些资源。
pci_request_regions和pci_release_regions
这两个函数背后,实际调用的是request_region和release_region,或者request_mem_region和 release_mem_region进行I/O端口的分配与释放,或者I/O内存的分配与释放。
还有关于pci_iomap与pci_iounmap,前文已有介绍