IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 系统运维 -> Linux驱动学习记录-字符设备驱动 -> 正文阅读

[系统运维]Linux驱动学习记录-字符设备驱动

????????字符设备是Linux驱动中最基本的一类设备驱动,字符设备就是一个一个字节,按照字节流进行读写操作,读写数据分先后顺序。比如常见的点灯,按键,IIC,LCD等。

???????? 加载/卸载函数

????????加载/卸载函数module_init(XXX_init), module_exit(XXX_exit),其中XXX_init和XXX_exit是需要自己编写的函数,当执行命令”insmod”和”remod”会加载/卸载驱动时,会调用上面两个函数。模板如下:

static int __init XXX_init(void)
{
    /*入口函数的内容*/
    return 0;
}

static void __exit XXX_exit(void)
{
    /*出口函数的内容*/
}

module_init(XXX_init);
module_exit(XXX_exit);

????????其中static表示静态函数,与普通函数的区别:在函数的返回类型前加修饰词static,这个函数就变成静态函数,此函数只能在声明他的文件里使用,不能被其他文件调用。而普通函数的定义和声明默认是extern的。好处是在其他文件中可以定义同名函数而不会有冲突。

????????__init和__exit修饰符:给内核的暗示,表示此函数只是初始化函数,在初始化完毕后可以丢掉,释放内存;标识这个函数只用于模块卸载,只有在卸载时才会调用,其他任何时刻调用都会出错。

????????字符设备的注册和注销????????

????????字符设备的注册和注销,static inline int register_chrdev(unsigned int major, const char *name, const struct file_operations *fops)和static inline void unregister_chrdev(unsigned int major, const char *name)。

  • major:主设备,Linux下每一个设备都有一个设备号。Linux设备号范围0~4095,有主号就有次号,后面会说。
  • name:设备名称,字符串。
  • fops:结构体file_operations类型的指针,指向设备操作函数的集合变量。此结构体存放函数包括read(),write(),open()等等。
static struct file_operations test_fops;

static int __int XXX_init(void)
{
    /*注册字符设备驱动*/
    int temp = 0;
    temp = register_chrdev(200, "test", &test_fops)
    if(temp < 0)
    {
        printk("register error!");
    }
    return 0;
}

static void __exit XXX_exit(void)
{
    /*注销字符设备驱动*/
    unregister_chrdev(200, "test");
}

????????上面是采用静态分配设备号的方法,即注册的时候指定一个数字作为设备号。但是你不知道这个设备号是否已经被使用(通过命令 "cat /proc/devices"可以查看系统已经使用的设备号)。下面介绍动态分配设备号的方法:在注册设备之前先申请一个设备号,系统会自动给你一个没有使用的设备号,避免冲突,卸载驱动的时候要释放这个设备号。推荐使用动态分配,虽然可能会复杂一些。

??????? 申请和释放设备号函数int alloc_chrdev_region(dev_t *dev, unsigned baseminor, unsigned count, const char *name)和void unregister_chrdev_region(dev_t from, unsigned count)。

  • dev:保存申请到的设备号。
  • baseminor:次设备号起始地址。一般为0.
  • count:要申请的设备号数量。
  • name:设备名字。
int major;
int minor;
dev_t devid;  //设备号结构体,"猜测是含有俩个unsigned int变量的结构体"

if(major) //如果major有效
{    
    devid = MKDEV(major, 0);  //定义设备号,次设备号一般是0
    /*MKDEV是将主设备和次设备号转换为dev_t类型的内核函数*/
    register_chrdev_region(devid, 1, "test"); //申请设备号
}
else  //无效
{
    alloc_chrdev_region(&devid, 0, 1, "test"); //申请设备号
    major = MAJOR(devid);  //获取主号
    minor = MINOR(devid);  //获取次号
}

unregister_chrdev_region(devid, 1); //注销设备号,简单

里面多了一个函数int register_chrdev_region(dev_t from, unsigned count, const char *name),如果有主号和次号就用这个函数申请。(既然有设备号了,为啥不直接调用函数register_chrdev,进行设备注册,不太懂)

????????设备具体操作函数

??????? 设备具体操作函数,file_operations结构体是具体的设备操作函数。假设这里的test设备控制一段缓冲区(内存),则要有read和write函数进行读写。

/*打开设备需要做的*/
/*
inode:传递给驱动的inode
filp:设备文件,file结构体结构体有个叫做 private_data 的成员变量,一般在 open 的时候将private_data 指向设备结构体。
*/
static int test_open (struct inode *inode, struct file *filp)
{
    /**/
    return 0;
}

/*从设备读取*/
/*
filp:要打开的设备
buf:返回给用户空间的数据缓冲区
cnt:要读取的数据长度
offt:相对于文件首地址的偏移
*/
static ssizet_t test_read (struct file *filp, char __user *buf, size_t cnt, loff_t *offt)
{
    /**/
    return 0;
}

/*写设备*/
static ssize_t test_write (struct file *filp, const char __user *buf, size_t cnt, loff_t *offt)
{
    /**/
    return 0;
}

/*释放设备*/
static int test_release(struct inode *inode, struct file *filp)
{
    /**/
    return 0;
}

/*设备操作函数结构体*/
static sturct file_operations test_fops = {
    .owner = THIS_MODULE,
    .open = test_open,
    .read = test_read,
    .write = test_write,
    .release = test_release,
};

??????? 添加信息

????????添加信息。在最后要添加LICENSE信息和作者信息。其中LICENSE是必须的,否则编译出错。示例如下:

module_init(XXX_init);
module_exit(XXX_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("GaoXu");

  系统运维 最新文章
配置小型公司网络WLAN基本业务(AC通过三层
如何在交付运维过程中建立风险底线意识,提
快速传输大文件,怎么通过网络传大文件给对
从游戏服务端角度分析移动同步(状态同步)
MySQL使用MyCat实现分库分表
如何用DWDM射频光纤技术实现200公里外的站点
国内顺畅下载k8s.gcr.io的镜像
自动化测试appium
ctfshow ssrf
Linux操作系统学习之实用指令(Centos7/8均
上一篇文章      下一篇文章      查看所有文章
加:2021-09-12 13:32:23  更:2021-09-12 13:33:10 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年12日历 -2024/12/30 3:33:40-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码