收藏 分享(赏)

Linux内核 文档翻译汇总.doc

上传人:yjrm16270 文档编号:6800340 上传时间:2019-04-22 格式:DOC 页数:42 大小:175.50KB
下载 相关 举报
Linux内核 文档翻译汇总.doc_第1页
第1页 / 共42页
Linux内核 文档翻译汇总.doc_第2页
第2页 / 共42页
Linux内核 文档翻译汇总.doc_第3页
第3页 / 共42页
Linux内核 文档翻译汇总.doc_第4页
第4页 / 共42页
Linux内核 文档翻译汇总.doc_第5页
第5页 / 共42页
点击查看更多>>
资源描述

1、 我们的内核1Linux 内核文档翻译汇总-device model如果有任何疑问,请联系:Linux 内核文档翻译汇总-device model .1前言 1Overview2Binding.4Bus .6Class .9Device 13Devres 17Driver .23Interface27Platform30Porting34前言我们翻译的第一批文档已经翻译出来了,我将这些文档整理到一起,方便大家阅读,下面的工作更加艰巨,就是如何校订我们的文档,保证我们的文档的权威性(准确性) 。这不仅需要大家的努力,还需要我们制定良好的校订文档规则。下面是我制定的一些校订规则,如果有什么疑问欢迎

2、各位补充:文档校订规则:0. 对进入校订期的文档,请翻译者将文档的最新版本在 bbs 上发帖公示。在文档的点击率达到 100,或者文档翻译完成一周后,翻译者可以准备,申请答辩,答辩必须在群中交流,根据文档的大小确定答辩形式,在一致认为答辩通过后,标记为稳定版本。添加到发行版中。1. 答辩规则(一般情况,特殊情况另外说明)-1. 答辩者提前一周,在群中发表声明,说明自己的文章需要答辩,并告知负责人。-2. chenyongbiao 负责安排答辩时间,并发群邮件通知群成员,在群公告中发表公告。-3. 答辩开始,答辩者做简单陈述(所翻译的文章概要) 。-4. 答辩组成员阅读文章,提出疑问(包括错别字

3、,专用名词等) 。 我们的内核2-5. 答辩完成,答辩者综合考虑答辩组成员的意见,整理文档。-6. 将答辩完的文章公示,并注明已通过答辩,这阶段主要是让大家找文章中的错别字等。-7. 公示一周后,文章正式添加进发行版。2. 文档提交。如果有任何疑问,请快联系我:,下一步我们将执行校订方案。Overview翻 译者:宙翰 Linux 内核设备模型Patrick Mochel 起草于 2002 年 8 月 26 日于 2006 年 1 月 31 日更新概述Linux 内核设备模型是对所有以前在内核中以前使用过的不同驱动模型的一种统一.它设是通过把一组数据和操作统一到全局可访问的数据结构中来为桥接器

4、和设备增加总线专有驱动.传统的驱动模型给它所控制的设备实现了一系列的树形结构(有些仅仅是一个链表). 他们在不同类型的总线设备上区别很大.现在的驱动模型给描述一种总线和会出现在这个总线下的设备提供了一种公共的,统一的数据模型.这种统一的总线模型包括了一组所有总线都有的公共属性和一组公共的回掉函数,例如能在总线枚举,总线关闭和总线电源管理.通用设备和桥接器接口也体现了现代计算机的目标:也就是实现设备的即插即用,电源管理和热插拔功能.特别是由 Intel 和 Microsoft 提出的的模型(即 ACPI),它确保了几乎所有的设备能在和 X86 兼容的系统中大多数任意总线上使用 .当然并不是每一个

5、总线都能够支持所有这些操作,但几乎所有的总线支持大多数这样的操作.底层访问公共的数据项已经从单个总线中移到了公用数据结构中.当然总线层仍然可以访问这些域,有时也要可被设备专有驱动所访问 我们的内核3其它的总线层被用来做以前给 PCI 层所做的那些工作.pci_dev 结构如下:复制内容到剪贴板代码:struct pci_dev .struct device dev;首先要注意的是这个结构是静态分配的.也就是说在发现设备时只会分配一个.另外要注意的是 pci_dev 结构末尾的 device 结构。这是用来防止编程者混淆 device 和 pci_dev。PCI 总线层可以自如的访问结构 str

