嵌入式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. 挂载设备. 读写设备 . 驱动程序代码: /***************** ...
随机推荐
- 设计模式(五): 简单而又不失其重要性的单例模式(Singleton Pattern)
上篇博客我们系统的介绍了三种工厂模式,今天我们就来介绍一下单例模式.单例模式虽然简单,但是还是比较重要的,是常用设计模式之一.在之前的博客<Objective-C中的单例模式>中介绍了Ob ...
- linux2.6 内存管理——概述
在紧接着相当长的篇幅中,都是围绕着Linux如何管理内存进行阐述,在内核中分配内存并不是一件非常容易的事情,因为在此过程中必须遵从内核特定的状态约束.linux内存管理建立在基本的分页机制基础上,在l ...
- c 网络与套接字socket
我们已经知道如何使用I/O与文件通信,还知道了如何让同一计算机上的两个进程进行通信,这篇文章将创建具有服务器和客户端功能的程序 互联网中大部分的底层网络代码都是用C语言写的. 网络程序通常有两部分组成 ...
- FFmpeg学习1:视频解码
在视频解码前,先了解以下几个基本的概念: 编解码器(CODEC):能够进行视频和音频压缩(CO)与解压缩(DEC),是视频编解码的核心部分. 容器/多媒体文件(Container/File):没有了解 ...
- C#开机自动启动程序代码
新建一个winform拖一个checkbox进来.. 然后设置它的changed事件. 已经测试过,可以直接复制使用. private void checkBox1_CheckedChanged(ob ...
- HTML基础标签
[HTML写法标签][HTML字体段落标签][锚点][有序无序列表][表格] 一.HTML写法标签:双标签:<标签名>内容</标签名>单标签:<标签名 内容/> 二 ...
- 2017Windows下安装pip
-------------------------------------------- 下载地址: https://pypi.python.org/pypi/pip#downloads 下载颜色那 ...
- java抽象类和接口
面向对象设计过程中重要的一点是如何进行抽象,即把"问题空间"中的元素与"方案空间"中的元素建立理想的一对一的映射关系.抽象类和接口便是抽象过程中的产物. ...
- MongoDB集群卡死问题
一年前搭了个MongoDB集群,跑得还算不错,但是有几次遇到过服务卡死的问题.处理起来已经得心应手了,拿来跟大家分享一下: 故障现象: 业务查询缓慢,而且会有连接异常: { "serverU ...
- redis 安装
安装wget http://download.redis.io/releases/redis-3.2.3.tar.gztar -xzvf redis-3.2.3.tar.gzcd redis-3.2. ...