linux系统中字符设备驱动开发方法

简介: linux系统中字符设备驱动开发方法

第一:字符设备驱动简介

      字符设备是Linux驱动中最基本的一类设备驱动,字符设备就是一个一个字节,按照字节流进行读写操作的设备,读写数据是分先后顺序的,比如我们常见的点灯、IIC、SPI等都是字符设备,这些设备的驱动叫做字符设备驱动。

       在详细的学习字符设备驱动架构之前,我们先来简单的了解一下 Linux 下的应用程序是如

何调用驱动程序的,Linux 应用程序对驱动程序的调用如下:

   

分析:

应用程序运行在用户空间,而 Linux 驱动属于内核的一部分,因此驱动运行于内核空间。

当我们在用户空间想要实现对内核的操作,比如使用 open 函数打开/dev/led 这个驱动,因为用

户空间不能直接对内核进行操作,因此必须使用一个叫做“系统调用”的方法来实现从用户空

间“陷入”到内核空间,这样才能实现对底层驱动的操作。openclosewrite read 等这些函

数是由 C 库提供的,在 Linux 系统中,系统调用作为 C 库的一部分。当我们调用 open 函数的

时候流程如图:

第二:字符设备驱动开发步骤

       

     在linux驱动开发中肯定要初始化相应的外设寄存器,只是在linux驱动开发中,需要根据规定的框架来编写驱动,所以学linux驱动开发重点是学习框架。

     linux驱动有两种运行方式,第一种就是将驱动编译进linux内核中,这样当linux内核启动的时候就会自动运行驱动程序。第二种将驱动编译成模块(linux下模块扩展名为.ko),在linux内核启动以后使用insmod命令加载驱动模块。

      模块的加载和卸载函数注册函数如下:

     

module_init(xxx_init);    //注册模块加载函数
module_exit(xxx_exit);    //注册模块卸载函数

      module_init 函数用来向 Linux 内核注册一个模块加载函数,参数 xxx_init 就是需要注册的具体函数,当使用“insmod”命令加载驱动的时候,xxx_init 这个函数就会被调用。module_exit() 函数用来向 Linux 内核注册一个模块卸载函数,参数 xxx_exit 就是需要注册的具体函数,当使 用“rmmod”命令卸载具体驱动的时候 xxx_exit 函数就会被调用。

第三:编写字符设备驱动实验程序

#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/ide.h>
#include <linux/init.h>
#include <linux/module.h>
//声明对应的变量
#define CHRDEVBASE_MAJOR    200     //主设备号
#define CHRDEVBASE_NAME     "chrdevbase"
static char  readbuf[100];    //读缓冲区
static char  writebuf[100];   //写缓冲区
static char  kerneldata[]={"kernel data!"};
//打开设备
static int chrdevbase_open(struct inode *inode,struct file *file)
{
    return 0;
}
//从设备读取数据   filp---要打开的设备文件(文件描述符)
static ssize_t chrdevbase_read(struct file *filp,char __user *buf,size_t cnt,loff_t *offt)
{
    int retvalue = 0;
    //向用户空间发送数据
    memcpy(readbuf,kerneldata,sizeof(kerneldata));
    retvalue = copy_to_user(buf,readbuf,cnt);
   if(retvalue == 0){
        printk("kernel senddata ok!\r\n");
   }else {
       printk("kernel senddata failed\r\n");
  }
    return 0;
}
//向设备中写数据
static ssize_t chrdevbase_write(struct file *filp,const char __user *buf,size_t cnt, loff_t *offt )
{
    int retvalue = 0;
    //接收用户空间传递给内核的数据并且打印出来
    retvalue = copy_from_user(writebuf,buf,cnt);
    if(retvalue == 0)
    {
       printk("kernel recevdata:%s\r\n",writebuf);  
    }else
    {
       printk("kernel recevdata failed!\r\n");
    }
      return 0;
}
//关闭释放设备
static int chrdevbase_release(struct inode *inode,struct file *filp)
{
    return 0;
}
//设备操作函数结构体
static struct file_operations chrdevbase_fops = {
    .owner = THIS_MODULE, 
    .open = chrdevbase_open,
    .read = chrdevbase_read,
    .write = chrdevbase_write,
    .release = chrdevbase_release, 
};
//驱动入口函数
static int __init chrdevbase_init(void)
{
    int retvalue =0 ;
    //注册字符设备驱动
    retvalue = register_chrdev(CHRDEVBASE_MAJOR, CHRDEVBASE_NAME,&chrdevbase_fops);
    return 0;
}
//驱动出口函数
static void __exit chrdevbase_exit(void)
{
   /* 注销字符设备驱动 */
     unregister_chrdev(CHRDEVBASE_MAJOR, CHRDEVBASE_NAME);
     printk("chrdevbase_exit()\r\n"); 
}
//将上面两个函数指定为驱动的入口函数和出口函数
module_init(chrdevbase_init);
module_exit(chrdevbase_exit);
MODULE_LINCENSE("GPL");

