嵌入式实践教程--【Linux驱动】Linux驱动开发基于Linux4.0+(一)——字符设备驱动

简介: 嵌入式实践教程--【Linux驱动】Linux驱动开发基于Linux4.0+(一)——字符设备驱动

区别于Linux4.0之前的字符设备驱动结构,4.0采用cdev注册字符设备。

一、构造一个字符设备结构体,用于cdev的初始化


struct led_dev_t{
  struct cdev cdev;
};


二、__init 入口函数


1.设备号的处理

dev_t led_devno= MKDEV(led_major,0);


MKDEV(led_major,0)通过主次设备号生成dev_t,在cdev的结构体里面定义了成员dev_t为,32位,12位是主设备号,20位是次设备号。如果不想自己设定主次设备号,可以使用MAJOR(dev_t dev)和MINOR(dev_t dev)生成主次设备号。


if(led_major)
  {
    ret = register_chrdev_region(led_devno, 1,"led");
  }
  else
  {
    ret = alloc_chrdev_region(&led_devno, 0, 1, "led");
    led_major = MAJOR(led_devno);
  }


判断主设备号是否已定义,如果已定义,则注册设备号和设备名;否则申请一个设备号空间然后使用MAJOR(led_devno)生成主设备号。


2.注册字符设备前的准备:申请所需注册设备的结构体空间


ledevp = kzalloc(sizeof(led_dev_t), GFP_KERNEL);  /*申请内存空间*/
  /*判断内存是否申请成功*/
  if(!ledevp)
  {
    ret = -ENOMEM;
    unregister_chrdev_region(led_devno,1);
    return ret;
  }


3.注册字符设备

static void led_setup_cdev(struct led_dev_t *dev,int index)
{
  int err, led_devno = MKDEV(led_major,index);  /*通过主设备号和次设备号生成dev_t*/
  cdev_init(&dev->cdev,&chardev_led_fops);  /*初始化cdev*/
  dev->cdev.owner = THIS_MODULE;
  err = cdev_add(&dev->cdev,led_devno,1);   /*添加一个cdev,param1:cdev,param2:主次设备号*/
  if(err)
  {
    printk(KERN_NOTICE"Error %d adding led %d",err,index);
  }
}


cdev_init初始化cdev,将本驱动的cdev添加进cdev链表


三、字符设备驱动模板


#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/fb.h>
#include <linux/init.h>
#include <linux/gpio.h>
#include <linux/io.h>
#include <linux/cdev.h>
#include <linux/irq.h>
#include <linux/uaccess.h>
#include <linux/of.h>
#include <linux/of_gpio.h>
#define LED_MAJOR 229
static int led_major = LED_MAJOR;
/*设备结构体*/
struct led_dev_t{
  struct cdev cdev;
};
struct led_dev_t *ledevp;
static int led_drv_open(struct inode *inode,struct file *file)
{
  /*设置LED引脚为输出模式*/
}
static ssize_t led_drv_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
{
  /*向引脚写入值*/
  copy_from_user(..,buf,..);//从用户空间获得参数
}
const static struct file_operations chardev_led_fops = {
  .owner = THIS_MODULE,
  .open = led_drv_open,
  .write = led_drv_write
};
static void led_setup_cdev(struct led_dev_t *dev,int index)
{
  int err, led_devno = MKDEV(led_major,index);  /*通过主设备号和次设备号生成dev_t*/
  cdev_init(&dev->cdev,&chardev_led_fops);  /*初始化cdev*/
  dev->cdev.owner = THIS_MODULE;
  err = cdev_add(&dev->cdev,led_devno,1);   /*添加一个cdev,param1:cdev,param2:主次设备号*/
  if(err)
  {
    printk(KERN_NOTICE"Error %d adding led %d",err,index);
  }
}
static int __init  chardev_led_init(void)
{
  int ret;
  dev_t led_devno= MKDEV(led_major,0);    
  /*获取字符设备号*/
  if(led_major)
  {
    ret = register_chrdev_region(led_devno, 1,"led");
  }
  else
  {
    ret = alloc_chrdev_region(&led_devno, 0, 1, "led");
  }
  ledevp = kzalloc(sizeof(led_dev_t), GFP_KERNEL);  /*申请内存空间*/
  /*判断内存是否申请成功*/
  if(!ledevp)
  {
    ret = -ENOMEM;
    unregister_chrdev_region(led_devno,1);
    return ret;
  }
  led_setup_cdev(ledevp,1);       /*设置字符设备*/
  return 0;
}
static void __exit chardev_led_exit(void)
{  
  cdev_del(&ledevp->cdev);        /*删除cdev,释放内存空间*/
  kfree(ledevp);
  unregister_chrdev_region(MKDEV(led_major, 0), 1);
}
module_init(chardev_led_init);
module_exit(chardev_led_exit);
MODULE_AUTHOR(" MUGGLE <1198492751@qq.com>")
MODULE_LICENSE("GPL v2");