6、uct device 中的各成员 .要了解 pci_dev 这个数据结构,也应该知道 devibe 这个数据结构.已经被转换成当前驱动模型的单独的 PCI 设备驱动不要也不应该去动 device 结构中的成员 ,除非有强烈的令人信服的理由才去这么做.这种抽象是为了防止在过渡期间产生的不必要的麻烦.如果一个成员的名字变了或是被去除了,那所有底层的驱动将会不可用.另一方面来说,如果只有总线层(并不是设备层) 访问device 结构 ,那就只需修改需要修改的那一层即可.用户接口这种对系统中所有设备进行一种完全分层的组织的好处是可以相对容易的给用户空间提供一种完全分层次的设备关系图.通过实现一种称之谓

7、 sysfs 的特殊的虚拟文件系统内核已经实现了这样的组织视图.因此用户就可以在用户空间的任意点挂载这个完整的 sysfs 文件系统.也可以把下面的语句添加到/etc/fstab 中来实现挂载:复制内容到剪贴板代码:sysfs /sys sysfs defaults 0 0Or by hand on the command line:或者在命令行下敲如下的命令进行挂载:复制内容到剪贴板代码:# mount -t sysfs sysfs /sys无论何时在这个树上插入设备,内核都会为它创建一个目录.这个目录可能在每个层中出现比如全局层,总线层,或设备层.在全局层一般创建两个文件-“name“和“

8、power“.只是列出了设备的名称 .后一个是 我们的内核4描述设备当前的电源状态.它通常被用来设置当前的电源状态.总线层也会为在探测时发现的设备创建文件.例如,PCI 层一般会为每一个 PCI 设备创建irq和resource文件.特定设备的驱动程序也可能会在它的目录下通过创建文件来导出该设备的数据或提供调整的接口?更多关于 sysfs 目录布局的信息可以查阅当前文件夹中的其它文档和文件Documentation/filesystems/sysfs.txt.Binding原文作者:翻 译者: saltycookie 校 订者:版本状态:还未完成=驱动程序绑定驱动程序绑定是把设备与能够控制该

9、设备的驱动程序关联的过程。典型的情况下,由总线驱动程序来处理绑定,因为每一种总线都有自己特定的结构体来表示设备和设备驱动。有了表示设备和设备驱动程序的通用结构体,大部分的绑定工作使用同样的代码就可以完成。总线表示总线类型的结构体包含了系统里面连接在这种总线上的所有设备的列表。为某个设备调用 device_register 的时候,该设备就被插到列表的末端。这个结构体里面也包含了总线上所有驱动程序的的列表。当为某个驱动程序调用 dirver_register 的时候,该驱动程序就被插到列表的末端。这两个事件触发了驱动程序绑定。device_register添加新设备的时候,系统扫描总线的驱动程序

10、列表,试图找到支持该设备的驱动程序。如何确定驱动程序支不支持该设备呢?就看设备标识符(device ID)是不是与驱动程序支持的所有设备标识符的其中一个相匹配。设备标识符的格式和语义因总线而异。与其推导一个复杂的状态自动机和匹配算法, 我们的内核5通常是交由总线驱动程序提供一个匹配设备和驱动程序的回调函数。如果匹配成功,回调函数返回 1;否则返回 0.int match(struct device * dev, struct device_driver * drv);如果匹配成功,系统将设备的 driver 域置为该驱动程序,并调用驱动程序的 probe 回调函数,以检测驱动程序是否确实支持这

11、个硬件,同时确定设备是否处于工作状态。设备类型probe 成功完成调用后,设备被注册到它所属的设备类型中。设备驱动程序属于唯一一个类型,记录在设备结构体的 devclass 域中。在设备类型的 register_dev 回调函数中,会调用 devclass_add_device 遍历该类型下的所有设备并注册该设备。注意:设备类型结构体以及操作它们的系统调用并不包含在主流的内核中,所以我们这里的讨论多少有点推测的味道。驱动程序当驱动程序关联到设备上时,该设备被插到驱动程序的设备列表中。sysfs驱动程序绑定后:在总线的 devices 目录下面创建一个指向该设备的物理目录的符号链接。在驱动程序的

12、 devices 目录下面创建一个指向该设备的物理目录的符号链接。在设备类型的目录下创建一个设备目录,并与该设备在 sysfs 中的物理位置建立符号链接。也可建立从设备的物理目录到它的设备类型目录或者类型根目录,以及到它的驱动程序目录的符号链接,不过现在还没有这么做。driver_register注册驱动程序的过程与添加新设备几乎是一样的。系统对总线的设备列表进行遍历以发现匹配的设备,并将尽可能多的设备绑定到该驱动程序上。已经有驱动程序的设备会被忽略。 我们的内核6删除设备和驱动程序删除设备时,驱动程序的 remove 回调函数被调用,将设备从它的设备列表中删除,并将设备的引用数减 1,直至引

