嵌入式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. 挂载设备. 读写设备 . 驱动程序代码: /***************** ...
随机推荐
- DDD 领域驱动设计-领域模型中的用户设计
上一篇:<DDD 领域驱动设计-如何控制业务流程?> 开源地址:https://github.com/yuezhongxin/CNBlogs.Apply.Sample(代码已更新,并增加了 ...
- Oracle数据库文件路径变更
环境:RHEL 6.4 + Oracle 11.2.0.3 情景一:只是部分普通数据文件迁移,可以在线操作. 1.将对应表空间offline,移动数据文件到新路径 2.数据文件alter databa ...
- SQL实用
实用的SQL语句 行列互转 create table test(id int,name varchar(20),quarter int,profile int) insert into test ...
- Properties操作指南
一.简介: Properties是java中用的比较多的一个类,表示一个持久的属性集.继承于Hashtable,Properties可从流中加载,也可保存在流中.属性列表中每个键极其对应值共同组成一个 ...
- 通过Http接口及SolrNet 两种方法基于Solr5.5.1 实现CURD
前言 老规矩,任何技术的入门我通常都会总结增删改查,本文我就通过HttpWebRequest和SolrNet的方式实现Solr最基础的增删改查(CURD).对于自己的完整项目,同时不想过于依赖第三方类 ...
- zeroclipboard浏览器复制插件使用记录
一个简单例子: <html> <body> <button id="copy-button" data-clipboard-text="Co ...
- Delphi_03_Delphi_Object_Pascal_基本语法_01
这次是一个基本语法的第一部分,包括变量.变量初始化.常量.运算符.字符串等内容. { 本程序演示 Delphi Pascal 的基本语法 1.变量及变量的初始化 2.常量 3.运算符 3. 4. } ...
- 【译】Core Java Questions and Answers【1-33】
前言 译文链接:http://www.journaldev.com/2366/core-java-interview-questions-and-answers Java 8有哪些重要的特性 Java ...
- [连载]《C#通讯(串口和网络)框架的设计与实现》- 6.通讯控制器的设计
目 录 第六章 通讯控制器的设计... 2 6.1 控制器接口... 2 6.2 串口控制器... 3 6.3 ...
- 中国式商业智能报表ActiveReports免费公开课,10月20日开讲
ActiveReports公开课全方位报表解决方案,满足商业报表五大需求 [开课时间]10月20日[主讲老师]葡萄城报表产品经理[开课形式]网络在线公开课[活动费用]前50名免费 适合人群:报表开发人 ...