嵌入式Linux驱动学习之路(二十七)字符设备驱动的另一种写法
之前讲的字符设备驱动程序,只要有一个主设备号,那么次设备号无论是什么都会和同一个 struct file_operations 结构体对应。
而本节课讲的是如何在设备号相同的情况下,让不同的次设备号对应不同的 struct file_operations 结构体。
在本次的驱动程序中,打开/dev/hello0 、 /dev/hello1 调用的是hello_open函数。打开/dev/hello2 调用的是 hello2_open 函数。打开其他次设备号的文件,则是打开失败。
驱动程序代码:
/*************************************************************************
> File Name: hello.c
> Author:
> Mail:
> Created Time: 2016年11月14日 星期一 20时28分50秒
************************************************************************/
#include <linux/sched.h>
#include <linux/signal.h>
#include <linux/spinlock.h>
#include <linux/errno.h>
#include <linux/random.h>
#include <linux/poll.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/wait.h>
#include <linux/mutex.h>
#include <linux/io.h>
#include <linux/cdev.h> #include <linux/fs.h> /* 确定主设备号 唯一 */
static int major;
/* 第二种设备的函数 */
static int hello2_open( struct inode *inode, struct file *file )
{
printk("hello_open2\n");
return ;
}
/* 第一种设备的函数 */
static int hello_open( struct inode *inode, struct file *file )
{
printk("hello_open\n");
return ;
}
/* 第一种设备的结构体 */
static struct file_operations hello_ops = {
.owner = THIS_MODULE,
.open = hello_open,
};
/* 第二种设备的结构体 */
static struct file_operations hello2_ops = {
.owner = THIS_MODULE,
.open = hello2_open,
}; static struct cdev hello_cdev;
static struct cdev hello2_cdev;
static struct class *cls;
static int hello_init(void)
{
dev_t devid; if(major) //如果已经有了设备号则不再申请,如果没有则自动申请一个
{
devid = MKDEV(major, ); //次设备号从0开始计算
register_chrdev_region(devid,,"hello"); //有两个设备文件与之对应
}
else
{
alloc_chrdev_region(&devid, , ,"hello"); //次设备号从0开始计算,有两个设备文件与之对应
major = MAJOR(devid);
}
cdev_init( &hello_cdev, &hello_ops );
cdev_add( &hello_cdev, devid, ); //有两个设备文件与之对应 即次设备号为0~1的设备文件调用 hello_ops 中的函数 /* 因为上面的已经有了主设备号,这里肯定也是有主设备号,所以不用判断是否要去申请了 */
devid = MKDEV(major, ); //次设备号从0开始计算
register_chrdev_region(devid,,"hello2"); //有一个设备文件与之对应
cdev_init( &hello2_cdev, &hello2_ops );
cdev_add( &hello2_cdev, devid, ); //有一个设备文件与之对应 即次设备号为2的设备文件调用 hello2_ops 中的函数 cls = class_create(THIS_MODULE,"hello");
class_device_create(cls,NULL,MKDEV(major,),NULL,"hello0");
class_device_create(cls,NULL,MKDEV(major,),NULL,"hello1");
class_device_create(cls,NULL,MKDEV(major,),NULL,"hello2");
class_device_create(cls,NULL,MKDEV(major,3,NULL,"hello3");
return ;
} static void hello_exit(void)
{
class_device_destroy(cls,MKDEV(major,));
class_device_destroy(cls,MKDEV(major,));
class_device_destroy(cls,MKDEV(major,));
class_device_destroy(cls,MKDEV(major,3));
class_destroy(cls); cdev_del(&hello_cdev);
unregister_chrdev_region(MKDEV(major,),); cdev_del(&hello2_cdev);
unregister_chrdev_region(MKDEV(major,),);
} module_init(hello_init);
module_exit(hello_exit);
MODULE_LICENSE("GPL");
测试程序代码:
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h> int main( int argc, char **argv )
{
int fd;
if(argc != )
return ;
fd = open(argv[],O_RDWR); if(fd<)
printf("open failed\n");
else
printf( "can open\n" ); return ;
}
嵌入式Linux驱动学习之路(二十七)字符设备驱动的另一种写法的更多相关文章
- 嵌入式Linux驱动学习之路(二十一)字符设备驱动程序总结和块设备驱动程序的引入
字符设备驱动程序 应用程序是调用C库中的open read write等函数.而为了操作硬件,所以引入了驱动模块. 构建一个简单的驱动,有一下步骤. 1. 创建file_operations 2. 申 ...
- 嵌入式Linux驱动学习之路(二十)USB设备驱动
USB在接入系统的时候,以0的设备ID和主机通信,然后由主机为其分配新的ID. 在主机端,D+和D-都是下拉接地的.而设备端的D-接上拉时,表明此设备为高速设备:12M/s. D+接上拉时则是全速设备 ...
- Linux USB驱动学习总结(二)---- USB设备驱动
USB 设备驱动: 一.USB 描述符:(存在于USB 的E2PROM里面) 1. 设备描述符:struct usb_device_descriptor 2. 配置描述符:struct usb_c ...
- Linux驱动实践:你知道【字符设备驱动程序】的两种写法吗?
作 者:道哥,10+年嵌入式开发老兵,专注于:C/C++.嵌入式.Linux. 关注下方公众号,回复[书籍],获取 Linux.嵌入式领域经典书籍:回复[PDF],获取所有原创文章( PDF 格式). ...
- 嵌入式Linux驱动学习之路(二十四)Nor Flash驱动程序
Nor Flash和Nand Flash的不同: 类型 NOR Flash Nand Flash 接口 RAM-like,引脚多 引脚少 容量 小(1M.2M...) 大(512M.1G) 读 简 ...
- 嵌入式Linux驱动学习之路(二十五)虚拟网卡驱动程序
一.协议栈层次对比 设备无关层到驱动层的体系结构 1).网络协议接口层向网络层协议提供提供统一的数据包收发接口,不论上层协议为ARP还是IP,都通过dev_queue_xmit()函数发送数据,并通过 ...
- 嵌入式Linux驱动学习之路(二十三)NAND FLASH驱动程序
NAND FLASH是一个存储芯片. 在芯片上的DATA0-DATA7上既能传输数据也能传输地址. 当ALE为高电平时传输的是地址. 当CLE为高电平时传输的是命令. 当ALE和CLE都为低电平时传输 ...
- 嵌入式linux的学习之路[转]
我认为的一条学习嵌入式Linux的路: 1)学习 Linux系统安装. 常用命令.应用程序安装. 2) 学习 Linux 下的 C 编程.这本书必学<UNIX 环境高级编程>.<UN ...
- 嵌入式Linux驱动学习之路(二十二)用内存模拟磁盘
安装驱动后,可在/dev/目录下发现已经生成了相应的设备文件. 格式化设备:mkdosfs /dev/ramblock. 挂载设备. 读写设备 . 驱动程序代码: /***************** ...
随机推荐
- 前端学PHP之mysql扩展函数
× 目录 [1]连接数据库 [2]使用数据库 [3]执行SQL查询[4]操作结果集[5]关闭连接 前面的话 mysql由于其体积小.速度快.总体拥有成本低,尤其是具有开放源码这一特点,许多中小型网站为 ...
- 实践 Neutron FWaaS - 每天5分钟玩转 OpenStack(118)
前面我们学习了 FWaaS 的理论知识,今天将通过实验来学习 FWaaS. 在我们的实验环境中,有两个 instance: cirros-vm1(172.16.100.3) 和 cirros-vm2( ...
- GDB调试命令
1.查看源码: list [函数名][行数] 2.暂停程序 (1)设置断点: a.break + [源代码行号][源代码函数名][内存地址] b.break ... if condition .. ...
- javascript的变量作用域--对比js、php和c的for循环
为什么要写这篇文章呢?主要是给自己提个醒,js的水很深,需要小心点儿才能趟过去,更何况自己不是专业人士,那就得更加小心了. 看下面的js代码: <!DOCTYPE html> <ht ...
- 【分布式】Zookeeper序列化及通信协议
一.前言 前面介绍了Zookeeper的系统模型,下面进一步学习Zookeeper的底层序列化机制,Zookeeper的客户端与服务端之间会进行一系列的网络通信来实现数据传输,Zookeeper使用J ...
- react入门(3)
在第一篇文章里我们介绍了jsx.组件.css写法 点击查看react入门(1) 第二篇文章里我们介绍了事件.this.props.children.props....other.map循环 点击查 ...
- iOS UIGestureRecognizer与UIMenuController(内容根据iOS编程)
UIGestureRecognizer 对象会截取本应由视图处理的触摸事件.当某个UIGestureRecognizer对象识别出特定的手势后,就会向指定的对象发送指定的消息.iOS SDK默认提供若 ...
- 记录软件工程课程项目开发时遇到的各种小问题(django)
1.python manage.py makemigrations 无效/无法检测出model的变化 在修改了models.py之后,我们想要更新数据库的表,使用了python manage.py m ...
- React Native组件介绍
1.React Native目前已有的组件 ActivityIndicatorIOS:标准的旋转进度轮; DatePickerIOS:日期选择器: Image:图片控件: ListView:列表控件: ...
- 学习之路~sqh
推荐博客 Edison Chou: Vamei: 算法∙面试专题 - 简书: 设计模式 极速理解设计模式系列[目录索引]- Caleung: Net设计模式 - 灵动生活: 宅男程序员给老婆的计算机课 ...