字符设备驱动代码的编写

简介: 传统方法,优点简单缺点就是不易宽展,硬件更换了板子都要重新写代码重新比编译,硬件的每次改动都要重新修改软件版本增加工作量。

字符设备驱动框架


linux/cdev.h


  cdev结构体:  操作方法集    设备号(主设备号+次设备号)    
  围绕cdev结构体进行的一系列操作:
  0.申请/注册设备号    
  1.分配cdev结构体    
  2.初始化结构体    
  3.添加cdev到内核 


编写驱动程序的三种方法

一:传统方法,优点简单缺点就是不易宽展,硬件更换了板子都要重新写代码重新比编译,硬件的每次改动都要重新修改软件版本增加工作量。


二: 总线设备驱动模型,将驱动分为两部分,device和driver两部分挂在platform总线上,device负责指定资源,如管脚等。对于相同的硬件操作driver部分都是相同的,硬件只需要编写相应的device代码来指定硬件资源即可。这种方法稍微复杂,但是易扩展,冗余代码多且以代码的形式出现。


三: 设备树。仍然是分为两部分,一是xxx_driver.c跟总线设备驱动模型一样,二是设备树文件xxx.dts文件来指定文件,内核根据这个文件来构造xxx_device文件,运行时去读取解析xxx.dts文件。优点是比传统方法稍复杂,容易扩展,没有冗余代码,不需要重新编译内核或者驱动只需要提供不一样的设备树文件。


字符设备驱动代码的编写*


#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/cdev.h>
#include <linux/fs.h>
#define BASEMINOR 0
#define COUNT     3
#define NAME      "cdev_demo"
dev_t devno = 0;
struct cdev *cdevp = NULL;
int demo_open(struct inode *inode, struct file *filp){
  printk(KERN_DEBUG "---%s---%s---%d---\n",__FILE__,__func__,__LINE__); 
  return 0;
  }
  int demo_release(struct inode *inode, struct file *filp){ 
  printk(KERN_DEBUG "---%s---%s---%d---\n",__FILE__,__func__,__LINE__); 
  return 0;
  }
  struct file_operations fops = { .owner    = THIS_MODULE,  .open     = demo_open,  .release  = demo_release,};
  int __init demo_init(void){ int ret = 0;  
  //0.申请设备号-内核分配主设备号,次设备好从0开始,共三个(0,1,2)  
  ret = alloc_chrdev_region(&devno,BASEMINOR,COUNT, NAME);  
  if(ret < 0)
  {   
  printk(KERN_ERR "alloc_chrdev_region failed...\n");   
  goto err0;  
  } 
  printk(KERN_INFO "---major:%d---\n",MAJOR(devno));  
  //1.分配cdev结构体 
  cdevp = cdev_alloc(); 
  if(cdevp == NULL)
  {   
  printk(KERN_ERR "cdev_alloc failed...\n");    
  ret = -ENOMEM;    
  goto err1;      
  } 
  //2.初始化cdev结构体  
  cdev_init(cdevp, &fops);
  //3.将cdev结构体添加到内核中,由内核对驱动进行统一的管理  
  ret = cdev_add(cdevp, devno, COUNT);  
  if(ret < 0){    
  printk(KERN_ERR "cdev_add failed...\n");    
  goto err1;  
  } 
  printk(KERN_DEBUG "---%s---%s---%d---\n",__FILE__,__func__,__LINE__); 
  return 0;err1:  
  unregister_chrdev_region(devno, COUNT);err0:  
  return ret;}void __exit demo_exit(void){  
  cdev_del(cdevp);  
  unregister_chrdev_region(devno, COUNT); 
  printk(KERN_DEBUG "---%s---%s---%d---\n",__FILE__,__func__,__LINE__);
  }
  module_init(demo_init);module_exit(demo_exit);MODULE_LICENSE("GPL");


相关文章
|
6月前
|
编译器 Linux C++
3C++程序的编写和实现
3C++程序的编写和实现
54 2
|
6月前
|
Linux C语言 Ubuntu
Linux驱动入门——编写第一个驱动
Linux驱动入门——编写第一个驱动
Linux驱动入门——编写第一个驱动
|
6月前
|
Linux
Linux 驱动开发基础知识——编写LED驱动程序(三)
Linux 驱动开发基础知识——编写LED驱动程序(三)
95 0
Linux 驱动开发基础知识——编写LED驱动程序(三)
|
6月前
|
敏捷开发 设计模式 Unix
嵌入式C语言代码的基本编写规范要求
嵌入式C语言代码的基本编写规范要求
145 0
|
算法 Linux C语言
Linux驱动中常用的一些接口函数
Linux驱动中常用的一些接口函数
|
Linux 编译器
Linux设备驱动---字符设备驱动接口函数
Linux设备驱动---字符设备驱动接口函数
170 1
|
Unix Linux 编译器
编写Linux设备驱动程序的注意事项
编写Linux设备驱动程序的注意事项
|
Linux
linux驱动---platform框架的按键驱动
linux驱动---platform框架的按键驱动
160 0
|
芯片
LED驱动程序外部框架
LED驱动程序外部框架
71 0
|
Linux 编译器 C语言
Linux驱动开发笔记(一):helloworld驱动源码编写、makefile编写以及驱动编译基本流程
基于linux的驱动开发学习笔记,本篇是描述了一个字符驱动的基础开发流程,以便做嵌入式开发多年的应用或者系统学习驱动开发。