13、用数减到为止。两者之间的所有符号链接也被删除。删除驱动程序时,必须对它所支持的所有设备进行遍历,对每个设备调用驱动程序的 remove 回调函数。设备从驱动程序的设备列表中删除,两者之间的所有符号链接也被删除。Bus原文作者:翻 译者:xiaochuan-xu 校 订者:版本状态:还未完成=总线类型定义struct bus_type char * name;struct subsystem subsys;struct kset drivers;struct kset devices;struct bus_attribute * bus_attrs;struct device_attribute

14、 * dev_attrs;struct driver_attribute * drv_attrs;int (*match)(struct device * dev, struct device_driver * drv);int (*hotplug) (struct device *dev, char *envp, int num_envp, char *buffer, int buffer_size);int (*suspend)(struct device * dev, pm_message_t state);int (*resume)(struct device * dev);int b

15、us_register(struct bus_type * bus); 我们的内核7声明内核中每一种总线类型(如 PCI, USB 等)都应该声明一个与之对应的静态对象。必须初始化name 域,并可选择性的初始化 match 回调函数。struct bus_type pci_bus_type = .name= “pci“,.match = pci_bus_match,;这个结构体应该通过一个头文件向驱动程序开放:extern struct bus_type pci_bus_type;注册通过调用 bus_register 函数来初始化驱动程序。这个函数初始化总线对象的其余成员变量,并把它插入到

16、一个全局的总线类型链表种。一旦这个总线对象被注册,总线驱动就可以使用总线对象的成员。回调函数match(): 关联驱动程序到设备match 回调函数通过比较特定设备的设备标识与驱动程序支持的设备标识为总线提供这个驱动程序是否支持这个特定的设备的判断机会。这种方式没有牺牲总线私有属性或类型安全。当向总线注册一个驱动时,系统遍历总线的设备链表,并为每个无驱动程序关联的设备调用match 回调函数。设备与驱动程序链表 我们的内核8设备链表和驱动程序链表是用来替代大多总线持有的本地链表。它们分别是 struct device和 struct device_driver 结构的链表。总线驱动可以随心所欲

