18 linux字符设备驱动之设备号

设备驱动通常是给用户进程来调用的, 但用户进程通过什么来调用驱动?
最常用的是设备驱动里实现字符设备驱动, 实现后在”/dev”目录里提供一个设备文件, 然后用户进程就可以通过操作设备文件来调用驱动.

如pc上的uart设备文件:
crw-rw—- 1 root dialout 4, 64 Jun 8 09:20 /dev/ttyS0
crw-rw—- 1 root dialout 4, 65 Jun 8 09:20 /dev/ttyS1
crw-rw—- 1 root dialout 4, 66 Jun 8 09:20 /dev/ttyS2
crw-rw—- 1 root dialout 4, 67 Jun 8 09:20 /dev/ttyS3

第一个字符’c’表示字符设备文件,也就是此设备文件对应着一个字符设备驱动.
设备文件名字不重要,不管改成什么名字,功能还是可以用的.

设备文件的设备号才是最重要的.设备号由主设备号和次设备号组成.
如ttyS0的主设备号是4, 次设备号是64.
主设备号通常表示一个字符设备驱动, 上面4个uart设备它们驱动方法应是一样的,可以共用一个驱动。
在驱动里可通过次设备号来区分不同的硬件接口.

设备驱动里在初始化时也需指定使用哪些设备号。当用户进程操作设备文件时,内核会根据设备文件的设备号找到对应的设备驱动,从而让用户进程通过内核与设备驱动建立联系,实现调用驱动里实现的功能.

//
设备号很重要,在系统里是不可以重用的资源。注意是设备号不能重用,但主设备号可不可以重用?

在linux内核里用类型”dev_t”来表示一个设备号. 其实就是一个unsigned int.

dev_t类型有32位数, 其中高12位用于存放主设备号,低20位用于存放次设备号.
在”include/linux/kdev_t.h”里有提供设备号的操作宏:

#define MINORBITS   20
#define MINORMASK   ((1U << MINORBITS) - 1)

#define MAJOR(dev)  ((unsigned int) ((dev) >> MINORBITS))
#define MINOR(dev)  ((unsigned int) ((dev) & MINORMASK))
#define MKDEV(ma,mi)    (((ma) << MINORBITS) | (mi))


设备号使用前需要向内核申请,使用完后需返还内核。

#include <linux/fs.h>    

//静态:申请指定的设备号, from指设备号(需已指定主设备和次设备号), count指使用该驱动有多少个设备(次设备号), name设备名(用于查看用, 长度不能超过64字节   )
int register_chrdev_region(dev_t from, unsigned count, const char *name);


//动态申请设备号, 由内核分配没有使用的主设备号, 分配好的设备号存在dev(不需初始化), baseminor指次设备号从多少开始, count指设备个数, name设备名 
int alloc_chrdev_region(dev_t *dev, unsigned baseminor, unsigned count,
            const char *name)

//释放设备号, from指设备号, count指设备数
void unregister_chrdev_region(dev_t from, unsigned count)

//可通过”cat /proc/devices”查看系统里主设备号的使用状况
//也可在内核源码的documentations/devices.txt可查看设备号的保留用途.

/
测试代码:

    #include <linux/init.h>
    #include <linux/module.h>
    #include <linux/fs.h>

    #define MYMA  1234
    #define MYMI  3344
    #define COUNT    3

    dev_t devid; //用于存放设备号 
    static int __init test_init(void)
    {
        int ret;

        devid = MKDEV(MYMA, MYMI); //生成一个设备号
        ret = register_chrdev_region(devid, COUNT, "mydev");
        if (ret < 0)
            goto err0;

        //执行到这里,则有三个设备号(1234,3344), (1234, 3345), (1234, 3346)
        return 0;
    err0:
        return ret;
    }

    static void __exit test_exit(void)
    {
        //使用完后需回收设备号
        unregister_chrdev_region(devid, COUNT);
    }

    module_init(test_init);
    module_exit(test_exit);

    MODULE_LICENSE("GPL");
编译后加载模块后 :
cat /proc/devices
... 
1234 mydev
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Linux字符设备驱动实验是指在Linux操作系统中编写和测试字符设备驱动程序的过程。字符设备驱动程序负责与字符设备进行交互,包括输入输出数据、控制设备和处理设备的状态等。 在进行Linux字符设备驱动实验之前,首先需要了解字符设备字符设备驱动的基本概念及其工作原理。字符设备是指以字符为单位进行输入输出的设备,如串口、打印机等。字符设备驱动是指将操作系统与字符设备进行交互的程序。 在实验中,我们通常需要编写一个字符设备驱动程序,包括初始化设备、读写数据、控制设备等功能。首先,我们需要定义字符设备驱动的数据结构,包括设备号、驱动程序打开、关闭等函数的实现。然后,我们需要实现字符设备驱动的读写函数来实现数据的输入输出。最后,我们可以进行一些附加功能的实现,如控制设备的状态、处理中断等。 在实验过程中,我们需要使用Linux内核提供的字符设备接口来进行字符设备驱动的编写和测试。可以使用一些工具和命令来加载和测试字符设备驱动程序,如insmod、rmmod等。通过这些工具和命令,我们可以加载和卸载字符设备驱动程序,并在用户空间进行数据的读写操作,来测试字符设备驱动的功能和性能。 Linux字符设备驱动实验可以帮助我们深入了解字符设备字符设备驱动的工作原理,并学习Linux内核的开发和调试技术。通过实验,我们可以更好地理解操作系统和驱动程序之间的关系,提高我们在Linux系统开发和嵌入式系统开发中的能力。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值