生成设备节点

  • 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)--生成设备节点相关推荐

  1. linux设备和驱动注册,Linux驱动第五篇-----驱动注册和生成设备节点

    加载驱动的指令是:insmod xx.ko 查看驱动的指令是: lsmod 卸载驱动的指令是:rmmod xx 在include/linux/platform_device.h这个文件中定义了平台驱动 ...

  2. Linux驱动开发---杂项设备

    一.基本概念 Linux设备驱动类型: 字符设备:字符设备是能够像字节流一样被访问的设备. 一般说来对硬件设备 IO 的操作可以归结为字符设备. 常见的字符设备有 led. 蜂鸣器. 串口. 键盘等: ...

  3. linux驱动之字符设备

    linux驱动之字符设备 linux驱动设备分类 linux驱动分为了三种驱动: 字符设备: 字符设备和应用程序之间是以字节进行进行数据交换的.在进行数据交换的时候数据是以一定顺序进行传输的,传输是实 ...

  4. linux uart寄存器 代替 printk,Linux驱动学习之设备树(设备树下的LED驱动实验),...

    Linux驱动学习之设备树(设备树下的LED驱动实验), 概念 Linux内核从3.x开始引入设备树的概念,用于实现驱动代码与设备信息相分离.相当于从驱动代码分离出来的配置文件,比如串口的波特率通过设 ...

  5. Linux驱动之字符设备驱动

    系列文章目录 第一章 Linux入门之驱动框架 第二章 Linux驱动之字符设备驱动 文章目录 系列文章目录 前言 一.认识字符设备驱动 1.基本概念 2.基本概念 二.字符设备旧框架 1.注册和注销 ...

  6. 【linux驱动之字符设备驱动基础】

    linux驱动之字符设备驱动基础 文章目录 linux驱动之字符设备驱动基础 前言 一.开启驱动学习之路 二.驱动预备知识 三.什么是驱动? 3.1 驱动概念 3.2 linux 体系架构 3.3 模 ...

  7. 【Linux驱动开发】设备树详解(二)设备树语法详解

    ​ 活动地址:CSDN21天学习挑战赛 [Linux驱动开发]设备树详解(一)设备树基础介绍 [Linux驱动开发]设备树详解(二)设备树语法详解 [Linux驱动开发]设备树详解(三)设备树Kern ...

  8. Linux Shell 判断块设备节点是否存在

    /************************************************************************** Linux Shell 判断块设备节点是否存在* ...

  9. linux用户空间flash驱动,全面掌握Linux驱动框架——字符设备驱动、I2C驱动、总线设备驱动、NAND FLASH驱动...

    原标题:全面掌握Linux驱动框架--字符设备驱动.I2C驱动.总线设备驱动.NAND FLASH驱动 字符设备驱动 哈~ 这几天都在发图,通过这种方式,我们希望能帮大家梳理学过的知识,全局的掌握Li ...

最新文章

  1. [题解]洛谷P1119 灾后重建
  2. mysql 的select语句_MYSQL SELECT语句新手
  3. c语言mc协议,easymc - C语言开发的简易消息通道库
  4. 出现ping: unknown host www.baidu.com 问题解决
  5. 解决conda install安装arch报错的问题
  6. python 同步event对象
  7. 十大必须掌握的 Chrome 浏览器开发者工具
  8. 第一次没有写出来的SQL
  9. android mediaplayer单曲循环播放,android mediaplayer永远在ICS上循环播放
  10. STL之容器deque
  11. 大咖访谈丨金星分享2020年直播数据,助农产品如何走上产销快车道
  12. 日立6TB充氦硬盘详细规格、实物照片
  13. 软件评测师题库--程序语言基础知识
  14. 使用c语言判断是闰年还是平年
  15. 【转】王怡 自由主义的书单
  16. 微信小程序账号长时间未登录冻结解封
  17. MATLAB面板数据空间计量模型估计代码④
  18. 现在是做一个站长博客好还是做一个站长论坛好?
  19. 一个真实项目的性能分析策略
  20. 【剑桥英语I优加】剑桥ket考试适合几年级的孩子

热门文章

  1. Mac安装metasploit-framework【亲测有用】
  2. 软考高级论文如何“吹”
  3. css设置元素继承父元素宽度_详解CSS中的百分比的应用
  4. o oia ospf 路由优先_乾颐堂军哥HCIE课程4-OSPF的3、4、5类LSA以及虚连接和转发地址的理论与实践...
  5. php 统计二维数组次数最多_前端面试题(数组篇)
  6. 数据库SQL命令经典面试题65道
  7. OO第二单元(电梯)单元总结
  8. 在InternetExplorer.Application中显示本地图片
  9. 模块(module)
  10. ASP.NET中的FILE对象总结