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

一、字符设备驱动

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 查看消息

相关推荐
CQ_YM12 分钟前
ARM中断
arm开发·嵌入式硬件·arm
曹牧16 分钟前
C#:WebReference
开发语言·c#
C#程序员一枚20 分钟前
C#AsNoTracking()详解
开发语言·c#
羽获飞21 分钟前
51单片机UART-串口通讯的配置方法
stm32·单片机·嵌入式硬件
猫猫的小茶馆23 分钟前
【Linux 驱动开发】一. 搭建开发环境
linux·汇编·arm开发·驱动开发·stm32·嵌入式硬件·mcu
猫猫的小茶馆1 小时前
【Linux 驱动开发】嵌入式 Linux 开发概念
linux·服务器·arm开发·stm32·单片机·嵌入式硬件·mcu
EVERSPIN1 小时前
单片机CH554电容触摸屏控制器方案
单片机·嵌入式硬件·单片机ch554
容测电子1 小时前
ISO 11452-4:大电流注入BCI,从原理到校准
经验分享·嵌入式硬件·汽车·电磁兼容·emc测试·emc测试设备
兆龙电子单片机设计1 小时前
【STM32项目开源】STM32单片机智能宠物喂养系统
stm32·单片机·开源·毕业设计·电子信息
明月看潮生1 小时前
编程与数学 03-008 《看潮企业管理软件》项目开发 01 需求分析 3-1
c#·.net·需求分析·erp·企业开发·项目实践·编程与数学