嵌入式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. 挂载设备. 读写设备 . 驱动程序代码: /***************** ...
随机推荐
- 中文分词工具探析(二):Jieba
1. 前言 Jieba是由fxsjy大神开源的一款中文分词工具,一款属于工业界的分词工具--模型易用简单.代码清晰可读,推荐有志学习NLP或Python的读一下源码.与采用分词模型Bigram + H ...
- 1元搭建自己的云服务器&解析域名
最近在学做微信开发,没有自己的域名和服务器就不得不寄人篱下,索性自己就到云主机上搭建了个服务器,但是水平有限弄了一个下午~~有自己的域名和服务器的好处相信不用我多说了.比如日后可以有自己域名的个性博客 ...
- js正则表达式校验正数、负数、和小数:^(\-|\+)?\d+(\.\d+)?$
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- 【C#公共帮助类】 WebHelper帮助类
如果你是一个新手,如果你刚接触MVC,如果你跟着置顶的那个项目,我们肯定会用到这里面的几个帮助类 它们都在Common类库下,大家一定要记住要点:取其精华去其糟粕,切勿拿来主义~ Applicatio ...
- svn 提交代码报错
svn 提交代码报错 最近新安装了TortoiseSvn 1.92,在上传代码,其中有新增加的文件,出现如下错误: 解决方法: 1.用vs生成patch文件 2.生成的patch文件中讲nonexis ...
- html
有目标的学知识才行 要学习html语言,我突然发现我好像可以在markdown文本编辑器中编辑html标签,既然这样我就多玩玩.markdown完全兼容html,这真的是一个好事情.好像也有功能在ma ...
- java反射复制属性值
/** 将sourceObj的属性拷贝到targetObj * @param sourceObj * @param targetObj * @param clazz 从哪一个类开始(比如sourceO ...
- quartz CronExpression表达式
一个cron表达式有至少6个(也可能7个)有空格分隔的时间元素.按顺序依次为1.秒(0~59)2.分钟(0~59)3.小时(0~23)4.天(月)(0~31,但是你需要考虑你月的天数)5.月(0~11 ...
- Atitit.兼具兼容性和扩展性的配置方案attilax总结
Atitit.兼具兼容性和扩展性的配置方案attilax总结 文件配置法1 Jdbc多数据源文件配置发1 Bat文件配置法1 改进的文件配置法(采用类似i18n技术) 推荐1 使用自动化pc_id的方 ...
- SQL Server游标(转)
清晰地介绍了SQL游标,很好的学习资料. 转自 http://www.cnblogs.com/knowledgesea/p/3699851.html 什么是游标 结果集,结果集就是select查询之后 ...