17、的使用这些链表,但可能需要转换为总线私有的数据类型。LDM 核提供了一些遍历这些链表的辅助函数。int bus_for_each_dev(struct bus_type * bus, struct device * start, void * data,int (*fn)(struct device *, void *);int bus_for_each_drv(struct bus_type * bus, struct device_driver * start, void * data, int (*fn)(struct device_driver *, void *);这些辅助函数遍历各

18、自的链表,并为链表上的每一个设备或驱动程序调用回调函数。所以链表的访问通过持有总线锁同步。链表上的每一个对象的引用计数在调用回调函数之前被增加在获取下一个对象后被减小。调用回调函数时锁被释放。sysfs 文件系统这是一个名叫bus的顶层目录。每一种总线在这个bus目录下获取一个子目录,同时还有两个默认目录:/sys/bus/pci/|- devices- drivers注册到总线上的驱动程序在该总线驱动程序目录下获取一个目录:/sys/bus/pci/|- devices- drivers|- Intel ICH|- Intel ICH Joystick|- agpgart- e100在总线上

19、发现的每一个给总线类型的设备获取一个该总线设备目录下的指向设备物理层次目录的符号链接。/sys/bus/pci/ 我们的内核9|- devices| |- 00:00.0 - /root/pci0/00:00.0| |- 00:01.0 - /root/pci0/00:01.0| - 00:02.0 - /root/pci0/00:02.0- drivers导出属性struct bus_attribute struct attribute attr;ssize_t (*show)(struct bus_type *, char * buf);ssize_t (*store)(struct bu

20、s_type *, const char * buf, size_t count);总线驱动能够通过 BUS_ATTR 宏导出属性,BUS_ATTR 宏工作方式与设备DEVICE_ATTR 宏相似。比如,类似这样定义:static BUS_ATTR(debug,0644,show_debug,store_debug);等价于声明:static bus_attribute bus_attr_debug;这可以用来对 sysfs 文件系统上的总线目录添加和删除属性,使用:int bus_create_file(struct bus_type *, struct bus_attribute *);v

21、oid bus_remove_file(struct bus_type *, struct bus_attribute *);Class原文作者:翻 译者: 王翔 校 订者:版本状态:Request for comment!=设备类介绍一个设备类描述了一种类型的设备,比如说是声音或者是网络设备。随后的设备类是这样定义的: 我们的内核10每一个设备类都定义了一系列的语意和一个与该类对应的设备所要遵循的编程接口。设备的驱动就是这个编程接口的实现,用于驱动在特定总线上工作的特定设备。设备工作在什么总线上,对于设备类是不可知的。 编程接口设备类的结构可能会是这样的:typedef int (*dev

22、class_add)(struct device *);typedef void (*devclass_remove)(struct device *);struct device_class char * name;rwlock_t lock;u32 devnum;struct list_head node;struct list_head drivers;struct list_head intf_list;struct driver_dir_entry dir;struct driver_dir_entry device_dir;struct driver_dir_entry drive

23、r_dir;devclass_add add_device;devclass_remove remove_device;一个典型的设备类的定义可能会是这样的:struct device_class input_devclass = .name = “input“,.add_device = input_add_device,.remove_device = input_remove_device,;每一个设备类的结构应该被导出在一个头文件里面,以便被驱动程序,扩展程序和接口使 我们的内核11用。使用以下的语句,实现设备类的注册和撤销:int devclass_register(struct d

24、evice_class * cls);void devclass_unregister(struct device_class * cls);Devices设备当设备与驱动程序绑定了后,它们就被添加到了驱动程序所属的设备类里面去。在驱动模型内核(这里不知道怎么翻译比较好)问世之前,当设备被初始化了后,这一个添加的操作一般都是在驱动程序在回调 probe()的时候发生的。但是现在,添加操作是在内核中回调了 probe()后发生的。在类中,设备会被枚举出来。每一次设备被加入到类中,类的 devnum 数据项的值就会就增加,并且将会被指定给设备。但是这个数据项的值永远不会减少,也就是说,如果设备从类

25、中移除出去,又重新添加,它将会接受到一个不同的枚举值。类被允许用来为设备创建一个明确的数据结构,并且使用使用一个设备的 class_data 指针来指向这个数据结构。在设备类中,不存在设备的列表。每一个驱动程序都有它支持的设备的列表。设备类拥有都有一个驱动程序的列表。要访问类中的全部驱动程序,遍历类中每个驱动程序的设备列表即可。设备驱动程序当设备被内核注册的时候,设备的驱动程序就添加到了设备的类中去。驱动程序通过设置结构 device driver:devclass 字段来指明这是什么类。文件系统目录结构存在一个顶级的文件系统目录,名称为:class每一个类都在 class 文件夹里面拥有一个

26、目录,下面还有两个默认的子文件夹:class/- input|- devices- 我们的内核12通过类来注册的驱动程序,在 drivers/目录下有一个符号连接,指向了驱动程序的文件夹(在它的 bus 目录下):class/- input|- devices- drivers- usb:usb_mouse - /bus/drivers/usb_mouse/每一个设备都在 devices/目录下面有一个符号连接,指向了设备的物理层次的文件夹:class/- input|- devices| - 1 - /root/pci0/00:1f.0/usb_bus/00:1f.2-1:0/- driv

27、ers导出属性struct devclass_attribute struct attribute attr;ssize_t (*show)(struct device_class *, char * buf, size_t count, loff_t off);ssize_t (*store)(struct device_class *, const char * buf, size_t count, loff_t off);类驱动程序可以使用 DEVCLASS_ATTR 宏来导出属性,工作方式和 DEVICE_ATTR 相似。例如,一个定义可以是这样的:static DEVCLASS_AT

28、TR(debug,0644,show_debug,store_debug);与如下声明的效果是一样的:static devclass_attribute devclass_attr_debug;总线的驱动可以从类的文件系统目录中添加或者或者删除属性,方法如下:int devclass_create_file(struct device_class *, struct devclass_attribute *);void devclass_remove_file(struct device_class *, struct devclass_attribute *); 我们的内核13在上面的例子中

29、,在文件系统的类的文件夹中,文件将会被命名为debug。接口存在着多种用于访问特定设备类类型的同种设备的机制。设备的接口描述了这些机制。当一个设备被添加到了设备类中后,内核尝试将设备添加到每一个接口中去。Device原文作者:翻 译者: Solarapex 校 订者:版本状态:还未完成=基本设备结构体代码:struct device struct list_head g_list;struct list_head node;struct list_head bus_list;struct list_head driver_list;struct list_head intf_list;str

30、uct list_head children;struct device *parent;char nameDEVICE_NAME_SIZE;char bus_idBUS_ID_SIZE;spinlock_t lock;atomic_t refcount;struct bus_type * bus;struct driver_dir_entry dir;u32 class_num;struct device_driver *driver;void *driver_data;void *platform_data; 我们的内核14u32 current_state;unsigned char *

31、saved_state;void (*release)(struct device * dev);域g_list: 全局设备列表中的节点.node: 父设备的孩子列表中的节点.bus_list: 设备从属的总线所属的设备列表中的节点.driver_list: 设备对应的驱动所属的设备列表中的节点.intf_list: intf_data 列表. 对每个该设备所支持的接口, 程序会分配一个结构体.children: 子设备列表.parent: * 待修正 *name: 设备描述(用 ASCII 码).例: “ 3Com Corporation 3c905 100BaseTX Boomerang“

32、bus_id: 设备总线的位置描述(用 ASCII 码). 此设备从属的总线下的所有设备应对应唯一的描述符.例: PCI 总线 bus_id 的格式为:系统中所有 PCI 设备的 bus_id 都对应上述同一个名字.lock: 设备的自旋锁(spinlock) 我们的内核15(译注: 在自旋锁中, 线程简单地循环等待并检查, 直到锁可用.)(xlp 补注: 在 UP(uni processor)情况下,spinlock 就是简单的清中断(CLI)和设中断(SEI).在 SMP 情况下,spinlock_lock 是循环检测锁,可用后获取锁,spinlock_unlock 是直接释放锁).ref

33、count: 设备引用的数量.bus: 指向设备所属总线的 bus_type 结构体的指针.dir: 设备的 sysfs 目录 .(译注: sysfs 是 Linux 2.6 提供的虚拟文件系统. sysfs 从内核设备模型中向用户空间导出设备及驱动的信息. 它也被用来进行配置.)class_num: 设备的 Class-enumerated 值.driver: 指向设备驱动程序结构体 device_driver 的指针.driver_data: 驱动相关的数据.platform_data: 设备所在平台的数据.例: 对嵌入式或片上系统(SOC)这类用户自定义板上的设备, Linux 常使用p

34、latform_data 指向一个针对板的结构体, 来描述设备以及设备间的连线.这样一个结构体中可能包含可用的端口, 芯片参数, GPIO 针扮演的额外角色等等. 它可以缩小“板支持包“(Board Support Packages, BSP)的体积并减少驱动中针对板的#ifdef 的数量.current_state: 设备当前电源状态.saved_state: 指向设备已保存的状态的指针. 驱动可以利用它来控制设备,release: 当所有设备引用都撤销后用来释放设备的回调函数. 它应由为设备分配空间的程序(也就是发现这个设备的总线驱动 )来设置 我们的内核16编程接口发现设备的总线驱动程序

35、用下列接口来向核心注册该设备:代码:int device_register(struct device * dev);总线负责初始化下列域:- parent- name- bus_id- bus当设备引用减为零时, 设备就被从核心删除. 设备引用数可由下列接口调整:代码:struct device * get_device(struct device * dev);void put_device(struct device * dev);如果设备引用数不为零(即便是在设备正在被卸载的过程中), get_device 将返回一个指针, 该指针指向设备传回的一个结构体.驱动程序可以通过下列接口访问

36、设备结构体中的锁:代码:void lock_device(struct device * dev);void unlock_device(struct device * dev);属性代码:struct device_attribute struct attribute attr;ssize_t (*show)(struct device * dev, char * buf, size_t count, loff_t off);ssize_t (*store)(struct device * dev, const char * buf, size_t count, loff_t off);使用

37、一个简单的类似 procfs 的接口 ,便可以通过驱动程序导出设备属性(译注: procfs 是 process file system 的缩写, 它是一个启动时建立的伪文件系统, 用来访问内核中的进程信息. 该文件系统通常被挂载到/proc 下. 它因为不是真实的文件系统, 所以只消耗少量内存, 而不占存储空间) 我们的内核17关于 sysfs 如何工作的信息 , 请参阅 Documentation/filesystems/sysfs.txt属性用宏 DEVICE_ATTR 来声明:代码:#define DEVICE_ATTR(name,mode,show,store)例:代码:DEVICE

38、_ATTR(power,0644,show_power,store_power);上句声明了一个叫做“dev_attr_power“ 的设备属性结构体. 此结构体可以用下列接口添加到设备或同设备删除:代码:int device_create_file(struct device *device, struct device_attribute * entry);void device_remove_file(struct device * dev, struct device_attribute * attr);例:代码:device_create_file(dev,device_remove

39、_file(dev,文件名和模式将分别是“power“和 0644(-rw-r-r-).Devres原文作者:Tejun Heo 翻 译者:Henry 校 订者:版本状态:已完成=Devres - 设备资源管理=Tejun Heo 于 2007 年 1 月 10 号第一次起草1.简介 : 嘿? Devres(设备资源)?2.Devres(设备资源) : 果壳里的 Devres(设备资源) 我们的内核183.Devres(设备资源)组 : 聚集 Devres(设备资源)和释放 Devres(设备资源)4.详细内容 : 生命周期规则 ,调用上下文, .5.费用 : 我们必须为此付出多大的代价 ?6

40、.管理级别的接口列表: 现有的已被实现的管理级别的接口1.简介-当你正试着用 IO 映射来转化 libata, devres(设备资源)就产生了。每个被 IO 映射的地址都应该被保存起来,而当驱动被卸载时都应该变成未映射的。举个例子来说,一个简单的 SFF ATA 控制器 (就是那种很经典的 PCI IDE)在本地模式需要使用五个 PCI BARS,并且所有的PCI BARS 都需要被维护。就和大多数其他的设备驱动一样,在-remove 和-probe 失败路径里 libata 底层驱动也有很多的漏洞。是的,那也许是因为 libata 底层驱动开发者们都是一群懒家伙,但是是不是所有的底层开发者

41、都是这样呢?在没有任何关于 Braindamaged 的文档的情况下,我花了一天的时间来折腾 Braindamaged 硬件,最后它成功的工作了。出于某种原因,我们并没有像测试核心代码一样来测试底层驱动,并且一些在驱动卸载时发生的漏洞以及一些初始化失败也没能引起我们的注意。而关于初始化失败的路径则是更加糟糕,因为它需要应付多个入口点,更不用说完全遍历了。所以,许多底层驱动都会在卸载时产生资源泄露,一半的失败原因都是在实现 probe()时导致的,当它执行失败后就会产生泄露,也许还会产生更加意想不到的错误。IO 映射添加了更多与 probe()的结合,当然也包括 msi 和 msix。2. De

42、vres(设备资源)-设备资源从根本上说就是一个占着内存的由设备结构体连接而成的链表。每个设备资源入口都与一个释放资源的函数相关联。一个设备资源能通过多种方式来释放。不管是那一种方式,所有的设备资源入口都应该在驱动被卸载时而释放掉。释放资源时,相关联的释放函数就会被应用,并且设备资源入口也会被释放掉。设备驱动使用资源时,管理级别接口就会被创建用来使用设备资源。举例来说,使用dma_alloc_coherent()来获得连续的 DMA 内存。这个管理级别的版本被称作dmam_alloc_coherent()。它和 dma_alloc_coherent()功能大致一样,除了 DMA 内存分配时使用

43、它来管理,并且在卸载时自动释放所分配的内存。实现看起来和下面相似:struct dma_devressize_t size; 我们的内核19void *vaddr;dma_addr_t dma_handle; static void dmam_coherent_release(struct device *dev, void *res)struct dma_devres *this = res;dma_free_coherent(dev, this-size, this-vaddr, this-dma_handle);dmam_alloc_coherent(dev, size, dma_han

44、dle, gfp)struct dma_devres *dr;void *vaddr;dr = devres_alloc(dmam_coherent_release, sizeof(*dr), gfp);./* alloc DMA memory as usual */vaddr = dma_alloc_coherent(.);./* record size, vaddr, dma_handle in dr */dr-vaddr = vaddr;.devres_add(dev, dr);return vaddr;如果一个驱动使用 dmam_alloc_coherent(), 那么被分配的区域都会保证被释放不管是否是中途初始化失败还是驱动被卸载。如果大多数的资源都是用管理级别的接口来获得,那么一个驱动在编写初始化和退出代码时就会显得更加简单。初始化路径看起来大概和下面很像:my_init_one()struct mydev *d;d = devm_kzalloc(dev, sizeof(*d), GFP_KERNEL);if

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 企业管理 > 管理学资料

本站链接:文库   一言   我酷   合作


客服QQ:2549714901微博号:道客多多官方知乎号:道客多多

经营许可证编号: 粤ICP备2021046453号世界地图

道客多多©版权所有2020-2025营业执照举报