字符设备驱动开发-注册-设备文件创建

一、字符设备驱动

linux系统中一切皆文件

1、应用层: APP1 APP2 ...

fd = open("led驱动的文件",O_RDWR);

read(fd);

write();

close();

2、内核层:

对灯写一个驱动

led_driver.c

driver_open();

driver_read();

driver_write();

driver_close();

struct file_operations

{

int (*open) (struct inode *, struct file *);

ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);

ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);

int (*release) (struct inode *, struct file *);//(close)

}

cdev:

设备号1 设备号2 设备号n

设备驱动1 设备驱动2 .... 设备驱动n

设备号:32位,无符号数字

高12位 :主设备号 :区分哪一类设备

低20位 :次设备号 :区分同类中哪一个设备

3、硬件层: LED uart ADC PWM

每个驱动里面都有对应的file_operations

1)open的过程:

open打开文件,这个文件与底层的驱动的设备号有关系,

通过设备号访问设备驱动中的struct file_operations里面的open函数。

2)read的过程:

open函数会有一个返回值,文件描述符fd,read函数通过fd

找到驱动中的struct file_operations里面的read函数。

Led驱动:字符设备 步骤:
  1. 注册字符设备驱动 - 得到一个字符设备驱动的框架,并且得到设备号
  2. 确定操作的硬件设备 - led灯(初始化灯)
  3. 初始化灯(先建立灯实际物理地址和虚拟地址之间的映射)-
  4. 基于操作系统开发,操作虚拟内存,
  5. 用户空间数据拷贝到内核空间数据的交互(用户使用的时候,驱动才会被真正运行,涉及数据交互)
  6. 在应用层创建一个设备文件(设备节点)
file_operations 操作方法结构体

struct file_operations

{

int (*open) (struct inode *, struct file *);

ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);

ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);

int (*release) (struct inode *, struct file *);//(close)

}

二、字符设备驱动的注册

1、注册一个字符设备驱动 register_chrdev

复制代码
int` `register_chrdev(unsigned int major,` `const` `char` `*name,` `const` `struct file_operations *fops)`
`功能:注册一个字符设备驱动`
`参数:`
	`@major:主设备号  `
`			  :如果你填写的值大于0,它认为这个就是主设备号`
`			  :如果你填写的值为0,操作系统给你分配一个主设备号`
	`@name` `:名字	cat /proc/devices `
    `@fops` `:操作方法结构体`
`返回值:major>0` `,成功返回0,失败返回错误码(负数) vi -t EIO`
`		major=0,成功主设备号,失败返回错误码(负数)		  `

`当注册一个字符设备驱动的时候。

如果成功的话,当你使用cat /proc/devices 命令查看的时候可以看到系统自动分配的主设备号和这个名字

2、 注销一个字符设备驱动

复制代码
void` `unregister_chrdev(unsigned int major,` `const` `char` `*name)`
`	功能:注销一个字符设备驱动`
`	参数:`
		`@major:主设备号`
		`@name:名字`
`	返回值:无`
`

三、手动创建设备文件 mknod

sudo mknod led (路径是任意) c/b 主设备号 次设备号

sudo --rf led 删除的时候记得加-rf

1、设备驱动程序

复制代码
#include <linux/module.h>`
`#include <linux/init.h>`
`#include <linux/printk.h>`
`#include <linux/fs.h>`

`#define NAME "chrdev_devled"`

`int major =` `0;` `//保存主设备号`
`// open read write release 初始化`
`int` `myopen(struct` `inode` `*node,` `struct` `file` `*file_t)`
`{`
    `printk("%s %s %d\n",` `__FILE__,` `__func__,` `__LINE__);`
    `return` `0;`
`}`
`ssize_t` `myread(struct` `file` `*file_t,` `char __user *ubuf,` `size_t n,` `loff_t` `*off_t)`
`{`
    `printk("%s %s %d\n",` `__FILE__,` `__func__,` `__LINE__);`
    `return` `0;`
`}`
`ssize_t` `mywrite(struct` `file` `*file_t,` `const` `char __user *ubuf,` `size_t n,` `loff_t` `*off_t)`
`{`
    `printk("%s %s %d\n",` `__FILE__,` `__func__,` `__LINE__);`
    `return` `0;`
