博客
关于我
Linux设备驱动开发学习(4):字符设备驱动(未完)
阅读量:792 次
发布时间:2023-02-05

本文共 2614 字,大约阅读时间需要 8 分钟。

4.1 scull的设计

scull字符设备的驱动将默认对应4个scull设备(文件),分别为scull0到scull3。开发者可以通过在编译时、加载时或运行时的不同方式来改变scull设备的数量。后续将详细说明每种方式的具体操作。

4.2 字符设备的主、次设备号

字符设备的存取依赖于其在文件系统中的名称,类似于普通文件的存取。通过ls -l /dev命令可以查看/dev目录中的设备信息。第1列的字母表示设备类型(c表示字符设备),第5列的数字分别表示主设备号和次设备号。主设备号用于连接设备驱动,现代Linux系统通常允许多个驱动共享同一主设备号,但大部分情况下一个主设备号对应一个驱动。

4.2.1 设备号的内部表示

设备号在内核中用dev_t类型表示。随着内核版本的变化,设备号的实际类型和主次设备号的位分布也可能发生变化。因此,不能简单地将设备号视为某个特定类型。头文件<linux/kdev_t.h>提供了辅助宏来管理设备号:

  • MAJOR(dev_t dev):获取设备的主设备号
  • MINOR(dev_t dev):获取设备的次设备号
  • MKDEV(int major, int minor):构造dev_t,根据指定的主次设备号

4.2.2 设备号的分配与释放

设备号由内核统一管理,字符设备驱动需要向系统申请设备号。分配方式分为静态和动态两种:

  • 静态申请设备号:调用register_chrdev_region函数,参数first为申请的第一个设备号,count为要申请的连续设备号个数,name为设备号区间的名称。函数返回0表示成功,负数表示失败。

  • 动态申请设备号:调用alloc_chrdev_region函数,参数dev指向申请返回的设备号,firstminor指定第一个从设备号,count为要申请的设备号个数,name为设备号区间的名称。函数返回0表示成功,负数表示失败。

设备号申请后必须及时释放,通常在设备驱动模块的退出函数中调用unregister_chrdev_region函数。

4.2.3 动态分配主设备号

部分主设备号已被预先分配给通用设备,开发者可以通过查看Documentation/devices.txt文档获取预分配的主设备号。动态分配方式的优点是可以灵活获取设备号,但需要确保设备号的唯一性和可用性。通过/proc/devices文件可以查看当前分配的主设备号。

4.2.4 scull模块的加载与卸载

为了测试scull驱动,通常需要手动加载或卸载scull模块。开发者可以使用脚本实现:

  • 加载scull模块
#!/bin/shinsmod ./scull.komknod /dev/scull0 c `awk "$module" { print $1 }" /proc/devices | head -n1`mknod /dev/scull1 c $major 1mknod /dev/scull2 c $major 2mknod /dev/scull3 c $major 3chmod -sf scull0 /dev/scull0chgrp bill /dev/scull[0-3]
  • 卸载scull模块
#!/bin/shrmmod scullrm -f /dev/scull[0-3]

另外,Linux提供了模块的自动加载机制。开发者可以通过以下步骤实现:

  • 将模块复制到内核模块目录:
  • sudo cp scull.ko /lib/modules/`uname -r`/kernel/drivers/char/scull.ko
    1. /etc/modules文件中添加模块名称:
    2. sudo vi /etc/modules

      添加行:

      scull
      1. 重启系统后,检查模块是否已加载:
      2. lsmod
        1. 也可以通过编写初始化脚本实现模块的自动加载:
        2. #!/bin/shmodprobe scull

          并创建脚本的软链接:

          sudo ln -s /etc/init.d/scull /etc/rcS.d/Sscull

          4.3 字符设备的重要数据结构

          在开发字符设备驱动前,需要了解以下关键数据结构:

          • struct file_operations:定义在<linux/fs.h>中,描述文件操作接口。字符设备通常将大多数成员置为NULL,如readdirpoll等,因为这些操作不适用于字符设备。
          • struct file:定义在<linux/fs.h>中,描述打开的文件描述符。成员包括:
            • f_mode:文件模式(读写权限)。
            • f_flags:文件标志(非阻塞、同步等)。
            • f_op:文件操作接口。
            • f_private_data:文件自定义数据。
          • struct inode:定义在<linux/fs.h>中,描述文件系统中的文件节点。成员包括:
            • i_rdev:设备文件的设备号。
            • i_bdev:块设备指针。
            • i_cdev:字符设备指针。

          4.4 字符设备注册

          4.4.1 字符设备的分配与初始化

          字符设备通过struct cdev结构体描述。可以通过静态或动态方式分配字符设备结构:

          • 动态分配:
          struct cdev *my_cdev = cdev_alloc();my_cdev->ops = &my_fops;
          • 静态分配:
          cdev_init(&my_cdev, &my_fops);

          4.4.2 挂接字符设备到内核

          调用cdev_add函数将字符设备挂接到内核:

          int cdev_add(struct cdev *p, dev_t dev, unsigned count);

          注意:字符设备在被挂接后可能立即进入使用,必须确保所有准备工作完成。

          4.4.3 从内核删除字符设备

          调用cdev_del函数移除字符设备:

          void cdev_del(struct cdev *p);

          4.5 scull字符设备的实现

          scull字符设备是对内存的操作,不依赖于具体硬件,因此可以在任何支持虚拟化的操作系统上测试。其核心功能包括:

          • 提供四个设备文件(scull0到scull3)。
          • 支持读写操作,数据通过内存映射实现。
          • 提供同步机制(fsync、fasync)。
          • 支持异步I/O操作(aio_read、aio_write)。

          通过以上步骤,可以实现一个功能完善的scull字符设备驱动。

    转载地址:http://cqkfk.baihongyu.com/

    你可能感兴趣的文章
    Linux查看CPU信息
    查看>>
    Linux查看CPU和内存使用情况
    查看>>
    linux查看cpu的负载
    查看>>
    Linux查看mac地址
    查看>>
    linux查看redis安装目录
    查看>>
    Linux查看当前时间
    查看>>
    Linux查看所有用户用什么命令1
    查看>>
    linux查看文件大小
    查看>>
    Linux查看服务器端口打开情况
    查看>>
    linux查看用户登录信息2-who命令
    查看>>
    Linux查看目录命令
    查看>>
    Linux查看硬盘型号
    查看>>
    Linux查看磁盘空间的命令
    查看>>
    linux查看端口占用情况
    查看>>
    Linux查看系统中用户信息,Linux下用于查看系统当前登录用户信息的4种方法
    查看>>
    linux查看系统位数
    查看>>
    linux查看系统内存
    查看>>
    linux查看进程是否存在,不存在则重启
    查看>>
    linux查看远程文件,linux下远程自动查看日志
    查看>>
    linux根文件系统 /etc/resolv.conf 文件详解
    查看>>