一、linux2.6与杂项驱动的不同
- linux2.6不会生成设备文件,需要用到其他的接口或者指令生成
- 需要申请设备号
二、使用的函数
1.申请设备号
- 功能:让内核分配一个或者多个可以用的设备号
- 头文件:<linux/fs.h>
- 原型:int alloc_chrdev_region(
dev_t * devnum, //向内核申请的设备号
unsigned base, //自己申请的次设备号
unsigned count, //连续申请几个
const char * lable //标签名字
);
2.结构体初始化函数
- 功能:初始化Linux2.6的核心结构体
- 头文件:<linux/cdev.h>
- 原型:void cdev_init(struct cdev * cdev , const struct file_operations * fops);// 核心结构体 内核操作集合
3.内核的注册添加
- 功能:向内核添加一个已经完成初始化工作的 cdev 核心结构体
- 头文件:<linux/cdev.h>
- 原型:int cdev_add(struct cdev * cdev, dev_t devnum,unsigned count);
4.创造一个设备文件
- 功能:创造一个设备文件
- 头文件:<linux/device.h>
- 原型:struct device *device_create(
struct class *cls,
struct device *parent,
dev_t devt,
void *drvdata,
const char *fmt, ...
);
实现使用Linux2.6驱动蜂鸣器
设备代码
#include "linux/kernel.h"
#include "linux/module.h"
#include "linux/miscdevice.h"
#include "linux/fs.h"
#include "linux/gpio.h"
#include "linux/cdev.h"
dev_t my_dev;
struct cdev mycdev;
struct file_operations my_oper;
struct class *my_class;
//功能函数
int mybeep_open(struct inode *i, struct file *f)
{
gpio_set_value(36,1);
return 0;
}
int mybeep_close(struct inode *i, struct file *f)
{
gpio_set_value(36,0);
return 0;
}
//加載函數
static int __init mybeep_init(void)
{
//初始化GPIO
gpio_request(36,"beep");
gpio_direction_output(36,0);
//申请设备号
alloc_chrdev_region(&my_dev,18,1,"mybeepdevice");
printk("申请的设备号是%d\r\n",my_dev);
printk("主设备号为:%d\r\n",my_dev>>20);
printk("次设备号为:%d\r\n",my_dev & 0xFFFFF);
//初始化Linux2.6核心结构体
my_oper.owner = THIS_MODULE;
my_oper.open = mybeep_open;
my_oper.release = mybeep_close;
cdev_init(&mycdev,&my_oper);
//向内核添加设备
cdev_add(&mycdev,my_dev,1);
//需要用函数添加设备文件
//生成一个类结构体
my_class = class_create(THIS_MODULE,"MY_beep");
//生成设备文件
device_create(my_class,NULL,my_dev,NULL,"MY_beep");
return 0;
}
static void __exit mybeep_exit(void)
{
device_destroy(my_class,my_dev);
class_destroy(my_class);
cdev_del(&mycdev);
unregister_chrdev_region(my_dev,1);
}
module_init(mybeep_init);
module_exit(mybeep_exit);
MODULE_LICENSE("GPL");
主函数代码
#include "stdio.h"
#include "unistd.h"
#include "fcntl.h"
#include "sys/types.h"
#include <sys/stat.h>
int main()
{
int fd = 0;
while (1)
{
/* code */
fd = open("/dev/MY_beep", O_RDWR);
sleep(1);
close(fd);
sleep(1);
}
return 0;
}
出现的问题
错误原因一:89编译模式下 变量的声明要放到函数体内的上面,也可以在kernel修改Makefile中的-std=gnu89改为-std=gnu99 注释掉KBUILD_CFLAGS += -Wdeclaration-after-statement
错误原因二:编写mybeep_exit函数的时候多打了一个{