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类:字符设备.块设备.网络设备.使用驱动程序: 字符设备:是指只能一个字节一个字节读写的设备,不能随机读取设备内存中的某一数据,读取数据需要按照先后数据.字符设备是面向流 ...
随机推荐
- gdb学习(一)[第二版]
概述 gdb是GNU debugger的缩写,是编程调试工具. 功能 1.启动程序,可以按照用户自定义的要求随心所欲的运行程序. 2.可让被调试的程序在用户所指定的断点处停住 (断点可以是条件表达式) ...
- 【Android 应用开发】Android应用的自动更新模块
. 作者 :万境绝尘 转载请注明出处 : http://blog.csdn.net/shulianghan/article/details/18964835 . 软件的自动更新一般都与Splash界 ...
- 学习C++模板,初体验
最近,看了很多码神级人物的代码,发现其代码很炫酷,尤其对模板的使用,作为小码农,感觉已经落伍了,所以应该发奋图强,好好学习和掌握模板这个东西. 模板是什么呢?有人说一个模板就是一个创建类或函数的蓝图或 ...
- 【46】java对象的三个特征(oop)
对象的三个特征: 对象的行为: 对象有哪些行为和方法 同一个类的实例,由于支持相同的行为具有家族式的特征,对象的行为是由方法定义的. 对象的状态: 施加方法时.对象的响应 每个对象都保存着描述当前特征 ...
- 【Qt编程】基于Qt的词典开发系列<十五>html特殊字符及正则表达式
1.html特殊字符的显示 我们知道html语言和C语言一样也有一些特殊字符,它们是不能正常显示的,必须经过转义,在网上可以查到如何显示这些字符,如下图所示: 上图给了最常用的特殊字符的显示,下面我们 ...
- Java Class Version 研究
一:要解决的问题 我们在尝鲜 JDK1.5 的时候,相信不少人遇到过 Unsupported major.minor version 49.0 错误,当时定会茫然不知所措.因为刚开始那会儿,网上与此相 ...
- 关于gcc的一点小人性化提示
现在对于大多数平台的C编译器来说都会有很多种选择,而gcc和clang无疑是2个非常优秀的C编译器.当然他们也不只是C编译器.我最近用clang的比较多,原因有很多.不过一些小的细节很让我喜欢,比如O ...
- java基础语法(二)--单列模式
java基础语法(二)--单列模式 /** * 功能:单列模式 * @author Administrator * */ public class SingletonTest { public sta ...
- SQL性能分析之执行计划
一直想找一些关于SQL语句性能调试的权威参考,但是有参考未必就能够做好调试的工作.我深信实践中得到的经验是最珍贵的,书本知识只是一个引导.本篇来源于<Inside Microsoft SQL S ...
- 完美支持Py3的微信开发库推荐
之前分享了个代码,后来发现中文发送是乱码,应该是加密代码的问题,然后在又找到这个可完美使用的Py3微信库wechatpy:https://github.com/jxtech/wechatpy