android 字符设备驱动程序的一点小总结

1. 分配设备号:
extern int alloc_chrdev_region(dev_t *, unsigned, unsigned, const char *);
extern int register_chrdev_region(dev_t, unsigned, const char *);
第一种方式是静态分配,适用于指定主设备号的情况
第二种是动态分配,主设备号是动态分配的。

2. 注册设备:
extern int register_chrdev(unsigned int, const char *,
               struct file_operations *);
如果前面两步不成功就要注销设备和注销设备号
注销设备:
extern int unregister_chrdev(unsigned int, const char *);
注销设备号:
extern void unregister_chrdev_region(dev_t, unsigned);

说明:

extern int register_chrdev(unsigned int, const char *,
               struct file_operations *);
作用:注册一个字符串设备
unsigned int 是主设备号;
const char*是设备名;
struct file_operations*是文件结构体。
extern int register_chrdev_region(dev_t first, unsigned int count, char* name)
要想注册一个设备则需要一个主设备号,那么就需要给设备分配一个主设备号。
这个函数的作用:就是给一个设备分配设备编号的。
first是要分配设备编号范围的起始值。
count是所请求连续设备编号的个数。不能太大。
name是设备名,(要与该设备编号范围关联)
如果分配成功,则返回0,
如果分配失败,则返回负的错误码。这时候所请求的编号区域不能用。
注:申请是只是一个设备编号区域。
extern int alloc_chrdev_region(dev_ *dev, unsigned int firstminor, unsinged int count, char *name)
说明:
1.如果我们提前知道设备的编号,那么就用register_chrdev_region(),这个可以工作的很好。
2.但是如果我们不知道呢,linux一直想解决这个问题,这就有了上面的函数。
这个函数是动态申请设备编号,这样就不用考虑设备编号的问题了,这个函数分自动分配一个给我们。
*dev是一个输出参数,当设备成功完成调用后,它将保存已分配范围的第一个编号。
firstminor是要请求的第一个次设备号。一般为0。
count同样是所请求连续设备编号的次数。
*name同样是相应和设备名。
一旦给一个设备分配好了设备号后,我们就可以通过cat /proc/devices读取到我们的设备。

3, cdev初始化
cdev_init
cdev_alloc
内核中每个字符设备都对应一个 cdev 结构的变量,下面是它的定义:
struct cdev {
   struct kobject kobj;          // 每个 cdev 都是一个 kobject
   struct module *owner;       // 指向实现驱动的模块
   const struct file_operations *ops;   // 操纵这个字符设备文件的方法
   struct list_head list;       // 与 cdev 对应的字符设备文件的 inode->i_devices 的链表头
   dev_t dev;                   // 起始设备编号
   unsigned int count;       // 设备范围号大小
};
一个 cdev 一般它有两种定义初始化方式:静态的和动态的。
静态内存定义初始化:
struct cdev my_cdev;
cdev_init(&my_cdev, &fops);
my_cdev.owner = THIS_MODULE;
动态内存定义初始化:
struct cdev *my_cdev = cdev_alloc();
my_cdev->ops = &fops;
my_cdev->owner = THIS_MODULE;
两种使用方式的功能是一样的,只是使用的内存区不一样,一般视实际的数据结构需求而定。
struct cdev *cdev_alloc(void)
{
   struct cdev *p = kzalloc(sizeof(struct cdev), GFP_KERNEL);
   if (p) {
       INIT_LIST_HEAD(&p->list);
       kobject_init(&p->kobj, &ktype_cdev_dynamic);
   }
   return p;
}
void cdev_init(struct cdev *cdev, const struct file_operations *fops)
{
   memset(cdev, 0, sizeof *cdev);
   INIT_LIST_HEAD(&cdev->list);
   kobject_init(&cdev->kobj, &ktype_cdev_default);
   cdev->ops = fops;
}
由此可见,两个函数完成都功能基本一致,只是 cdev_init() 还多赋了一个 cdev->ops 的值。
4, cdev_add()

初始化 cdev 后,需要把它添加到系统中去。为此可以调用 cdev_add() 函数。传入 cdev 结构的指针,起始设备编号,以及设备编号范围。
int cdev_add(struct cdev *p, dev_t dev, unsigned count)
{
   p->dev = dev;
   p->count = count;
   return kobj_map(cdev_map, dev, count, NULL, exact_match, exact_lock, p);
}
当一个字符设备驱动不再需要的时候(比如模块卸载),就可以用 cdev_del() 函数来释放 cdev 占用的内存。
void cdev_del(struct cdev *p)
{
   cdev_unmap(p->dev, p->count);
   kobject_put(&p->kobj);
}

 

5, udev自动创建设备结点

可以用mknod来命令手动创建设备节点,也可以使用 class_create(),device_create自动创建设备文件结点

驱动初始化的代码里调用class_create为该设备创建一个class,再为每个设备调用 device_create 创建对应的设备。大致用法如下:


struct class *myclass = class_create(THIS_MODULE, “my_device_driver”);

device_create (myclass , NULL, dev, "%s", “my_device”);

这样的module被加载时,udev daemon就会自动在/dev下创建my_device设备文件。

设备节点创建以后就可以通过open read write等方式,或者通过ioctl来操作设备了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Android系统架构及其驱动研究】   1.1 Android系统架构 .....................................03   1.2 Android代码结构 .....................................04   1.3 Android专用驱动 .....................................05   1.4 Linux设备驱动在Android上的使用分析 ....06   1.5 Android比起Linux的七点优势 ..................10 【Android底层驱动概述】   2.1 Android底层驱动的详细内容 ...................11   2.2 字符设备和块设备 ....................................13   2.3 Linux下的VFS ...........................................14    【Android 驱动类别】   3.1 Android专用驱动 Ashmem、binder、logger .............17   3.2 设备驱动 .................................................................17 【Android 驱动实例】   4.1 Android Led控制实验 ..............................................22   4.2 基于PXA310上的Android手机的驱动开发 ...............31   4.3 Android内核驱动——Alarm .....................................34 【Android 驱动实例】   5.1 CameraSerivce服务的注册流程 ...........................47   5.2 ramdisk driver 驱动实现的源码 ..........................61 【其他】   6.1 提交BUG ..............................................................74   6.2 关于eoe Android .................................................74   6.3 eoe携手支付宝移动应用开发者沙龙 ...................74   6.4 eoe Android移动互联高峰论坛在深圳举行 ..........74
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值