【嵌入式Linux驱动开发】三、字符设备驱动(一)
2014-04-08 20:31
579 查看
1. 基本步骤
(1)确定主设备号和次设备号
(2)实现字符驱动程序
实现file_operations结构体;
实现初始化函数,注册字符设备;
实现销毁函数,释放字符设备;
实现字符设备其他基本成员函数。
(3)创建设备文件节点
2. 什么是主设备号/次设备号
主设备号是内核识别一个设备的标识。它是一个整数(占12位),通常使用1~255。
次设备号由内核使用,用于正确确定设备文件所指的设备。它也是一个整数(占20位),通常使用0~255。
注:同一类设备的主设备号相同,不同的是次设备号。如多个串口的主设备号是相同的,次设备号不同。
3. 设备编号的内部表达
(1)dev_t类型(32位):用来保存设备编号
(2)从dev_t获得主、次设备号:
MAJOR(dev_t): //主
MINOR(dev_t); //次
(3)将主、次设备号转换成dev_t类型:
MKDEV(int major, int minor);
4. 分配设备号
通常在模块加载函数中调用。
(1)手工分配:找一个内核没有使用的主设备号来使用
(2)动态分配:
5. 释放设备号
通常在模块清理函数中调用。
6. 重要结构体
(1)cdev结构体
(2)file_operations结构体
是字符驱动和内核的接口,在include/linux/fs.h中定义;
字符驱动都要实现一个file_operations结构体;
file_operations的主要成员:
struct module *owner:指向模块自身(THIS_MODULE)
open:打开设备
release:关闭设备
read:从设备上读数据
write:向设备上写数据
ioctl:I/O控制函数
llseek:定位当前读写位置指针
mmap:映射设备空间到进程的地址空间
(3)file结构体
file_operations结构相关的一个结构体,描述一个正在打开的设备文件。
file的成员:
loff_t f_pos:当前读写位置
unsigned int f_flags:标识文件打开时是否可读或可写,O_RDONLY、O_NONBLOCK、O_SYNC
struct file_operations *f_op:文件相关的操作,指向所实现的struct file_operations
void *private_data:私有数据指针,驱动程序可以将这个字段用于任何目的或者忽略(设为NULL)这个字段
(4)inode结构体
内核用inode结构在内部表示文件;
inode与file的区别:file表示打开的文件描述符,多个表示打开的文件描述符的file结构可以指向一个inode结构。
inode的重要成员:
dev_t i_rdev:对表示设备文件的inode结构,该字段包含了真正的设备号
struct cdev *i_cdev:表示字符设备在内核中的内部结构
7. 字符设备驱动程序模版
(1)确定主设备号和次设备号
(2)实现字符驱动程序
实现file_operations结构体;
实现初始化函数,注册字符设备;
实现销毁函数,释放字符设备;
实现字符设备其他基本成员函数。
(3)创建设备文件节点
2. 什么是主设备号/次设备号
主设备号是内核识别一个设备的标识。它是一个整数(占12位),通常使用1~255。
次设备号由内核使用,用于正确确定设备文件所指的设备。它也是一个整数(占20位),通常使用0~255。
注:同一类设备的主设备号相同,不同的是次设备号。如多个串口的主设备号是相同的,次设备号不同。
3. 设备编号的内部表达
(1)dev_t类型(32位):用来保存设备编号
(2)从dev_t获得主、次设备号:
MAJOR(dev_t): //主
MINOR(dev_t); //次
(3)将主、次设备号转换成dev_t类型:
MKDEV(int major, int minor);
4. 分配设备号
通常在模块加载函数中调用。
(1)手工分配:找一个内核没有使用的主设备号来使用
#include<linux/fs.h> int register_chrdev_region(dev_t first, unsigned int count, char *name); //first是设备号,次设备号通常为0;count是要分配设备号的个数,即次设备号个数;name是此类设备的名字。
(2)动态分配:
#include<linux/fs.h> int alloc_chrdev_region(dev_t *dev, unsigned int firstminor, unsigned int count, char *name); //dev是输出的设备号;firstminor是要申请第一个次设备号;count是要申请的设备号个数;name是此类设备的名字。
5. 释放设备号
通常在模块清理函数中调用。
#include<linux/fs.h> void unregister_chrdev_region(dev_t dev, unsigned int count);
6. 重要结构体
(1)cdev结构体
struct cdev { struct kobject kobj; //内嵌的kobject对象 struct module *owner; //所属模块 struct file_operations *ops; //文件操作结构体 struct list_head list; dev_t dev; //设备号 unsigned int count; };操作cdev结构体的函数:
void cdev_init(struct cdev *cdev, struct file_operations *ops); //用于初始化已分配的cdev结构,并建立cdev和file_operations之间的连接 struct cdev *cdev_alloc(void); //用于动态申请一个cdev内存 int cdev_add(struct cdev *cdev, dev_t num, unsigned int count); //向内核添加一个cdev,完成字符设备的注册,通常在模块加载函数中调用 void cdev_del(struct cdev *cdev); //删除一个cdev,完成字符设备的注销,通常在模块卸载函数中调用
(2)file_operations结构体
是字符驱动和内核的接口,在include/linux/fs.h中定义;
字符驱动都要实现一个file_operations结构体;
file_operations的主要成员:
struct module *owner:指向模块自身(THIS_MODULE)
open:打开设备
release:关闭设备
read:从设备上读数据
write:向设备上写数据
ioctl:I/O控制函数
llseek:定位当前读写位置指针
mmap:映射设备空间到进程的地址空间
(3)file结构体
file_operations结构相关的一个结构体,描述一个正在打开的设备文件。
file的成员:
loff_t f_pos:当前读写位置
unsigned int f_flags:标识文件打开时是否可读或可写,O_RDONLY、O_NONBLOCK、O_SYNC
struct file_operations *f_op:文件相关的操作,指向所实现的struct file_operations
void *private_data:私有数据指针,驱动程序可以将这个字段用于任何目的或者忽略(设为NULL)这个字段
(4)inode结构体
内核用inode结构在内部表示文件;
inode与file的区别:file表示打开的文件描述符,多个表示打开的文件描述符的file结构可以指向一个inode结构。
inode的重要成员:
dev_t i_rdev:对表示设备文件的inode结构,该字段包含了真正的设备号
struct cdev *i_cdev:表示字符设备在内核中的内部结构
7. 字符设备驱动程序模版
//字符设备驱动模块加载函数 static int __init xxx_init(void) { ... cdev_init(&xxx_dev.cdev, &xxx_fops); //初始化cdev xxx_dev.cdev.owner = THIS_MODULE; ad9e //获取字符设备编号 if(xxx_major) { register_chrdev_region(xxx_dev_no, 1, DEV_NAME); } else { alloc_chrdev_region(&xxx_dev_no, 0, 1, DEV_NAME); } ret = cdev_add(&xxx_dev.cdev, xxx_dev_no, 1); //注册设备 ... }
//字符设备驱动模块卸载函数 static void __exit xxx_exit(void) { unregister_chrdev_region(xxx_dev_no, 1); //释放占用的设备号 cdev_del(&xxx_dev.cdev); //注销设备 ... }
相关文章推荐
- Am335x 下GPIO控制实例
- 驱动分类
- SylixOS中APIC HPET定时器字符驱动实现
- linux设备驱动第二篇:构造和运行模块
- 字符设备设备节点创建的两种方法
- Linux内核中的pinctrl子系统应用实例
- linux驱动模块Makefile解
- Linux字符驱动中container_of宏的作用
- SylixOS中APIC HPET定时器字符驱动实现
- Linux字符设备中的两个重要结构体(file、inode)
- 字符设备驱动程序
- linux内核input子系统解析
- Linux应用程序访问字符设备驱动详细过程解析
- TTY
- linux下字符设备驱动的三种创建方式
- linux设备驱动--字符设备驱动
- 字符设备驱动程序之异步通知
- 字符设备驱动程序之poll机制
- Linux字符设备驱动结构
- 开发一个字符设备驱动