linux设备驱动简介一
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
设备文件
• Udev
– 动态管理:当设备添加 / 删除时,udev 的守护进程侦听来自内核 的 uevent,以此添加或者删除 /dev下的设备 文件,所以 udev 只 为已经连接的设备产生设备文件,而不会在 /dev下产生大量虚无 的设备文件。 – 自定义命名规则:通过 Linux 默认的规则文件,udev 在 /dev/ 里为 所有的设备定义了内核设备名称,比如 /dev /sda、/dev/hda、 /dev/fd等等。由于 udev 是在用户空间 (user space) 运行,Linux 用 户可以通过自定义的规则文件,灵活地产生标识性强的设备文件 名,比如 /dev/boot_disk、/dev/root_disk、 /dev/color_printer等。 – 设定设备的权限和所有者 / 组:udev 可以按一定的条件来设置设 备文件的权限和设备文件所有者 / 组。
设备文件
• Linux为所有的设备文件都提供了统一的操作函数接口,方 法是使用数据结构struct file_operations。这个数 据结构中 包括许多操作函数的指针,如open()、close()、read()和 write()等,但由于外设的种类较多,操作方式各不相同。 Struct file_operations结构体中的 成员为一系列的接口函数 ,如用于读/写的read/write函数和用于控制的ioctl等。
驱动入口函数
• linux kernel中有很大一部分代码是设备驱动 代码,这些驱动代码都有初始化等函数,q 且一般都只执行一次,为了有更有效的利 用内存,这些代码所 占用的内存需要释放 出来。对只需要初始化运行一次的函数都 加上__init属性,这些函数将被放在( .init.text)段,使用后其空间将被释放。
• 此过程中dev和drv匹配,并开始调用驱动总的probe 函数。此时驱动初始化流程基本结束。
平台设备驱动
• 对于一般平台驱动的platform_driver_register基本 都是放到module_init的函数总使用的,以rtc为例
设备文件
设备文件
• Linux使用对文件一样管理方式来管理设备,所以对于系统 中的每个字符设备或者块设备都必须为其创建一个设备文 件,这个设备文件就是放在/dev/目录下的设备节点,它包 含了该设备的设备类型(块设备或字符设备)、设备号( 主设备号和次设备 号)以及设备访问控制属性等。设备文 件可以通过手工用mknod命令生成 也可以由udev用户工具 软 件在系统启动后根据/sys目录下每个 设备的实际信息创 建,使用后一种方式可以为每个设备动态分配设备号,而 不必分配固定的设备号。
平台设备驱动
• platform_device
平台设备驱动
• 以I2C为例,其平台设备及资源定义为
– 其中定义了两组资源,分别描述了MEM和IRQ类型的资源。在平台 驱动中即可抽象的使用
平台设备驱动
• 平台设备驱动的初始化流程
– platform bus先被kenrel注册 – 系统初始化过程中先platform_add_devices或者 platform_device_register,将平台设备(platform devices) 注册到平台总线中(platform bus) – 平台驱动(platform driver)与平台设备(platform device)的 关联是在platform_driver_register或者driver_register中 实现的,一般这个函数在驱动的初始化过程调用
驱动入口函数
• 静态加载module
– 此属性指定改变量将放在.initcall6.init区段。
驱动入口函数
• 在vmlinux.lds.S中指定了
驱动入口函数
• 宏 INITCALLS
驱动入口函数
• 其他初始化模块的宏定义
– 根据不同的id号以保证模块加载的前后顺序, 同一级别的模块,其顺序无法保证。
平台设备驱动
平台设备驱动
• 从Linux 2.6起引入了一套新的驱动管理和注册机制 :Platform_device和Platform_driver。Linux中大部分 的设备驱动,都可以使用这套机制, 设备用 Platform_device表示,驱动用Platform_driver进行 注册.
设备文件
– 主设备号 • 驱 动程序在初始化时,会注册它的驱动及对应主设备号到系 统中,这样当应用程序访问设备节点时,系统就知道它所访问 的驱动程序了。 – 次设备号 • 驱 动程序遍历设备时,每发现一个它能驱动的设备,就创建 一个设备对象,并为其分配一个次设备号以区分不同的设备。 这样当应用程序访问设备节点时驱动程序就可 以根据次设备 号知道它说访问的设备了。 主设备号标识设备对应的驱动程序,告诉Linux内核使用 哪一个驱动 程序为该设备(也就是/dev下的设备文件)服务;而次设备号则用来 标识具体且唯一的某个设备。
– 一般来说相对独立,拥有独自的资源都可以用平台设备驱动来实 现,例如LCD,usb,camera等等。
• Board-msm7x27.c中msm7x2x_init-> platform_add_devices和 platform_device_register即注册了大量的平台设备
– 平台机制将设备 本身的资源(设备的地址,中断号)注册进内核 ,由内核统一管理,在驱动程序中使用这些资源时通过platform device提供的标准接口进行申请并使用。提高了驱动和资源管理的 独立性。
– kernel_init->init_post->free_initmem
驱动入口函数
• 动态加载module(非编译到kernel的驱动程 序)
– int init_module(void) __attribute__((alias(#initfn))) 用来告诉编译器将init_module作为initfn的别名alias替代initfn 这样可以不用显式的声明init_module,而是使用更具有模块化名字 xxx_init来让人更容易理解的定义入口,之后insmod解析init_module 入口执行之。
设备文件
• 如果系统中的设备不多,而且设备类型又 是常见的,可以使用手 工方式生成设备文 件,为常用设备创建一个已经分配号的设 备号对应的设备文件,这样比较方便。如 果系统很大,系统中的设备太多,那么最 好动态分配设备号,由udev在系统启动之 后根据设备实际信息自动创建设备文件。
设备文件
• 什么是udBaidu Nhomakorabeav
平台设备驱动
• platform driver关联platform device
– platform_driver_register->driver_register>bus_add_driver – bus_add_driver->driver_attach>bus_for_each_dev->driver_probe_device>really_probe
– udev 是 Linux2.6 内核里的一个功能,它替代了 原来的 devfs,成为当前 Linux 默认的设备管理 工具。udev 以守护进程的形式运行,通过侦听 内核发出来的 uevent 来管理 /dev目录下的设备 文件。不像之前的设备管理工 具,udev 在用户 空间 (user space) 运行,而不在内核空间 (kernel space) 运行。
驱动入口函数
• \kernel\init\main.c
– start_kernel->rest_init->kernel_init-> do_basic_setup-> do_initcalls
– do_initcalls调用后,用moudle_init定义的驱动初 始化函数即被执行。
驱动入口函数
属性文件
• 设备属性: – struct device_attribute { struct attribute attr; ssize_t (*show)(struct device *dev, char *buf); ssize_t (*store)(struct device *dev, const char *buf, size_t count);}; 属性文件的实际管理使用通常的函数对来处理: int device_create_file(struct device *device, struct device_attribute *entry); void device_remove_file(struct device *dev, struct device_attribute *attr); – 类似的还有总线属性和驱动属性
• 驱动在初始化阶段如果有相互前后的依赖 关系,需要加以区分,不能统一都是用 module_init初始化,例如:
– 开机初始化系统时间的函数rtc_hctosys,其功能依赖 RTC驱动,所以需要 module_init(msmrtc_init); late_initcall(rtc_hctosys); – I2C驱动由于会被众多I2C设备的驱动调用,所以需要 subsys_initcall(msm_i2c_init_driver); module_init(bma150_init);
设备文件
• 设备文件除了设备名,还有三个属 性:即 类型、主设备号、次设备号。
– 类型主要为字符设备和块设备的区分。
• 网络设备,是面向报文的而不是面向流的,它不支 持随机访问,也没有请求缓冲区。在Linux里一个网 络设备也可以叫做一个网络接口,如eth0,应用程 序是通过Socket而不是设备节点来访问网络设备, 在系统里根本就不存在网络设备节点。
Linux设备驱动简介
2010-07-11
Linux设备驱动简介(1)
• 驱动入口函数 • 平台设备驱动 • 设备文件
驱动入口函数
驱动入口函数
• 几乎每个linux驱动都会有个 module_init(XXX_init),这个函数就是驱动的 入口函数,负责驱动的加载。
– module_init定义在kernel\include\linux\init.h – 根据模块是否动态加载被定义为两种形式
通过这个三步,就将平台总线,设备,驱动关联起 来。
平台设备驱动
• kenrel注册platform bus(bus也是一种device)
– kernel_init->do_basic_setup->driver_init>platform_bus_init->bus_register
平台设备驱动
属性文件
• 以PowerManager为例,
在kernel\kennel\power\main.c中定义了 power_attr(state); static ssize_t state_store(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t n) static ssize_t state_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
• 将平台设备(platform devices)注册到平台总线中 (platform bus),系统启动阶段,总线的驱动链表 还是空的,所以启动阶段的 platform_add_devices()只负责将设备添加到总线 的设备链表上。 – platform_add_devices>platform_device_register>platform_device_add->device_add>bus_attach_device->device_attach – bus_type有值得devices才会被注册到对应的bus 上
设备文件
• Udev工作流程
设备文件
• 创建设备device_add中会调用 kobject_uevent(&dev->kobj, KOBJ_ADD);通过 socket广播消息 • 守护进程中侦听消息handle_device_fd>handle_device_event->make_device>mknod 创建设备文件