创建字符设备

创建字符设备

~/study/linuxlerning/linux-4.9.37/driver_test

Linux字符设备是一种按字节来访问的设备,字符驱动则负责驱动字符设备,这样的驱动通常实现open、close、read和write系统调用。例如:串口、Led、按键等。

创建字符设备文件的方法

1、使用命令 mknod /dev/文件名 c 主设备号 此设备号(查看主设备号:cat /proc/devices)

文件系统与字符设备驱动程序之间的关系

1、在Linux系统中,每一个打开的文件,在内核中都会关联一个struct file结构,它是由内核在打开文件时创建,在文件关闭后释放

struct file结构中的重要成员
  struct file_operations* f_op;  //文件操作函数集
  loff_t   f_pos;         //文件读写指针

2、每一个存在于文件系统中的文件都会关联一个inode结构,该结构主要用来记录文件物理上的信息。因此,它和代表打开文件的file结构是不同的,一个文件没有被打开时不会关联file结构,但是会关联一个inode结构(存于磁盘,操作文件是在内存中建立相应的映射结构)
3、系统实质上是把字符设备的注册表看成了文件。其中chrdevs[]在内核的定义如下

static struct char_device_struct {
    struct char_device_struct *next;
    unsigned int major;
    unsigned int baseminor;
    int minorct;
    char name[64];
    struct cdev *cdev;        /* will die */
} *chrdevs[CHRDEV_MAJOR_HASH_SIZE];

4、 字符设备在内核中使用struct cdev来描述

struct cdev {
    struct kobject kobj;
    struct module *owner;
    const struct file_operations *ops;  //设备操作函数集
    struct list_head list;
    dev_t dev;                //设备号
    unsigned int count;           //设备数
};

5、Linux内核中使用dev_t类型来定义设备号,dev_t其实质为32位unsigned int类型,其中高12位为主设备号,低20位为次设备号。
(1)MKDEV(主设备号,次设备号)
(2)MAJOR(dev_t dev)
(3)MINOR(dev_t dev)

注:字符设备文件与字符设备驱动是通过主设备号建立对应关系;驱动程序用次设备号来区分同类型的设备

设备号的申请与注销

(1)静态申请:开发者自己选择一个数字作为主设备号,通过函数 register_chardev_region 向内核申请
(2)动态分配:使用 alloc_chrdev_region 由内核分配一个可用的主设备号(推荐使用)
(3)不论使用何种方法分配设备号,都应该在驱动退出时,使用 unregister_chrdev_region 函数释放这些设备

字符设备描述结构的分配、注册与注销

  1. 字符设备描述结构的分配、注册与注销
    (1)cdev变量的定义可以采用静态和动态两种方法
      * 静态分配:struct cdev mdev;
      * 动态分配:struct cdev* pdev = cdev_alloc();(可以通过命令:cat /proc/devices查看主设备号)
    (2)cdev变量的初始化使用cdev_init()函数来完成
      void cdev_init(struct cdev *cdev, const struct file_operations *fops)
      cdev: 待初始化的cdev结构
      fops: 设备对应的操作函数集
    (3)字符设备的注册使用cdev_add()函数来完成
    (4)字符设备的注销使用cdev_del()函数来完成

设计Linux字符设备驱动程序的主要工作:

(1)根据外部设备的特点,实现file_operations结构所需要的函数

(2)调用函数cdev_alloc()函数向系统动态申请一个cdev结构实例

(3)调用函数cdev_init()初始化cdev实例,并建立cdev实例与file_operations实例之间的连接

(4)调用函数alloc_chrdev_region()向系统申请一个设备号

(5)调用函数cdev_add()向系统添加一个设备

(6)调用函数cdev_del()从系统删除一个cdev结构实例

注:如果把驱动程序制作成一个内核模块,上述的第(2)、(3)、(4)、(5)步应在模块的初始化函数中实现,而第(6)步应在模块的卸载函数中实现

一键创建

register_chrdev(major,fops)) 创建
1、第一个参数静态申请设备号,如果是0,则系统随机分配
2、fops
__unregister_chrdev() 注销

你可能感兴趣的:(创建字符设备)