相关文章
|
8月前
|
安全 Linux 网络安全
Nipper 3.9.0 for Windows & Linux - 网络设备漏洞评估
Nipper 3.9.0 for Windows & Linux - 网络设备漏洞评估
227 0
Nipper 3.9.0 for Windows & Linux - 网络设备漏洞评估
|
9月前
|
弹性计算 安全 Linux
阿里云服务器ECS安装宝塔Linux面板、安装网站(新手图文教程)
本教程详解如何在阿里云服务器上安装宝塔Linux面板,涵盖ECS服务器手动安装步骤,包括系统准备、远程连接、安装命令执行、端口开放及LNMP环境部署,手把手引导用户快速搭建网站环境。
|
10月前
|
NoSQL 关系型数据库 Linux
ERPNext 搭建教程:Linux 一键部署与维护
ERPNext 是一款开源免费的企业资源计划系统,适用于中小企业信息化管理。基于 Python 和 Frappe 框架开发,支持财务、销售、人力、库存等模块,具备高度可定制性。本文介绍如何通过 Websoft9 在 Linux 下快速部署 ERPNext,并提供环境配置、系统维护等实用建议,适合开发者和企业用户快速上手。
1827 7
ERPNext 搭建教程:Linux 一键部署与维护
|
10月前
|
Java Linux 网络安全
Linux云端服务器上部署Spring Boot应用的教程。
此流程涉及Linux命令行操作、系统服务管理及网络安全知识,需要管理员权限以进行配置和服务管理。务必在一个测试环境中验证所有步骤,确保一切配置正确无误后,再将应用部署到生产环境中。也可以使用如Ansible、Chef等配置管理工具来自动化部署过程,提升效率和可靠性。
955 13
|
9月前
|
数据采集 编解码 运维
一文讲完说懂 WowKey -- WowKey 是一款 Linux 类设备的命令行(CLT)运维工具
WowKey 是一款面向 Linux 类设备的命令行运维工具,支持自动登录、批量执行及标准化维护,适用于企业、团队或个人管理多台设备,显著提升运维效率与质量。
|
9月前
|
Ubuntu 网络协议 Unix
Linux教程(Ubuntu为蓝本)之Linux介绍篇
SuSE嫁到了Novell,SCO继续顶着骂名四处强行“化缘”, Asianux, MandrakeSoft也在五年中首次宣布季度赢利。3月,SGI宣布成功实现了Linux操作系统支持256个Itanium 2处理器。[1-2]
|
9月前
|
Ubuntu Linux 数据安全/隐私保护
Win10安装Linux子系统教程!如何在Win10系统中安装Ubuntu!
登录系统后,输入cd /返回上一级,然后再输入“ls”查看一下系统文件目录,看看对不对!
|
10月前
|
监控 Linux 开发者
理解Linux操作系统内核中物理设备驱动(phy driver)的功能。
综合来看,物理设备驱动在Linux系统中的作用是至关重要的,它通过与硬件设备的紧密配合,为上层应用提供稳定可靠的通信基础设施。开发一款优秀的物理设备驱动需要开发者具备深厚的硬件知识、熟练的编程技能以及对Linux内核架构的深入理解,以确保驱动程序能在不同的硬件平台和网络条件下都能提供最优的性能。
542 0
|
11月前
|
关系型数据库 Linux 数据库
Linux系统安装Postgre和Postgis教程
本文详细介绍了PostgreSQL/PostGIS的卸载与安装步骤。卸载部分涵盖Docker、Yum/RPM及源码编译安装的清理方法,包括停止服务、删除容器/包、清理残留文件和环境变量等操作,并强调卸载前需备份数据库数据。安装部分提供在线yum安装和离线源码编译两种方式,前者简单快捷,后者需准备依赖(如gcc、readline-devel等)、创建用户组、初始化数据库及配置访问规则。每步均附带命令示例,确保操作清晰明确。
1615 0
|
8月前
|
Linux 应用服务中间件 Shell
二、Linux文本处理与文件操作核心命令
熟悉了Linux的基本“行走”后,就该拿起真正的“工具”干活了。用grep这个“放大镜”在文件里搜索内容,用find这个“探测器”在系统中寻找文件,再用tar把东西打包带走。最关键的是要学会使用管道符|,它像一条流水线,能把这些命令串联起来,让简单工具组合出强大的功能,比如 ps -ef | grep 'nginx' 就能快速找出nginx进程。
919 1
二、Linux文本处理与文件操作核心命令