一、字符设备驱动
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驱动:字符设备 步骤:
- 注册字符设备驱动 - 得到一个字符设备驱动的框架,并且得到设备号
- 确定操作的硬件设备 - led灯(初始化灯)
- 初始化灯(先建立灯实际物理地址和虚拟地址之间的映射)-
- 基于操作系统开发,操作虚拟内存,
- 用户空间数据拷贝到内核空间数据的交互(用户使用的时候,驱动才会被真正运行,涉及数据交互)
- 在应用层创建一个设备文件(设备节点)
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 查看消息