`}`
`int` `myclose(struct` `inode` `*node,` `struct` `file` `*file_t)`
`{`
    `printk("%s %s %d\n",` `__FILE__,` `__func__,` `__LINE__);`
    `return` `0;`
`}`
`struct` `file_operations fops =` `{`
    `.open = myopen,`
    `.read = myread,`
    `.write = mywrite,`
    `.release = myclose,`
`};`
`//入口函数`
`static` `int __init chrdev_init(void)`
`{`
    `printk("%s %s %d\n",` `__FILE__,` `__func__,` `__LINE__);`
    `//注册字符设备驱动: 主设备号 驱动名 结构体`
`    major=register_chrdev(major, NAME,` `&fops);`
    `//容错判断`
    `if(major <` `0)`
    `{`
        `printk("chrdev_register err.\n");`
        `return` `-EINVAL;`
    `}`
    `return` `0;`
`}`
`//出口函数`
`static` `void __exit chrdev_exit(void)`
`{`
    `printk(KERN_ERR "%s %s %d\n",` `__FILE__,` `__func__,` `__LINE__);`
    `//注销字符设备驱动`
    `unregister_chrdev(major, NAME);`
`}`
`module_init(chrdev_init);//入口`
`module_exit(chrdev_exit);//出口`
`MODULE_LICENSE("GPL");//协议`
`

2、应用层读取程序

复制代码
#include <sys/types.h>`
`#include <sys/stat.h>`
`#include <fcntl.h>`
`#include <unistd.h>`
`#include <sys/ioctl.h>`
 
`#include <stdio.h>`
 
 
`int main(int argc,char *argv[])`
`{`
`    int fd =` `-1;`
`    char buf[32]` `=` `"";`
    `if(argc <` `2)`
    `{`
`        printf("请输入要打开的文件\n");`
        `return` `1;`
    `}`
 
`    fd = open(argv[1],O_RDWR);`
    `if(fd <` `0)`
    `{`
`        printf("open %s failed\n",argv[1]);`
        `return` `2;`
    `}`
`    read(fd,buf,sizeof(buf));`
`    write(fd,buf,sizeof(buf));`
`    read(fd,buf,sizeof(buf));`
`    write(fd,buf,sizeof(buf));`
`    printf("buf=%s\n",buf);`
`    close(fd);`
`    fd =` `-1;`
    `return` `0;`
`}`
`

3、操作步骤:

--make 驱动文件

--insmod 安装驱动

--cat /proc/devicse 查看设备号

--sudo mknod led c 244 0 创建设备文件(设备节点)

--dmesg 查看消息

--sudo dmesg -C删除消息

--sudo gcc app.c 编译应用层读取文件

--./app .led读取

--led--dmesg 查看消息

相关推荐
IT阳晨。6 小时前
【STM32】天气预报项目
stm32·单片机·嵌入式硬件
kylezhao20197 小时前
C# 语言基础(变量、数据类型、流程控制、面向对象编程)
开发语言·计算机视觉·c#·visionpro
翩若惊鸿_8 小时前
【无标题】
开发语言·c#
IT阳晨。8 小时前
【STM32】智能台灯项目
stm32·单片机·嵌入式硬件
搬砖的工人8 小时前
写了一个IIS监控工具,对付“假死“后自动重启站点
c#
炸膛坦客9 小时前
Cortex-M3-STM32F1 开发:(三十九)DMA详细介绍(3):相关寄存器、库函数介绍,配置步骤,以及内存到内存和内存到外设的实例
stm32·单片机·嵌入式硬件
landyjzlai10 小时前
AMBA总线(15)关于AXI-stream(sg模式)
arm开发·fpga开发·amba
红黑色的圣西罗12 小时前
对象池简述
unity·c#
水龙吟啸12 小时前
基于Orbbec-Gemini深度相机与SFM-2D to 3D重建算法、手部识别视觉算法、Unity运动控制的3D水果切割游戏
python·深度学习·神经网络·c#·游戏引擎·3d视觉·3d重建
polarislove021413 小时前
9.6 [定时器]超声波测距实验-嵌入式铁头山羊STM32笔记
笔记·stm32·嵌入式硬件