linux设备驱动之字符设备驱动模型(2)
在上一篇中我们已经了解了字符设备驱动的原理,也了解了应用层调用内核函数的机制,但是我们每次操作设备,都必须首先通过mknod命令创建一个设备文件名,比如说我们要打开u盘,硬盘等这些设备,难道我们还要自己创建,就如同刘老师常说的一句话,这也太山寨了吧,所以我们今天我们来点比较专业的,让函数帮我们自动创建;
在Linux 下,设备和驱动通常都需要挂接在一种总线上,总线有PCI、USB、I2C、SPI 等等,总线是处理器和设备之间的通道,在设备模型中,所有的设备都通过总线相连,一总线来管理设备和驱动函数;
因此我们先了解一下sys下的目录
block:用于管理块设备,系统中的每一个块设备会在该目录下对应一个子目录;
bus:用于管理总线,没注册一条总线,在该目录下有一个对应的子目录,其中,每个总线子目录下会有两个子目录:devices和drivers。
devices包含里系统中所有属于该总线的的设备。
drivers包含里系统中所有属于该总线的的驱动。
class:将系统中的设备按功能分类。
devices:该目录提供了系统中设备拓扑结构图。
dev:该目录已注册的设备节点的视图。
kernel:内核中的相关参数。
module:内核中的模块信息。
fireware:内核中的固件信息。
Fs:描述内核中的文件系统。
下面的代码是我们在sys/class中创建一个名为dog的类,然后在创建一个设备(wangcai);
#include <linux/init.h>
#include <linux/module.h>
#include <linux/cdev.h>
#include <linux/fs.h>
#include <linux/device.h>
#include <linux/err.h> MODULE_LICENSE("GPL");
MODULE_AUTHOR("bunfly"); struct class *dog;
struct device *wangcai; int bunfly_init()
{
dog = class_create(THIS_MODULE, "dog");//创建一个dog类
if(IS_ERR(dog)) {
PTR_ERR(dog);
return ;
} wangcai = device_create(dog, NULL, MKDEV(, ), NULL, "wangcai%d", );//创建一个名为旺财的设备
if(IS_ERR(wangcai)) {
PTR_ERR(wangcai);
return ;
} return ;
} int bunfly_exit()
{
printk("this is bunfly_exit\n"); return ;
} module_init(bunfly_init);
module_exit(bunfly_exit);
在实际的工作中我们一般都不需要创建类,设备等,linux系统都为常见的设备分好了类,而设备厂商都已经提供了,我们做的就是来驱动这些设备;在sys/class类中我们经常用的就是misc(杂项类)
杂项设备也是在嵌入式系统中用得比较多的一种设备驱动,其定义如下:
struct device;
struct miscdevice {
int minor; //次设备号
const char *name; //设备名
const struct file_operations *fops;//文件操作
struct list_head list; //形成链表
struct device *parent;
struct device *this_device;
const char *nodename;
mode_t mode;
};
extern int misc_register(struct miscdevice * misc); //混杂设备注册
extern int misc_deregister(struct miscdevice *misc); //混杂设备注销
#define MODULE_ALIAS_MISCDEV(minor) \
MODULE_ALIAS("char-major-" __stringify(MISC_MAJOR) \
"-" __stringify(minor))
#endif
下面代码是在misc下注册一个名为bunfly_led的设备;插入模块后,在/dev下生成一个名为bunfly_led的设备名
#include <linux/init.h>
#include <linux/module.h>
#include <linux/cdev.h>
#include <linux/fs.h>
#include <linux/device.h>
#include <linux/err.h>
#include <linux/miscdevice.h> MODULE_LICENSE("GPL");
MODULE_AUTHOR("bunfly"); struct file_operations fops;//方法
struct miscdevice led; int bunfly_init()
{
led.name = "bunfly_led";//设备名
led.fops = &fops;//关联方法
misc_register(&led);//在杂项类中注册led return ;
} int bunfly_exit()
{
printk("this is bunfly_exit\n");
misc_deregister(&led);//注销 return ;
} module_init(bunfly_init);
module_exit(bunfly_exit);
下面代码的功能是用ioctl()函数控制led灯,格式:./ioctl /dev/bunfly_led 0 (灯亮) | 1(灯灭)
#include <stdio.h>
#include <string.h>
#include <fcntl.h> //输入 ./ioctl /dev/bunly_led 1(灯灭) : 0(灯亮)
int main(int argc, char *argv[])
{
if(argc != ) {
printf("using %s <devname> 1:0\n", argv[]);
return ;
} int fd = ;
fd = open(argv[], O_RDWR);
if(fd < ) {
perror("open");
return ;
} //argv【2】为字符,需要atoi转换为数字
ioctl(fd, atoi(argv[]));
close(fd);
return ;
}
内核中:
#include <linux/init.h>
#include <linux/module.h>
#include <linux/cdev.h>
#include <linux/fs.h>
#include <linux/device.h>
#include <linux/err.h>
#include <linux/miscdevice.h>
#include <linux/fs.h>
#include <linux/io.h>
#include <linux/gpio.h> MODULE_LICENSE("GPL");
MODULE_AUTHOR("bunfly"); int bunfly_open(struct inode *n, struct file *fp);
long bunfly_ioctl(struct file *fp, unsigned int num, unsigned long vlaue);
void led_on();
void led_off(); struct file_operations fops;//方法
struct miscdevice led; unsigned long gpio_virt;
unsigned long *gpm4con, *gpm4dat; int bunfly_init()
{
fops.open = bunfly_open;//调用系统函数
fops.unlocked_ioctl = bunfly_ioctl; gpio_virt = ioremap(0x11000000, SZ_4K);//led物理地址到虚拟地址的映射
gpm4con = gpio_virt + 0x02e0;
gpm4dat = gpio_virt + 0x02e4; led.name = "bunfly_led";
led.fops = &fops;
misc_register(&led);//注册杂项类设备led return ;
} int bunfly_exit()
{
printk("this is bunfly_exit\n");
misc_deregister(&led);//注销设备 return ;
} module_init(bunfly_init);
module_exit(bunfly_exit); int bunfly_open(struct inode *n, struct file *fp)
{
printk("this is bunfly_open\n");
return ;
} long bunfly_ioctl(struct file *fp, unsigned int num, unsigned long vlaue)
{
if(num == ) {
led_on();
}
else {
if(num == ) {
led_off();
}
else {
printk("unkonw command %d\n", num);
}
} return ;
} void led_on()
{
*gpm4con &= ~0xffff;
*gpm4con |= 0x1111;
*gpm4dat = 0x0;
} void led_off()
{
*gpm4con &= ~0xffff;
*gpm4con |= 0x1111;
*gpm4dat = 0xf; }
linux设备驱动之字符设备驱动模型(2)的更多相关文章
- 【转】深入浅出:Linux设备驱动之字符设备驱动
深入浅出:Linux设备驱动之字符设备驱动 一.linux系统将设备分为3类:字符设备.块设备.网络设备.使用驱动程序: 字符设备:是指只能一个字节一个字节读写的设备,不能随机读取设备内存中的某一数据 ...
- 手把手教Linux驱动3-之字符设备架构详解,有这篇就够了
一.Linux设备分类 Linux系统为了管理方便,将设备分成三种基本类型: 字符设备 块设备 网络设备 字符设备: 字符(char)设备是个能够像字节流(类似文件)一样被访问的设备,由字符设备驱动程 ...
- Linux驱动设计——字符设备驱动(一)
Linux字符设别驱动结构 cdev结构体 struct cdev { struct kobject kobj; struct module *owner; const struct file_ope ...
- Linux 设备驱动之字符设备
参考转载博客:http://blog.chinaunix.net/uid-26833883-id-4369060.html https://www.cnblogs.com/xiaojiang1025/ ...
- linux中c表示字符设备文件符号
linux中c表示字符设备文件,b表示块设备文件,l表示符号链接文件,r表示可读权限,w表示可写权限.linux文件属性解读:文件类型:-:普通文件 (f)d:目录文件b:块设备文件 (block)c ...
- linux设备驱动之字符设备驱动模型(1)
一:字符设备驱动 在linux下面,应用层看到的一切皆为文件(名字)所有的设备都是文件,都可以调用open,read,write来操作,而在内核中每个中每个设备有唯一的对应一个设备号: APP ( ...
- 深入浅出:Linux设备驱动之字符设备驱
一.linux系统将设备分为3类:字符设备.块设备.网络设备.使用驱动程序: 字符设备:是指只能一个字节一个字节读写的设备,不能随机读取设备内存中的某一数据,读取数据需要按照先后数据.字符设备是面向流 ...
- 【Linux驱动】字符设备驱动
一.linux系统将设备分为3类:字符设备.块设备.网络设备.使用驱动程序: 1.字符设备:是指只能一个字节一个字节读写的设备,不能随机读取设备内存中的某一数据,读取数据需要按照先后数据.字符设备是面 ...
- 蜕变成蝶~Linux设备驱动之字符设备驱动
一.linux系统将设备分为3类:字符设备.块设备.网络设备.使用驱动程序: 字符设备:是指只能一个字节一个字节读写的设备,不能随机读取设备内存中的某一数据,读取数据需要按照先后数据.字符设备是面向流 ...
随机推荐
- ORM对象关系映射之GreenDAO自定义属性转换器PropertyConverter
在使用GreenDAO定义实体的属性时候,通常来说定义的实体属性名就是对应的表的字段名.实体中属性的类型(如Long.String等)就是表的字段名类型,但是我们难免会有不一样的需求,比如实体中我定义 ...
- Linux程序分析工具介绍—ldd,nm
原文链接:http://blog.csdn.net/statdm/article/details/7759100 本文要介绍的ldd和nm是linux下,两个用来分析程序很实用的工具.ldd是用来分析 ...
- 【面试笔试算法】Problem 7: 补提交卡(hiho题库)
时间限制:2000ms 单点时限:1000ms 内存限制:256MB 描述 小Ho给自己定了一个宏伟的目标:连续100天每天坚持在hihoCoder上提交一个程序.100天过去了,小Ho查看自己的提交 ...
- Oracle Advanced Pricing White Papers
Oracle Order Management - Version 11.5.10.0 and later Oracle Advanced Pricing - Version 11.5.10 and ...
- 物理引擎中velocity的单位是个什么鬼?
现在, 你可能对于什么是velocity的单位感到奇怪.他是单位秒中经过点的一个可测量的量(pt/s).如果你想要在iphone横屏从左往右的移动物体,并且你想在1秒内移动1024个点,那么物体的x速 ...
- JFinal开发环境搭建,JFinal开发案例
JFinal 是基于 Java 语言的极速 WEB + ORM 开发框架,其核心设计目标是开发迅速.代码量少.学习简单.功能强大.轻量级.易扩展.Restful.在拥有Java 语言所 ...
- iOS监听模式系列之对APNs的认知与理解
前言: APNs 协议在近两年的 WWDC 上改过两次, 15 年 12 月 17 日更是推出了革命性的新特性.但在国内传播的博客.面试题里关于 APNs 的答案全都是旧的.错的. 导航: 对 APN ...
- Android特效专辑(三)——自定义不一样的Toast
Android特效专辑(三)--自定义不一样的Toast 大家都知道,Android的控件有时候很难满足我们的需求,所以我们需要自定义View.自定义的方式很多,有继承原生控件也有直接自定义View的 ...
- 通信录列表+复杂Adapter分析
概述 最近写论文之余玩起了github,发现有个citypicker挺不错的,高仿了美团城市选择和定位的一些功能 地址链接 效果图如下: 自己手动写了一遍优化了一些内容,学到了一些姿势,下面对其中一些 ...
- ruby正则表带式对象使用备忘
ruby对于正则表达式的使用是非常灵活的,提供了专门的正则表达式对象Regexp.其包括match实例方法,字符串也含有该方法.so可以这么做: /a/ =~ "a" " ...