Linux2.6方式设备注册API

杂项设备注册和经典设备注册方法可参考我前俩篇博客

 

在linux2.6里面设备号的申请方式一共有2种

动态设备号申请:

>头文件:
> #include <linux/fs.h>
> 函数原型:
> int alloc_chrdev_region(dev_t *dev, unsigned baseminor, unsigned count, const char *name)
> 参数:
> dev:存放分配到的第一个设备(包括主次设备号)
> baseminon:要分配起始次设备号(次设备号的起始值)
> count:连续的次设备号数量
> name:设备名,不需要和/dev的设备文件名相同,随便取
>返回值:
> 成功返回0 失败返回负数

静态设备号申请

> 头文件:
> #include <linux/fs.h>
> 函数原型:
> int register_chrdev_region(dev_t from, unsigned count, const char *name)
> 参数:
> from:起始设备号(主,次)
> count:连续的次设备号数量
> name:设备名,不需要和/dev的设备文件名相同,随便取
> 返回值:
> 成功返回0 失败返回负数

设备号提取合成操作:
静态合成:
MKDEV(ma,mi)//已知次设备号合成完整设备号
动态提取:
MAJOR(dev)//从完整设备号提取主设备号
MINOR(dev)//从完整设备号提取次设备号

核心初始化函数:

头文件:#include <linux/cdev.h>
函数原型:
void cdev_init(struct cdev *cdev,const struct file_operations *fops)
功能:
初始化核心结构,具体做的是清零核心结构,初始化核心结构的
list,kobj,ops成员。
参数:
cdev:需要初始化的核心结构指针
fops:文件操作方法结构指针集
返回值:
无返回值
特别说明:
写这种驱动模型的时候,不需要在定义struct cdev结构变量初始
化,因为调用cdev_init函数的时候会把它清零0,定义时候的初始无效。

设备注册函数:

头文件:
#include <linux/cdev.h>
函数原型:
int cdev_add(struct cdev *p,dev_t dev,unsigned count)
功能:
功能注册一个cdev结构
参数:
p:已经初始化的核心结构指针
dev:起始设备号(包含主次设备号)
count:连续次设备号的数量
返回值:
成功: 返回 0 失败:返回负数

设备注销函数:

头文件:
#include <linux/cdev.h>
函数原型:
void cdev_del(struct cdev *p)
函数功能:
注销一个cdev结构
参数:
前面注册的struct cdev结构指针
返回值:
无返回值

设备号释放函数:

头文件:
#include <linux/fs.h>
函数原型:
void unregister_chrdev_region(dev_t from, unsigned int count)
函数功能:
释放一个设备号范围
参数:
from:起始设备号(主,次)(包含主次设备号)
count:连续的次设备号数量
返回值:
无返回值

示例:

内核设备模块

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/device.h>
#include <linux/fs.h>
#include <linux/io.h>//内存映射
#include <linux/cdev.h>
#include <linux/miscdevice.h>
/*
GPD0_0---beep
0x114000A0 -- con
0x114000A4 -- con
*/
unsigned int * base = NULL;
#define GPD0_CON (*((unsigned int * )(base)))
#define GPD0_DTA (*((unsigned int * )(base+1)))
struct file_operations my_ops;

int beep_open(struct inode * inode, struct file * file)
{
GPD0_DTA |=(0x01<<0);
return 0;
}
int beep_close(struct inode * inode, struct file * file)
{
GPD0_DTA &=~(0x01<<0);
return 0;
}
dev_t my_dev;
struct cdev my_cdev;
static int __init beep_init(void)
{
int rel;
//1:2.6注册一个设备
my_ops.owner = THIS_MODULE;
my_ops.open = beep_open;
my_ops.release = beep_close;

//1.1:申请一个可以用的设备号
rel = alloc_chrdev_region(&my_dev,0,1,"asdasdsa");
printk("major == %d\r\n",MAJOR(my_dev));
printk("minor == %d\r\n",MINOR(my_dev));
//1.2:注册
cdev_init(&my_cdev,&my_ops);
cdev_add(&my_cdev,my_dev,1);
base = ioremap(0x114000A0,8);
GPD0_CON &=~(0xF<<0);
GPD0_CON |=(0x01<<0);//输出
return 0;
}
static void __exit beep_exit(void)
{
cdev_del(&my_cdev);//解除设备的注册
unregister_chrdev_region(my_dev,1);//释放设备号
iounmap(base);
}

module_init(beep_init);
module_exit(beep_exit);
MODULE_LICENSE("GPL");

用户调用:

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
int main(void)
{
int fd=0;
while(1)
{
fd = open("/dev/beep",O_RDWR);
sleep(1);
close(fd);
sleep(1);
}
return 0;
}

Makefile

obj-m += beep.o

KDIR:=/home/jason/my_drive/linux-3.5

all:
make -C $(KDIR) M=$(PWD) modules
arm-linux-gcc beep_app.c -o beep_app

clean:
rm -f *.ko *.o *.mod.o *.mod.c *.symvers *.markers *.order

Linux驱动之----Linux2.6方式设备注册_头文件

运行结果和上篇,经典模式一样,要注意设备号。

Linux驱动之----Linux2.6方式设备注册_#include_02