总结:本次实验详细描述了字符设备驱动的开发过程,带领大家完成了第一个字符设备驱动的开发。

相关文章
Linux系统资源管理:多角度查看内存使用情况。
要知道,透过内存管理的窗口,我们可以洞察到Linux系统运行的真实身姿,如同解剖学家透过微观镜,洞察生命的奥秘。记住,不要惧怕那些高深的命令和参数,他们只是你掌握系统"魔法棒"的钥匙,熟练掌握后,你就可以骄傲地说:Linux,我来了!
67 27
|
9天前
|
Linux系统ext4磁盘扩容实践指南
这个过程就像是给你的房子建一个新的储物间。你需要先找到空地(创建新的分区),然后建造储物间(格式化为ext4文件系统),最后将储物间添加到你的房子中(将新的分区添加到文件系统中)。完成这些步骤后,你就有了一个更大的储物空间。
61 10
Android调试终极指南:ADB安装+多设备连接+ANR日志抓取全流程解析,覆盖环境变量配置/多设备调试/ANR日志分析全流程,附Win/Mac/Linux三平台解决方案
ADB(Android Debug Bridge)是安卓开发中的重要工具,用于连接电脑与安卓设备,实现文件传输、应用管理、日志抓取等功能。本文介绍了 ADB 的基本概念、安装配置及常用命令。包括:1) 基本命令如 `adb version` 和 `adb devices`;2) 权限操作如 `adb root` 和 `adb shell`;3) APK 操作如安装、卸载应用;4) 文件传输如 `adb push` 和 `adb pull`;5) 日志记录如 `adb logcat`;6) 系统信息获取如屏幕截图和录屏。通过这些功能,用户可高效调试和管理安卓设备。
|
2月前
|
Linux系统之whereis命令的基本使用
Linux系统之whereis命令的基本使用
105 24
Linux系统之whereis命令的基本使用
|
21天前
|
Linux系统中如何查看CPU信息
本文介绍了查看CPU核心信息的方法,包括使用`lscpu`命令和读取`/proc/cpuinfo`文件。`lscpu`能快速提供逻辑CPU数量、物理核心数、插槽数等基本信息;而`/proc/cpuinfo`则包含更详细的配置数据,如核心ID和处理器编号。此外,还介绍了如何通过`lscpu`和`dmidecode`命令获取CPU型号、制造商及序列号,并解释了CPU频率与缓存大小的相关信息。最后,详细解析了`lscpu`命令输出的各项参数含义,帮助用户更好地理解CPU的具体配置。
61 8
深度体验阿里云系统控制台:SysOM 让 Linux 服务器监控变得如此简单
作为一名经历过无数个凌晨三点被服务器报警电话惊醒的运维工程师,我对监控工具有着近乎苛刻的要求。记得去年那次大型活动,我们的主站流量暴增,服务器内存莫名其妙地飙升到90%以上,却找不到原因。如果当时有一款像阿里云 SysOM 这样直观的监控工具,也许我就不用熬通宵排查问题了。今天,我想分享一下我使用 SysOM 的亲身体验,特别是它那令人印象深刻的内存诊断功能。
|
11天前
|
微服务2——MongoDB单机部署4——Linux系统中的安装启动和连接
本节主要介绍了在Linux系统中安装、启动和连接MongoDB的详细步骤。首先从官网下载MongoDB压缩包并解压至指定目录,接着创建数据和日志存储目录,并配置`mongod.conf`文件以设定日志路径、数据存储路径及绑定IP等参数。之后通过配置文件启动MongoDB服务,并使用`mongo`命令或Compass工具进行连接测试。此外,还提供了防火墙配置建议以及服务停止的两种方法:快速关闭(直接杀死进程)和标准关闭(通过客户端命令安全关闭)。最后补充了数据损坏时的修复操作,确保数据库的稳定运行。
41 0
Linux系统查看操作系统版本信息、CPU信息、模块信息
在Linux系统中,常用命令可帮助用户查看操作系统版本、CPU信息和模块信息
209 23
|
3天前
|
linux命令详细说明以及案例
本文介绍了常用的 Linux 命令及其详细说明和示例,包括:`ls`(列出目录内容)、`cd`(更改目录)、`rm` 和 `mv`(删除与移动文件)、`grep`(搜索文本)、`cat`(显示文件内容)以及 `chmod`(更改文件权限)。每个命令均配有功能描述、选项说明及实际案例,帮助用户更好地掌握 Linux 命令的使用方法。
82 56
|
5天前
|
Linux基础:文件和目录类命令分析。
总的来说,这些基础命令,像是Linux中藏匿的小矮人,每一次我们使用他们,他们就把我们的指令准确的传递给Linux,让我们的指令变为现实。所以,现在就开始你的Linux之旅,挥动你的命令之剑,探索这个充满神秘而又奇妙的世界吧!
49 19

热门文章

最新文章