字符设备驱动函数解析(学习总结)
2012-12-02 12:31
246 查看
makefile中
obj -m 表示一个模块
obj -y 表示编译进内核
在学习驱动设备的时候,虽然各个模块知道大体是什么意思,但是具体到各个功能模块函数里面的一些定义,就感觉有些头疼
dev_t devno = MKDEV(mem_major, 0)
dev_t 是设备这种类型
MEDEV是宏构造主次设备号
静态分配 if(mem_major)为大于0
如果mem_major==0则动态分配
静态分配:
使用register_chrdev_region函数
动态分配:
由内核去找设备号
使用alloc_chrdev_region分配设备号
缺点:无法再安装驱动前创建设备文件。
注销设备号:
使用函数:unregister_chrdev_region
手动创建
mknod filename typle major minor
设备文件起桥梁的作用譬如read的时候传达给驱动程序
驱动程序再执行到硬件中然后返回到设备文件中。
在liNUX字符设备驱动设计中有三种很重要的数据结构
struct file:代表一个打开的文件。系统中每个打开的文件在内核空间中都有一个关联的stuct file.
struct inode:用来记录文件的物理信息。
struct file_operations:由函数指针构成。
右边是函数指针=左边函数名字。
找驱动函数去执行。绑着驱动程序。
在2.6内核中字符设备用struct cdev来描叙。其注册分三步:
分配cdev初始化cdev添加cdev
分配使用cdev_alloc函数:
初始化使用cdev_init函数:
添加使用 cdev_add函数:
完成驱动程序的注册后下一步 file_operation的函数需要我们去实现。
open方法:打开
read write:
读和写都完成类似的工作:从设备中读取数据到用户空间;
将数据传递给驱动程序。
size_t loff_t char_user
都是类型。
read和 write方法的buff 参数是用户空间指针,因此它都不能被内核代码直接引用:
用户空间指针在内核空间时可能根本是无效的没有那个地址映射。
内核提供了专门的函数访问用户空间的指针:
如copy_from_user 和copy_to_user两个函数。我们的read 和write是站在用户的角度来看的
用户需要读则要到用户。分析数据的流向。
字符设备的注销 cdev_del函数来完成。
设备号作用:主设备号用来标识与设备文件相连的驱动程序;
次设备号被驱动程序用来辨别操作哪个设备。
主设备号用来反映设备类型次设备号用来区分同类型的设备。
内核中如何描述设备号:
dev_t实质为unsigned int32 位整数高12位为主设备号低20位为此设备号
如何从dev_t中分解出主次设备号:
MAJOR(dev_t dev)
MINOR(dev_t dev)
mem_fops是操作里的 file_option
设备号》初始化》字符设备注册三步(直接定义的就需要分配)
为设备分配内存:
为设备描述结构分配内存:
反汇编(转成汇编语言)工具
arm-linux-dump -D -S hello >log(输入到log)
ELF 文件查看器
arm-linux-readelf -d hello
内核中##表示连接的作用
hello(name) _NR_##name 如果前面hello(name)中name取read则后面name也取read
BOOTLOADER移植
流程两个阶段:
阶段1:硬件的初始化(CPU内部的寄存器内存)
为加载2阶段准备RAM空间
拷贝BOOTLOADER的stage2到RAM中
设置好堆栈(原因:因为第二阶段C也需要堆栈,局部变量需要用到堆栈)
跳转到stage2的C入口点(第二阶段是C语言第一阶段汇编语言)
第一阶段运行在FLASH中第二阶段运行在内存中
阶段2:
硬件(串口网卡等)初始化
将内核映像和根文件系统从FLASH读到RAM中
调用内核
自动创建设备文件:
在驱动初始化的代码里调用class_create为该设备创建一个class,再为每个设备调用
class_device_create创建对应的设备。大致用法如下:
struct class *myclass = class_create(THIS_MODULE, “my_device_driver”);
class_device_create(myclass, NULL, MKDEV(major_num, 0), NULL, “my_device”);
这样的module被加载时,udev daemon就会自动在/dev下创建my_device设备文件。
obj -m 表示一个模块
obj -y 表示编译进内核
在学习驱动设备的时候,虽然各个模块知道大体是什么意思,但是具体到各个功能模块函数里面的一些定义,就感觉有些头疼
dev_t devno = MKDEV(mem_major, 0)
dev_t 是设备这种类型
MEDEV是宏构造主次设备号
静态分配 if(mem_major)为大于0
如果mem_major==0则动态分配
静态分配:
使用register_chrdev_region函数
动态分配:
由内核去找设备号
使用alloc_chrdev_region分配设备号
缺点:无法再安装驱动前创建设备文件。
注销设备号:
使用函数:unregister_chrdev_region
手动创建
mknod filename typle major minor
设备文件起桥梁的作用譬如read的时候传达给驱动程序
驱动程序再执行到硬件中然后返回到设备文件中。
在liNUX字符设备驱动设计中有三种很重要的数据结构
struct file:代表一个打开的文件。系统中每个打开的文件在内核空间中都有一个关联的stuct file.
struct inode:用来记录文件的物理信息。
struct file_operations:由函数指针构成。
右边是函数指针=左边函数名字。
找驱动函数去执行。绑着驱动程序。
在2.6内核中字符设备用struct cdev来描叙。其注册分三步:
分配cdev初始化cdev添加cdev
分配使用cdev_alloc函数:
初始化使用cdev_init函数:
添加使用 cdev_add函数:
完成驱动程序的注册后下一步 file_operation的函数需要我们去实现。
open方法:打开
read write:
读和写都完成类似的工作:从设备中读取数据到用户空间;
将数据传递给驱动程序。
size_t loff_t char_user
都是类型。
read和 write方法的buff 参数是用户空间指针,因此它都不能被内核代码直接引用:
用户空间指针在内核空间时可能根本是无效的没有那个地址映射。
内核提供了专门的函数访问用户空间的指针:
如copy_from_user 和copy_to_user两个函数。我们的read 和write是站在用户的角度来看的
用户需要读则要到用户。分析数据的流向。
字符设备的注销 cdev_del函数来完成。
设备号作用:主设备号用来标识与设备文件相连的驱动程序;
次设备号被驱动程序用来辨别操作哪个设备。
主设备号用来反映设备类型次设备号用来区分同类型的设备。
内核中如何描述设备号:
dev_t实质为unsigned int32 位整数高12位为主设备号低20位为此设备号
如何从dev_t中分解出主次设备号:
MAJOR(dev_t dev)
MINOR(dev_t dev)
mem_fops是操作里的 file_option
设备号》初始化》字符设备注册三步(直接定义的就需要分配)
为设备分配内存:
为设备描述结构分配内存:
反汇编(转成汇编语言)工具
arm-linux-dump -D -S hello >log(输入到log)
ELF 文件查看器
arm-linux-readelf -d hello
内核中##表示连接的作用
hello(name) _NR_##name 如果前面hello(name)中name取read则后面name也取read
BOOTLOADER移植
流程两个阶段:
阶段1:硬件的初始化(CPU内部的寄存器内存)
为加载2阶段准备RAM空间
拷贝BOOTLOADER的stage2到RAM中
设置好堆栈(原因:因为第二阶段C也需要堆栈,局部变量需要用到堆栈)
跳转到stage2的C入口点(第二阶段是C语言第一阶段汇编语言)
第一阶段运行在FLASH中第二阶段运行在内存中
阶段2:
硬件(串口网卡等)初始化
将内核映像和根文件系统从FLASH读到RAM中
调用内核
自动创建设备文件:
在驱动初始化的代码里调用class_create为该设备创建一个class,再为每个设备调用
class_device_create创建对应的设备。大致用法如下:
struct class *myclass = class_create(THIS_MODULE, “my_device_driver”);
class_device_create(myclass, NULL, MKDEV(major_num, 0), NULL, “my_device”);
这样的module被加载时,udev daemon就会自动在/dev下创建my_device设备文件。
相关文章推荐
- Linux 字符设备驱动开发基础(三)—— read()、write() 相关函数解析
- 关于字符设备驱动学习的总结
- 基于mini6410的linux驱动学习总结(二 字符设备与块设备的区别)
- 基于mini6410的linux驱动学习总结(五 字符设备驱动程序实例分析(虚拟设备驱动))
- Linux 字符设备驱动开发基础(四)—— ioctl() 函数解析
- 字符设备驱动的学习总结
- 基于mini6410的linux驱动学习总结(四 设计字符设备驱动程序)
- Linux 字符设备驱动开发基础(五)—— ioremap() 函数解析
- Linux 字符设备驱动开发基础(五)—— ioremap() 函数解析
- 嵌入式Linux驱动学习之路(二十一)字符设备驱动程序总结和块设备驱动程序的引入
- Linux 字符设备驱动开发基础(五)—— ioremap() 函数解析
- Linux 字符设备驱动开发基础(三)—— read()、write() 相关函数解析
- Linux 字符设备驱动开发基础(四)—— ioctl() 函数解析
- Linux 字符设备驱动开发基础(四)—— ioctl() 函数解析
- Linux 字符设备驱动开发基础(三)—— read()、write() 相关函数解析
- Linux 字符设备驱动开发基础(五)—— ioremap() 函数解析
- 字符设备驱动框架学习总结
- Linux驱动学习----字符设备驱动(一)
- Linux 字符设备驱动开发基础(六)—— VFS 虚拟文件系统解析
- [国嵌学习日志][113][字符设备驱动模型]