之前讲的字符设备驱动程序,只要有一个主设备号,那么次设备号无论是什么都会和同一个 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驱动学习之路(二十七)字符设备驱动的另一种写法的更多相关文章

  1. 嵌入式Linux驱动学习之路(二十一)字符设备驱动程序总结和块设备驱动程序的引入

    字符设备驱动程序 应用程序是调用C库中的open read write等函数.而为了操作硬件,所以引入了驱动模块. 构建一个简单的驱动,有一下步骤. 1. 创建file_operations 2. 申 ...

  2. 嵌入式Linux驱动学习之路(二十)USB设备驱动

    USB在接入系统的时候,以0的设备ID和主机通信,然后由主机为其分配新的ID. 在主机端,D+和D-都是下拉接地的.而设备端的D-接上拉时,表明此设备为高速设备:12M/s. D+接上拉时则是全速设备 ...

  3. Linux USB驱动学习总结(二)---- USB设备驱动

    USB 设备驱动: 一.USB 描述符:(存在于USB 的E2PROM里面) 1.  设备描述符:struct usb_device_descriptor 2.  配置描述符:struct usb_c ...

  4. Linux驱动实践:你知道【字符设备驱动程序】的两种写法吗?

    作 者:道哥,10+年嵌入式开发老兵,专注于:C/C++.嵌入式.Linux. 关注下方公众号,回复[书籍],获取 Linux.嵌入式领域经典书籍:回复[PDF],获取所有原创文章( PDF 格式). ...

  5. 嵌入式Linux驱动学习之路(二十四)Nor Flash驱动程序

    Nor Flash和Nand Flash的不同: 类型 NOR Flash  Nand Flash  接口 RAM-like,引脚多 引脚少 容量 小(1M.2M...) 大(512M.1G) 读 简 ...

  6. 嵌入式Linux驱动学习之路(二十五)虚拟网卡驱动程序

    一.协议栈层次对比 设备无关层到驱动层的体系结构 1).网络协议接口层向网络层协议提供提供统一的数据包收发接口,不论上层协议为ARP还是IP,都通过dev_queue_xmit()函数发送数据,并通过 ...

  7. 嵌入式Linux驱动学习之路(二十三)NAND FLASH驱动程序

    NAND FLASH是一个存储芯片. 在芯片上的DATA0-DATA7上既能传输数据也能传输地址. 当ALE为高电平时传输的是地址. 当CLE为高电平时传输的是命令. 当ALE和CLE都为低电平时传输 ...

  8. 嵌入式linux的学习之路[转]

    我认为的一条学习嵌入式Linux的路: 1)学习 Linux系统安装. 常用命令.应用程序安装. 2) 学习 Linux 下的 C 编程.这本书必学<UNIX 环境高级编程>.<UN ...

  9. 嵌入式Linux驱动学习之路(二十二)用内存模拟磁盘

    安装驱动后,可在/dev/目录下发现已经生成了相应的设备文件. 格式化设备:mkdosfs /dev/ramblock. 挂载设备. 读写设备 . 驱动程序代码: /***************** ...

随机推荐

  1. .NET Core的文件系统[1]:读取并监控文件的变化

    ASP.NET Core 具有很多针对文件读取的应用.比如我们倾向于采用JSON文件来定义配置,所以应用就会涉及针对配置文件读取.如果用户发送一个针对物理文件的HTTP请求,应用会根据指定的路径读取目 ...

  2. 设计模式(三):“花瓶+鲜花”中的装饰者模式(Decorator Pattern)

    在前两篇博客中详细的介绍了"策略模式"和“观察者模式”,今天我们就通过花瓶与鲜花的例子来类比一下“装饰模式”(Decorator Pattern).在“装饰模式”中很好的提现了开放 ...

  3. 日常css技巧小结(1)--背景透明度改变对内容无影响

    刚开始出现的错误,内容会受到背景透明度改变的影响:如图: 代码: <!DOCTYPE html> <html lang="en"> <head> ...

  4. C站投稿189网盘视频源(UP主篇)

    C站投稿189网盘视频源(UP主篇) 现在C站(吐槽弹幕网)的视频来源基本靠的都是189网盘,比如番剧区的每个视频基本来源于此,不像AB两站,拥有自己的资源服务器,为啥呢?没钱啊.都是外来的视频.本站 ...

  5. ASP.NET Core 中文文档 第二章 指南(4.8)添加新的字段

    原文 Adding a New Field 作者 Rick Anderson 翻译 谢炀(Kiler) 校对 许登洋(Seay).高嵩(Jack) 在这个章节你将使用 Entity Framework ...

  6. Rafy 框架 - 插件级别的扩展点

    本章说明如何使用额外的插件(如客户化插件)对另一插件(如产品插件)进行扩展.   使用场景 在 产品线工程 中,项目的研发分为领域工程和应用工程.这个过程中会需要对领域工程中的内容进行大量的扩展.   ...

  7. 文本框focus之后高亮背景颜色

    看效果:Html: CSS: jQuery: 或者使用连写法:

  8. 制作CAB包

    制作CAB包 inf文件 INF是Device INFormation File的英文缩写,是Microsoft公司为硬件设备制造商发布其驱动程序推出的一种文件格式,INF文件中包含硬件设备的信息或脚 ...

  9. C语言实现2个大数相加。

    #include<stdio.h>#include<string.h>int main(){    char s1[100],s2[100];    int num1[31], ...

  10. 随便记录下系列 - node->express

    随便记录下系列 - node->express 文章用啥写?VsCode. 代码用啥写?VsCode. 编辑器下载:VsCode 一.windows下安装node.js环境: 下载地址 相比以前 ...