Linux 字符设备驱动(二)---字符设备驱动开发流程及主要函数定义

参考资料:《Linux驱动开发入门与实战》

字符驱动开发思维导图:

1、构建设备号dev_t
    一个字符设备或块设备都有一个主设备号和一个次设备号。主设备号用来标识与设备文件相连的驱动程序,用来反映设备类型。次设备号被驱动程序用来辨别操作的是哪个设备,用来区分同类型的设备。
    linux内核中,设备号用dev_t来描述,2.6.28中定义如下:
 typedef u_long dev_t;
 在32位机中是4个字节,高12位表示主设备号,低20位表示次设备号。

    定义设备号:dev_t devno;

    查看主设备号:  cat /proc/devices
    查看当前设备的主次设备号: ls -l /dev    内核为我们提供了几个方便操作的宏实现dev_t:

1.1 通过major和minor构建设备号

  int major = 100;
  int minor= 0;
  dev_t devno = MKDEV(int major,int minor);

   注:这只是构建设备号。并未注册,需要调用register_chrdev_region 静态申请;

1.2 从设备号中提取主次设备号

int major = MAJOR(dev_t devno);                              
int minor = MINOR(dev_t devno);

2、分配设备号
2.1 静态分配设备号
    函数原型:int register_chrdev_region(dev_t from, unsigned count, const char *name);
    头文件:#include <linux/cdev.h>
    函数功能:申请使用从from开始的count个设备号(主设备号不变,次设备号增加);
    参数:
    from:要分配的设备号范围的起始值。一般只提供from的主设备号,from的次设备号通常被设置为0;
    count:需要申请的连续设备号的个数;
    name:和该范围编号关联的设备名称,该名称不能超过64字节;
    返回值:成功时返回0,失败时返回一个负的错误码,并且不能为字符设备分配设备号。
    源代码如下:

int register_chrdev_region(dev_t from, unsigned count, const char *name)
{
    struct char_device_struct *cd;
    dev_t to = from + count;
    dev_t n, next;
 
    for (n = from; n < to; n = next) {
        next = MKDEV(MAJOR(n)+1, 0);
        if (next > to)
            next = to;
        cd = __register_chrdev_region(MAJOR(n), MINOR(n),
                   next - n, name);
        if (IS_ERR(cd))
            goto fail;
    }
    return 0;
fail:
    to = n;
    for (n = from; n < to; n = next) {
        next = MKDEV(MAJOR(n)+1, 0);
        kfree(__unregister_chrdev_region(MAJOR(n), MINOR(n), next - n));
    }
    return PTR_ERR(cd);
}

2.2 动态分配设备号
    函数原型:int alloc_chrdev_region(dev_t *dev, unsigned baseminor, unsigned count,const char *name);
    头文件:#include <linux/cdev.h>
    函数功能:申请使用从from开始的count 个设备号(主设备号不变,次设备号增加);
    参数:
    dev:dev作为输出参数,在函数成功返回后将保存已经分配的设备号。函数有可能申请一段连续的设备号,这是dev返回的第  一个设备号;
    baseminor:要申请的第一个次设备号;
    count:次设备的个数;
    name:和该范围编号关联的设备名称,该名称不能超过64字节;
    返回值:成功返回0,失败返回错误码;
    源代码如下:

int alloc_chrdev_region(dev_t *dev, unsigned baseminor, unsigned count,
            const char *name)
{
    struct char_device_struct *cd;
    cd = __register_chrdev_region(0, baseminor, count, name);
    if (IS_ERR(cd))
        return PTR_ERR(cd);
    *dev = MKDEV(cd->major, cd->baseminor);
    return 0;
}

2.3 申请设备号举例

    int major = 100;
    dev_t devno;

    if(major)
    {
        devno= MKDEV(major, 0);
        ret = register_chrdev_region(devno, 1, "xxx_dev");
        if(ret != 0)
        {
            printk("[%s] %s %d : failed!\n", __FILE__, __func__, __LINE__);
            return -1;
        }
    }
    else
    {
        ret = alloc_chrdev_region(&devno, 0, 1, "xxx_dev");
        if(ret != 0)
        {
            printk("[%s] %s %d : failed!\n", __FILE__, __func__, __LINE__);
            return -1;
        }
    }

2.4 注销设备号
    void unregister_chrdev_region(dev_t from, unsigned count);
    from表示要释放的设备号,count表示从from开始要释放的设备号的个数。

3、分配cdev
3.1 静态分配cdev

    struct cdev xxx_cdev;

3.2 动态分配cdev

<
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值