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");

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

目录
打赏
0
0
0
0
44
分享
相关文章
|
7天前
|
Linux系统之whereis命令的基本使用
Linux系统之whereis命令的基本使用
50 23
Linux系统之whereis命令的基本使用
|
2月前
|
Linux缓存管理:如何安全地清理系统缓存
在Linux系统中,内存管理至关重要。本文详细介绍了如何安全地清理系统缓存,特别是通过使用`/proc/sys/vm/drop_caches`接口。内容包括清理缓存的原因、步骤、注意事项和最佳实践,帮助你在必要时优化系统性能。
231 78
Linux系统查看操作系统版本信息、CPU信息、模块信息
在Linux系统中,常用命令可帮助用户查看操作系统版本、CPU信息和模块信息
111 23
嵌入式Linux系统编程 — 5.3 times、clock函数获取进程时间
在嵌入式Linux系统编程中,`times`和 `clock`函数是获取进程时间的两个重要工具。`times`函数提供了更详细的进程和子进程时间信息,而 `clock`函数则提供了更简单的处理器时间获取方法。根据具体需求选择合适的函数,可以更有效地进行性能分析和资源管理。通过本文的介绍,希望能帮助您更好地理解和使用这两个函数,提高嵌入式系统编程的效率和效果。
121 13
Linux 超级强大的十六进制 dump 工具:XXD 命令,我教你应该如何使用!
在 Linux 系统中,xxd 命令是一个强大的十六进制 dump 工具,可以将文件或数据以十六进制和 ASCII 字符形式显示,帮助用户深入了解和分析数据。本文详细介绍了 xxd 命令的基本用法、高级功能及实际应用案例,包括查看文件内容、指定输出格式、写入文件、数据比较、数据提取、数据转换和数据加密解密等。通过掌握这些技巧,用户可以更高效地处理各种数据问题。
344 8
|
3月前
|
如何检查 Linux 内存使用量是否耗尽?这 5 个命令堪称绝了!
本文介绍了在Linux系统中检查内存使用情况的5个常用命令:`free`、`top`、`vmstat`、`pidstat` 和 `/proc/meminfo` 文件,帮助用户准确监控内存状态,确保系统稳定运行。
1131 6
|
3月前
|
在 Linux 系统中,“cd”命令用于切换当前工作目录
在 Linux 系统中,“cd”命令用于切换当前工作目录。本文详细介绍了“cd”命令的基本用法和常见技巧,包括使用“.”、“..”、“~”、绝对路径和相对路径,以及快速切换到上一次工作目录等。此外,还探讨了高级技巧,如使用通配符、结合其他命令、在脚本中使用,以及实际应用案例,帮助读者提高工作效率。
197 3
在 Linux 系统中,网络管理是重要任务。本文介绍了常用的网络命令及其适用场景
在 Linux 系统中,网络管理是重要任务。本文介绍了常用的网络命令及其适用场景,包括 ping(测试连通性)、traceroute(跟踪路由路径)、netstat(显示网络连接信息)、nmap(网络扫描)、ifconfig 和 ip(网络接口配置)。掌握这些命令有助于高效诊断和解决网络问题,保障网络稳定运行。
144 2
深入解析:Linux网络配置工具ifconfig与ip命令的全面对比
虽然 `ifconfig`作为一个经典的网络配置工具,简单易用,但其功能已经不能满足现代网络配置的需求。相比之下,`ip`命令不仅功能全面,而且提供了一致且简洁的语法,适用于各种网络配置场景。因此,在实际使用中,推荐逐步过渡到 `ip`命令,以更好地适应现代网络管理需求。
34 11
|
2月前
|
Linux 10 个“who”命令示例
Linux 10 个“who”命令示例
100 14
Linux 10 个“who”命令示例