Linux驱动(11)--生成设备节点
生成设备节点
- 1. 生成设备节点
- 1.1 杂项设备
- 1.2 注册文件
- 1.3 生成设备节点源代码
- 1.4 生成设备节点步骤
- 1.5 需要注意的问题
- 2. 调用设备节点
1. 生成设备节点
1.1 杂项设备
所有的设备都有自己的设备号,我们可以利用命令:
cat /proc/devices
来观察设备号:
一共255个设备号,这些都是主设备号,这显然不够用的。所以很多驱动都挂载在杂线设备的下面,也就是设备号为10的misc下面,这样可以节省主设备号,而且这样可以减少一步注册主设备号的过程。
1.2 注册文件
杂项设备的初始化部分源文件“drivers/char/misc.c”,里面内容就是给字符驱动做一个简单的封装。注册文件在:
/LinuxKernelPath/include/linux/miscdevice.h
中,结构体miscdevice以及注册函数如下所示:
struct miscdevice {int minor;const char *name;const struct file_operations *fops;struct list_head list;struct device *parent;struct device *this_device;const char *nodename;mode_t mode;
};
extern int misc_register(struct miscdevice * misc);
extern int misc_deregister(struct miscdevice *misc);
其中我们要用到的参数为:
.minor:设备号
.name:生成设备节点的名称
.fops:指向一个设备节点文件
1.3 生成设备节点源代码
生成设备节点的例程在Linux驱动(10)中的基础上添加的:
/*
Name:Device_Node.c
Author:Ethan
Version:1.0
Date:2019-11-30
*//*包含初始化宏定义的头文件,代码中的module_init和module_exit再次文件中)*/
#include<linux/init.h>
/*包含初始化加载模块的头文件,代码中的MODULE_LICENSE在此头文件中*/
#include<linux/module.h>
/*驱动注册的头文件,包含驱动的结构体以及注册和卸载的函数*/
#include<linux/platform_device.h>
/*注册杂项设备头文件*/
#include <linux/miscdevice.h>
/*注册设备节点的文件结构体*/
#include <linux/fs.h>/*声明驱动名称*/
#define DRIVER_NAME "helloworld_ctl"
/*声明设备节点名称*/
#define DEVICE_NAME "helloworld_node_ctl"/*声明是开源的,没有内核版本限制*/
MODULE_LICENSE("Dual BSD/GPL");
/*声明作者*/
MODULE_AUTHOR("Ethan");/*定义文档打开函数*/
static int device_node_open(struct inode *inode, struct file *file){printk(KERN_EMERG "Hello open! \n");return 0;
} /*定义文档关闭函数*/
static int device_node_release(struct inode *inode, struct file *file){printk(KERN_EMERG "Hello release! \n");return 0;
} /*定义IO控制函数*/
static long device_node_ioctl(struct file *file, unsigned int cmd, unsigned long arg){printk("cmd is %d, arg is %d \n",cmd,arg);return 0;
} /*定义文件操作结构体*/
struct file_operations ops_device_node = {.owner = THIS_MODULE,.open = device_node_open,.release = device_node_release,.unlocked_ioctl = device_node_ioctl,
};/*定义杂项设备节点结构体*/
struct miscdevice misc_device_node = {/*自动分配设备号*/.minor = MISC_DYNAMIC_MINOR,/*生成设备节点名称*/.name = DEVICE_NAME,/*指向一个设备节点文件*/.fops= &ops_device_node,
};/*定义驱动的probe函数*/
static int hello_probe(struct platform_device *pdv){/*打印信息,KERN_KMERG表示紧急信息*/printk(KERN_EMERG "Hello probe! \n");/*注册杂项设备*/misc_register(&misc_device_node);return 0;
}/*定义驱动的remove函数*/
static int hello_remove(struct platform_device *pdv){/*打印信息,KERN_KMERG表示紧急信息*/printk(KERN_EMERG "Hello remove! \n");/*移除杂项设备*/misc_deregister(&misc_device_node);return 0;
}/*定义驱动的shutdown函数*/
static void hello_shutdown(struct platform_device *pdv){/*打印信息,KERN_KMERG表示紧急信息*/printk(KERN_EMERG "Hello shutdown! \n");}/*定义驱动的suspend函数*/
static int hello_suspend(struct platform_device *pdv){/*打印信息,KERN_KMERG表示紧急信息*/printk(KERN_EMERG "Hello suspend! \n");return 0;
}/*定义驱动的resume函数*/
static int hello_resume(struct platform_device *pdv){/*打印信息,KERN_KMERG表示紧急信息*/printk(KERN_EMERG "Hello resume! \n");return 0;
}/*定义驱动结构体*/
struct platform_driver helloworld_driver = {.probe = hello_probe,.remove = hello_remove,.shutdown = hello_shutdown,.suspend = hello_suspend,.resume = hello_resume,.driver ={.name = DRIVER_NAME,.owner = THIS_MODULE,}
};/*编写初始化函数*/
static int hello_init(void)
{/*定义驱动状态变量*/int driverState;/*打印hello world,KERN_KMERG表示紧急信息*/printk(KERN_EMERG "Hello World! \n");/*注册helloworld驱动*/driverState = platform_driver_register(&helloworld_driver);/*打印驱动注册状态,KERN_KMERG表示紧急信息*/printk(KERN_EMERG "driverState is %d! \n",driverState);return 0;
}//编写卸载函数
static void hello_exit(void)
{/*打印see you,KERN_KMERG表示紧急信息*/printk(KERN_EMERG "See you!\n");/*卸载helloworld驱动*/platform_driver_unregister(&helloworld_driver);}/*初始化函数*/
module_init(hello_init);
/*卸载函数*/
module_exit(hello_exit);
1.4 生成设备节点步骤
注册设备的步骤为下:
① 将Device_Node.c和Makefile文件移动到linux系统中的某一文件夹下(任意地方或者新建都可以)。
② 执行命令:
make
执行完毕之后可以在该文件夹下生成.ko文件,该文件就是编译生成的驱动。
③ 我们通过开发板来验证该驱动是否编写与编译成功:
—>将.ko文件拷贝到U盘中
—>用命令
mount /dev/sda1 /mnt/disk/
将U盘挂载。
—>可以用命令
ls /mnt/disk/
来列出已经编译成功的.ko文件
—>用加载命令,来加载我们编译好的驱动
insmod /mnt/disk/Device_Module.ko
结果为:
然我们使用命令:
ls /dev
观察我们生成的设备节点为:
1.5 需要注意的问题
设备节点是跟着驱动注册一起生成的,它放在驱动注册的prob函数中,切记,只有当驱动与设备名称一致时,设备节点才能注册成功!
2. 调用设备节点
调用设备节点就是将我们刚注册的设备节点helloworld_node_ctl当做文件来读取,源文件如下所示:
/*
Name:Device_Node_calls.c
Author:Ethan
Version:1.0
Date:2019-11-30
*/
/*调用打印函数printf*/
#include <stdio.h>
/*基本系统数据类型*/
#include <sys/types.h>
/*系统调用函数头文件,可以调用普通文件、目录、管道、socket、字符、块的属性*/
#include <sys/stat.h>
/*定义了open函数*/
#include <fcntl.h>
/*定义了close函数*/
#include <unistd.h>
/*定义了ioctl函数*/
#include <sys/ioctl.h>main(){/*定义文件句柄*/int fd;/*定义了设备节点的路径*/char *hello_node = "/dev/helloworld_node_ctl";/*O_RDWR只读打开,O_NDELAY非阻塞方式*/ if((fd = open(hello_node,O_RDWR|O_NDELAY))<0){printf("APP open %s failed",hello_node);}else{printf("APP open %s success",hello_node);/*向节点传递参数*/ioctl(fd,1,6);}close(fd);
}
调用设备节点的步骤请参考之前的博文:Linux基础(3)–搭建最小的Linux系统
Linux驱动(11)--生成设备节点相关推荐
- linux设备和驱动注册,Linux驱动第五篇-----驱动注册和生成设备节点
加载驱动的指令是:insmod xx.ko 查看驱动的指令是: lsmod 卸载驱动的指令是:rmmod xx 在include/linux/platform_device.h这个文件中定义了平台驱动 ...
- Linux驱动开发---杂项设备
一.基本概念 Linux设备驱动类型: 字符设备:字符设备是能够像字节流一样被访问的设备. 一般说来对硬件设备 IO 的操作可以归结为字符设备. 常见的字符设备有 led. 蜂鸣器. 串口. 键盘等: ...
- linux驱动之字符设备
linux驱动之字符设备 linux驱动设备分类 linux驱动分为了三种驱动: 字符设备: 字符设备和应用程序之间是以字节进行进行数据交换的.在进行数据交换的时候数据是以一定顺序进行传输的,传输是实 ...
- linux uart寄存器 代替 printk,Linux驱动学习之设备树(设备树下的LED驱动实验),...
Linux驱动学习之设备树(设备树下的LED驱动实验), 概念 Linux内核从3.x开始引入设备树的概念,用于实现驱动代码与设备信息相分离.相当于从驱动代码分离出来的配置文件,比如串口的波特率通过设 ...
- Linux驱动之字符设备驱动
系列文章目录 第一章 Linux入门之驱动框架 第二章 Linux驱动之字符设备驱动 文章目录 系列文章目录 前言 一.认识字符设备驱动 1.基本概念 2.基本概念 二.字符设备旧框架 1.注册和注销 ...
- 【linux驱动之字符设备驱动基础】
linux驱动之字符设备驱动基础 文章目录 linux驱动之字符设备驱动基础 前言 一.开启驱动学习之路 二.驱动预备知识 三.什么是驱动? 3.1 驱动概念 3.2 linux 体系架构 3.3 模 ...
- 【Linux驱动开发】设备树详解(二)设备树语法详解
活动地址:CSDN21天学习挑战赛 [Linux驱动开发]设备树详解(一)设备树基础介绍 [Linux驱动开发]设备树详解(二)设备树语法详解 [Linux驱动开发]设备树详解(三)设备树Kern ...
- Linux Shell 判断块设备节点是否存在
/************************************************************************** Linux Shell 判断块设备节点是否存在* ...
- linux用户空间flash驱动,全面掌握Linux驱动框架——字符设备驱动、I2C驱动、总线设备驱动、NAND FLASH驱动...
原标题:全面掌握Linux驱动框架--字符设备驱动.I2C驱动.总线设备驱动.NAND FLASH驱动 字符设备驱动 哈~ 这几天都在发图,通过这种方式,我们希望能帮大家梳理学过的知识,全局的掌握Li ...
最新文章
- [题解]洛谷P1119 灾后重建
- mysql 的select语句_MYSQL SELECT语句新手
- c语言mc协议,easymc - C语言开发的简易消息通道库
- 出现ping: unknown host www.baidu.com 问题解决
- 解决conda install安装arch报错的问题
- python 同步event对象
- 十大必须掌握的 Chrome 浏览器开发者工具
- 第一次没有写出来的SQL
- android mediaplayer单曲循环播放,android mediaplayer永远在ICS上循环播放
- STL之容器deque
- 大咖访谈丨金星分享2020年直播数据,助农产品如何走上产销快车道
- 日立6TB充氦硬盘详细规格、实物照片
- 软件评测师题库--程序语言基础知识
- 使用c语言判断是闰年还是平年
- 【转】王怡 自由主义的书单
- 微信小程序账号长时间未登录冻结解封
- MATLAB面板数据空间计量模型估计代码④
- 现在是做一个站长博客好还是做一个站长论坛好?
- 一个真实项目的性能分析策略
- 【剑桥英语I优加】剑桥ket考试适合几年级的孩子
热门文章
- Mac安装metasploit-framework【亲测有用】
- 软考高级论文如何“吹”
- css设置元素继承父元素宽度_详解CSS中的百分比的应用
- o oia ospf 路由优先_乾颐堂军哥HCIE课程4-OSPF的3、4、5类LSA以及虚连接和转发地址的理论与实践...
- php 统计二维数组次数最多_前端面试题(数组篇)
- 数据库SQL命令经典面试题65道
- OO第二单元(电梯)单元总结
- 在InternetExplorer.Application中显示本地图片
- 模块(module)
- ASP.NET中的FILE对象总结