网站开发 q3687474,摄影摄像网站建设,国外设计师作品网站,怎么免费建自己的网站目录
一、杂项设备注册
杂项设备注册简介
杂项设备注册特点:
杂项设备注册相关API
misc_register()
misc_deregister()
杂项设备注册相关例程
例程简介
源码分享
二、Linux 2.6设备注册
Linux2.6设备注册简介
Linux 2.6设备注册特点
Linux2.6设备注册流程
Linu…
目录
一、杂项设备注册
杂项设备注册简介
杂项设备注册特点:
杂项设备注册相关API
misc_register()
misc_deregister()
杂项设备注册相关例程
例程简介
源码分享
二、Linux 2.6设备注册
Linux2.6设备注册简介
Linux 2.6设备注册特点
Linux2.6设备注册流程
Linux2.6设备注册相关函数
alloc_chrdev_region()
unregister_chrdev_region()
cdev_init()
cdev_add()
cdev_del()
class_create()
device_create()
device_destroy()
class_destroy()
Linux2.6设备注册相关例程
例程简介
源码分享
三、选择建议 Linux设备驱动开发中,需要向内核正确注册设备,才能创建设备节点,以供应用层访问。本文将详细介绍Linux下的两种设备注册方法:杂项设备注册和Linux 2.6新方法注册。
一、杂项设备注册
杂项设备注册简介 杂项设备注册是Linux驱动开发中的一种设备注册方式。在Linux系统中杂项设备是一类没有明确分类的设备它们不属于字符设备、块设备或网络设备等特定类型。杂项设备可以包括各种不同类型的设备如传感器、LED灯、温度计等。 杂项设备注册的目的是将这些杂项设备描述成设备文件以便通过文件操作来控制和访问设备。通过设备文件应用程序可以打开、关闭、读取和写入杂项设备实现对设备的控制和数据交互。 在杂项设备注册中使用struct miscdevice结构体来描述设备的属性和设备文件的名字。该结构体包含了主设备号、次设备号、设备文件名和文件操作集合等信息。通过调用misc_register函数将杂项设备的核心结构体注册到内核中完成设备的注册过程。 杂项设备注册的好处是它可以自动生成设备文件无需手动创建。系统会根据设备的主设备号和次设备号在/dev目录下自动创建对应的设备文件。这样应用程序可以直接通过设备文件来访问和控制杂项设备简化了设备的管理和使用。
杂项设备注册特点:
主设备号固定为10,次设备号自动分配注册后在/dev目录自动创建设备节点每个主机最多256个杂项设备
杂项设备注册相关API
misc_register()
功能向内核注册一个杂项设备
头文件Linux/miscdevice.h
原型int misc_register(struct miscdevice * misc)
参数struct miscdevice * misc杂项设备注册的核心结构体
返回值成功 0失败 负数struct miscdevice {//杂项注册核心结构体int minor; //次设备号const char *name; //设备的名字 会出现在 /dev/目录下const structfile_operations *fops; 操作集合结构体//以下内容可以不管struct list_head list;struct device *parent;struct device*this_device;const char *nodename;umode_t mode;
};struct file_operations {//操作集合结构体,使用时需要实现内核编程接口:open/close/read/write等。structmodule *owner; //固定填写 THIS_MODULEint(*open) (struct inode *, struct file *); //内核层的open函数int(*release) (struct inode *, struct file *); //内核层的close函数……………………………………..};
misc_deregister()
功能 取消注册的杂项设备
头文件Linux/miscdevice.h
原型int misc_deregister(struct miscdevice*misc)
参数struct miscdevice *misc杂项设备的核心结构体
返回值成功 0失败 负数
杂项设备注册相关例程
例程简介
这个例程的作用是实现一个蜂鸣器的控制功能。它包括了一个内核模块和一个用户态程序。
内核模块部分
在模块初始化函数bp_init中首先进行了地址映射将控制寄存器和数据寄存器映射到内核空间。然后设置了蜂鸣器的相关寄存器包括将控制寄存器的低四位设置为1将数据寄存器的最低位设置为0。接下来通过misc_register函数向内核注册了一个杂项设备。设置了该设备的打开和关闭函数并指定了设备文件名和次设备号。在模块退出函数bp_exit中调用misc_deregister函数取消注册杂项设备。
用户态程序部分
在main函数中通过open函数打开设备文件/dev/bp_dev并指定了读写权限。然后进入一个循环每隔一秒钟打开蜂鸣器并输出提示信息再关闭蜂鸣器并输出提示信息。循环会一直执行直到程序被手动终止。
源码分享
/*驱动层相关源码*/
#include linux/kernel.h
#include linux/module.h
#include linux/miscdevice.h
#include linux/fs.h
#include linux/io.hvoid __iomem *GPD0_CON NULL; //控制寄存器
void __iomem *GPD0_DAT NULL; //数据寄存器struct file_operations bp_fops;
struct miscdevice bp_misc;//开启蜂鸣器函数
int bp_open (struct inode *inode, struct file *file){
printk(蜂鸣器开启\n);
*((unsigned int *)GPD0_DAT) | 0x1;
return 0;
}//蜂鸣器关闭函数
int bp_close (struct inode *inode, struct file *file){
printk(蜂鸣器关闭\n);
*((unsigned int *)GPD0_DAT) ~(0x1);
return 0;
}static int __init bp_init(void){
printk(加载蜂鸣器模块\n);//地址映射
GPD0_CON ioremap(0x114000a0, 2);
GPD0_DAT ioremap(0x114000a4, 1);//寄存器设置
*((unsigned int *)GPD0_CON) ~(0xf);
*((unsigned int *)GPD0_CON) | (0x1);
*((unsigned int *)GPD0_DAT) (0x1);//向内核注册一个杂项设备
bp_fops.open bp_open; //打开蜂鸣器
bp_fops.release bp_close; //关闭蜂鸣器
bp_fops.owner THIS_MODULE; //模块所有者bp_misc.minor 255; //系统分配次设备号
bp_misc.name bp_dev; //设备文件名
bp_misc.fops bp_fops; //文件操作集合
misc_register(bp_misc);return 0;
}static void __exit bp_exit(void){
printk(卸载蜂鸣器模块\n);
misc_deregister(bp_misc);}module_init(bp_init);
module_exit(bp_exit);
MODULE_LICENSE(GPL);
MODULE_AUTHOR(YYY);/*用户层相关源码*/#include sys/types.h
#include sys/stat.h
#include fcntl.h
#include stdio.hint main(){int bp_fd 0;
while(1){bp_fd open(/dev/bp_dev, O_RDWR);if(bp_fd 0){printf(打开bp_dev失败\n);perror(open);}printf(开启蜂鸣器\n);sleep(1);close(bp_fd);printf(关闭蜂鸣器\n);sleep(1);
}
return 0;
}
二、Linux 2.6设备注册
Linux2.6设备注册简介 Linux 2.6内核引入了一种更灵活的设备注册机制提供了设备模型来管理和注册设备。这种设备注册方式相对于旧版本的Linux内核更加面向对象具有更好的可维护性和扩展性也是当前比较最流行的设备注册方法。
Linux 2.6设备注册特点
提供更灵活的设备注册机制,主次设备号不再限定注册后需要自行创建设备节点支持模块化和多实例设计可以灵活配置主次设备号支持多实例和模块化设计更好地处理多个设备的情况
Linux2.6设备注册流程
申请设备号(alloc_chrdev_region) 设备号由主设备号和次设备号组成用于唯一标识一个设备。可以使用alloc_chrdev_region函数动态申请字符设备号或者使register_chrdev_region函数静态注册一个已知的设备号。初始化cdev结构体(cdev_init) cdev结构体表示字符设备。开发者需要初始化这个结构体并将它与设备的文件操作函数关联起来。这可以通过cdev_init和cdev_add函数来完成。注册cdev结构体(cdev_add) cdev_add函数用于将cdev结构体添加到系统中使得内核可以管理和操作这个设备。创建设备类(class_create) 使用class_create函数创建一个设备类这个类将出现在/sys/class目录下。创建设备节点(device_create) 用device_create函数自动创建设备节点通常位于/dev目录下而不是手动使用mknod命令。
Linux2.6设备注册相关函数
alloc_chrdev_region()
功能向内核申请设备号
头文件Linux/fs.h
原型int alloc_chrdev_region(dev_t * dev, unsigned baseminor, unsigned count, const char * name)
参数dev_t *dev, 用来存放获取到的设备号的变量unsigned baseminor, 次设备号的起始位置 unsigned count, 要申请的设备号的数量 constchar *name 设备的名字
返回值成功 0失败 非零
unregister_chrdev_region()
功能释放设备号
头文件Linux/fs.h
原型void unregister_chrdev_region(dev_t from, unsigned count)
参数dev_t from, 要释放的设备号的起始位置 unsigned count 要释放的设备号的个数
返回值无
cdev_init()
功能初始化linux2.6的核心结构体
头文件Linux/cdev.h
原型void cdev_init(struct cdev *cdev, conststruct file_operations *fops);
参数struct cdev *cdev, linux2.6的核心结构体const struct file_operations *fops 操作集合结构体
返回值无
cdev_add()
功能注册一个linux2.6的核心结构体
头文件Linux/cdev.h
原型int cdev_add(struct cdev *, dev_t,unsigned);
参数struct cdev *cdev, linux2.6的核心结构体dev_t dev, 设备号unsigned count 向内核注册的linux2.6的核心结构体的个数 一般填1
返回值成功 0失败 错误码
cdev_del()
功能取消linux2.6核心结构体的注册
头文件Linux/cdev.h
原型void cdev_del(struct cdev *p)
参数struct cdev *plinux2.6的核心结构体指针
返回值无
class_create()
功能创建类结构体
头文件Linux/device.h
原型struct class *class_create( struct module*owner, const char *name)
参数struct module *owner, :THIS_MODULEconst char *name :类结构体的名字
返回值成功 类结构体指针失败 NULL
device_create()
功能自动生成设备文件
头文件Linux/device.h
原型struct device *device_create(struct class*class, struct device *parent,dev_t devt, void *drvdata, const char*fmt, ...)
参数struct class *class, 类结构体的名字struct device *parent, NULLdev_t devt, 设备号void*drvdata, 传给设备的私有数据 NULLconst char *fmt,... 设备的名字 会出现在/dev/目录下
返回值成功 设备的结构体指针失败 NULL
device_destroy()
功能销毁设备文件
头文件Linux/device.h
原型void device_destroy(struct class *class,dev_t devt)
参数struct class *class, 类结构体dev_t devt 设备号
返回值无
class_destroy()
功能销毁类结构体
头文件Linux/device.h
原型void class_destroy(struct class *cls)
参数struct class *cls:类结构体
返回值无
Linux2.6设备注册相关例程
例程简介
这个Linux内核模块的例程实现了一个简单的 LED 流水灯控制。
Linux内核模块部分
定义了一个字符设备驱动设备名为myled。这个驱动通过myopen和myclose函数控制LED灯的开关并实现了流水灯效果。在myled_init函数中首先通过alloc_chrdev_region函数申请设备号然后初始化cdev结构体并通过cdev_add函数将其添加到系统中。接着创建一个类结构体并在该类下创建设备文件。在myled_exit函数中注销设备文件注销类结构体取消cdev的注册并释放设备号。
用户空间程序部分
这个程序通过打开/dev/myled设备文件来控制LED灯的开关。每次打开设备文件时LED灯会按照流水灯的效果亮起每次关闭设备文件时LED灯会熄灭。程序会无限循环打开和关闭设备文件从而实现LED灯的不断闪烁。
源码分享
/*驱动层源码*/
#include linux/kernel.h
#include linux/module.h
#include linux/fs.h
#include linux/gpio.h
#include linux/cdev.h
#include linux/device.hdev_t mydev;
int count;
struct cdev mycdev;
struct file_operations myfops;
struct class *myclass NULL;//open函数实现开灯流水灯效果
int myopen (struct inode *inode, struct file *file){
if(count 4)
count 0;
gpio_set_value(EXYNOS4X12_GPM4(count), 0);
gpio_set_value(EXYNOS4_GPD0(0), 1);
count;
printk(开灯%d\n, count);
return 0;
}//close函数实现关灯流水灯效果
int myclose (struct inode *inode, struct file *file){
gpio_set_value(EXYNOS4X12_GPM4(count - 1), 1);
gpio_set_value(EXYNOS4_GPD0(0), 0);
printk(关灯%d\n, count - 1);
return 0;
}static int __init myled_init(void){
//申请设备号alloc_chrdev_region(mydev, 0, 1, myled);
printk(申请到的设备号为 %d\n, mydev);
printk(主设备号 %d\n, MAJOR(mydev));
printk(次设备号 %d\n, MINOR(mydev));//初始化Linux2.6的核心结构体
myfops.owner THIS_MODULE;
myfops.open myopen;
myfops.release myclose;
cdev_init(mycdev, myfops);//向内核注册一个Linux2.6核心结构体
cdev_add(mycdev, mydev, 1);//创建一个类结构体
myclass class_create(THIS_MODULE, myled);
if(myclass NULL){printk(创建类结构体失败\n);return -1;
}//创建设备文件
device_create(myclass, NULL, mydev, NULL, myled);
return 0;
}static void __exit myled_exit(void){
//注销设备文件
device_destroy(myclass, mydev);//注销类结构体
class_destroy(myclass);//取消Linux2.6注册
cdev_del(mycdev);//释放设备号
unregister_chrdev_region(mydev, 1);
}module_init(myled_init);
module_exit(myled_exit);
MODULE_LICENSE(GPL);
MODULE_AUTHOR(YYY);
/*用户层源码*/
#include sys/types.h
#include sys/stat.h
#include fcntl.h
#include stdio.hint main(){int led_fd 0;
while(1){led_fd open(/dev/myled, O_RDWR);if(led_fd 0){printf(打开myled失败\n);perror(open);}printf(开灯\n);sleep(1);close(led_fd);printf(关灯\n);sleep(1);
}
return 0;
}
//申请设备号
int alloc_chrdev_region(dev_t *dev, unsigned baseminor, unsigned count, const char *name);//初始化注册cdev
void cdev_init(struct cdev *cdev, const struct file_operations *fops);
int cdev_add(struct cdev *cdev, dev_t dev, unsigned count);//创建设备节点
struct device *device_create(struct class *cls, struct device *parent, dev_t devt, void *drvdata, const char *fmt,..);
三、选择建议
简单的字符设备推荐使用杂项设备注册需要灵活控制主次设备号的复杂设备使用Linux 2.6方法在模块化设计方面,Linux 2.6方式更优秀