设备驱动大致骨架
驱动代码.c文件
#include<linux/module.h>
#include<linux/init.h>
#include <linux/slab.h>//使用kmalloc就需要include
static unsigned char men[100000];
//设备文件file,buf数据位置,count可读字节数,ppos偏移量
static ssize_t 驱动读函数(struct file *file,char *buf,size_t count,loff_t *ppos){
copy_to_user(buf,(void*)mem,written_count);
return written_count;
}
//设备文件file,buf数据,count可写字节数,ppos偏移量
static ssize_t 驱动写函数(struct file *file,char *buf,size_t count,loff_t *ppos){
copy_from_user(mem,buf,count);
return count;
}
#define DEVICE_NAME "驱动名字"
static struct file_operations dev_fops =
{
.owner=THIS_MODULE,
.read=驱动读函数,
.write=驱动写函数,
……其他操作比如poll,ioctl
} ;
static struct miscdecice misc=
{
.minor = MISC_DYNAMIC_MINOR,
.name = DEVICE_NAME,
.fops = &dev_fops
};
int 初始化驱动函数()
{
printk(打印内核日志信息);
//atoi(用户空间) simple_strtol(内核空间)
//itoa(用户空间) snprintf(内核空间)
int ret=misc_register(&misc);//注册设备文件,注册完后,dev/目录下会多个驱动文件,read/write这个文件就能调用你的驱动read/write了。
}
int 卸载驱动函数()
{
misc_deregister()//注销设备文件
}
MODULE_AUTHOR(作者) //可选
MODULE_LICENSE(开源协议) //可选
MODULE_ALIAS(别名) //可选
MODULE_DESCRIPTION(描述) //可选
module_init(初始化驱动函数)
module_exit(卸载驱动函数)
同级目录下Makefile文件
下面3选1,对应不同的项目结构
obj-m+=驱动名字.o#需要手动insmod(单纯安装)、modprobe(检测依赖后进行安装) 和rmmod
obj-m+=驱动名字.o#系统启动时,它会自动使用modprobe安装驱动,不需要你手动执行安装驱动的命令。
obj-$(CONFIG_驱动名字)+=驱动名字.o#根据mk配置项来决定,一般还要在某个defconfig文件配置CONFIG_驱动名字的值
编程理念
- static
因为在C语言中用static声明函数、变量等资源,系统会将这些函数和变量单独放在内存的某一个区域,直到程序完全退出,否则这些资源不会被释放。Linux驱动一旦装载,除非手动卸载或关机,驱动会一直驻留内存,因此这些函数和变量资源会一直在内存中。也就是说多次调用这些资源不用再进行压栈、出栈操作了,有利于提高驱动的运行效率。
- 避免使用浮点
- 不可使用c库
- 目前搜寻的资料中表示,驱动的阻塞与否完全依赖于自身代码的实现,内核并不干预这个。所以如果用户使用非阻塞打开,而代码里不管fd的O_NONBLOCK,一律阻塞的话。也是可行的。这个我还不是很确定,有点空试一下。
- 模块依赖
调试
- ls -l /dev
- dmesg 查看内核输出
- echo 输入 > /dev/你的驱动
- cat /dev/你的驱动