linux设备和驱动注册,Linux驱动第五篇-----驱动注册和生成设备节点
加载驱动的指令是:insmod xx.ko
查看驱动的指令是: lsmod
卸载驱动的指令是:rmmod xx
在include/linux/platform_device.h这个文件中定义了平台驱动注册和卸载文件函数
platform_driver_register 和 platform_driver_unregister 函数
这个两个函数参数调用了结构体platform_driver
该结构中包含了一组操作函数和一个 struct device_driver 的对像。在驱动中首先要做的
就是定义 platform_driver 中的函数,并创建这个结构的一个对象实例, 然后在 init()函数中调用
platform_driver_register()向系统注册驱动。
函数 int (*probe)(struct platform_device *);
主要是进行设备的探测和初始化。例如想调用一个 GPIO,那么首先需要探测这个 GPIO 是
否被占用了,如果被占用了那么初始化失败,驱动注册也就失败了;如果没有被占用,那么就
申明要占用它。该函数中一般还会添加生成设备节点的函数,如果初始化成功,那么就会需要添加设备节点。
函数 int (*remove)(struct platform_device *);
移除驱动,该函数中一般用于去掉设备节点或者释放软硬件资源
void (*shutdown)(struct platform_device *);
int (*suspend)(struct platform_device *, pm_message_t state);
int (*resume)(struct platform_device *);
从字面上就很好理解了,关闭驱动,悬挂(休眠)驱动以及恢复的时候该驱动要做什么
接着的结构体 struct device_driver driver;
主要包含两个参数,一个是 name 参数,驱动名称(需要和设备驱动结构体中的 name 参
数一样,这点很重要);一个是 owner,一般是 THIS_MODULE。
接下来编写驱动代码:
#include #include /*驱动注册的头文件,包含驱动的结构体和注册和卸载的函数*/
#include #define DRIVER_NAME "hello_ctl" //这个和前面设备的注册的hello结构体里面的名字相同
MODULE_LICENSE("Dual BSD/GPL");
MODULE_AUTHOR("TOPEET");
static int hello_probe(struct platform_device *pdv){
printk(KERN_EMERG "\tinitialized\n");
return 0;
}
static int hello_remove(struct platform_device *pdv){
return 0;
}
static void hello_shutdown(struct platform_device *pdv){
;
}
static int hello_suspend(struct platform_device *pdv){
return 0;
}
static int hello_resume(struct platform_device *pdv){
return 0;
}
struct platform_driver hello_driver = {
.probe = hello_probe,
.remove = hello_remove,
.shutdown = hello_shutdown,
.suspend = hello_suspend,
.resume = hello_resume,
.driver = {
.name = DRIVER_NAME, //和devices名称相同
.owner = THIS_MODULE,
}
};
static int hello_init(void)
{
int DriverState;
printk(KERN_EMERG "HELLO WORLD enter!\n");
DriverState = platform_driver_register(&hello_driver); //然后在模块入口调用platform_driver_register
printk(KERN_EMERG "\tDriverState is %d\n",DriverState);
return 0;
}
static void hello_exit(void)
{
printk(KERN_EMERG "HELLO WORLD exit!\n");
platform_driver_unregister(&hello_driver);//在函数的出口调用platform_driver_unregister
}
module_init(hello_init);
module_exit(hello_exit);
如果设备和驱动匹配成功就会进入函数 hello_probe 打印“initialized
接着需要编写一下 Makefile 文件
#!/bin/bash
obj-m += probe_linux_module.o //文件名
#源码目录变量,这里用户需要根据实际情况选择路径
KDIR := /home/birate/topeet/iTop4412_Kernel_3.0 #linux源码目录
#当前目录变量
PWD ?= $(shell pwd)
#make命名默认寻找第一个目标
#make -C就是指调用执行的路径
#$(KDIR)Linux源码目录
#$(PWD)当前目录变量
#modules要执行的操作
all:
make -C $(KDIR) M=$(PWD) modules
#make clean执行的操作是删除后缀为o的文件
clean:
rm -rf *.o
使用make编译,生成模块文件probe_linux_module.ko
然后使用adb push probe_linux_module.ko /data 放到arm系统的/data目录下
之后加载insmod probe_linux_module.ko
如果没有错误将会打印initialized等内容
之后查看设备
卸载设备
后面我们生成杂项设备节点
杂项设备节点在include/linux/miscdevice.h这个文件中,我们也可以使用cat /proc/misc查看对应的杂项设备
extern int misc_register(struct miscdevice * misc);
杂项设备注册函数;一般在 probe 中调用,参数是 miscdevice
extern int misc_deregister(struct miscdevice *misc);
杂项设备卸载函数;一般是在 hello_remove 中用于卸载驱动
结构体 miscdevice 中参数很多,下面几个是常用的。
int .minor;设备号,赋值为 MISC_DYNAMIC_MINOR,这个宏定义可以查到为 10
const char *name;设备名称
const struct file_operations *fops
file_operations 结构体在头文件“include/linux/fs.h”中,如下图所示,使用命令“vim
include/linux/fs.h”打开头文件。
查找file_operations
struct module *owner;一般是 THIS_MODULE。
int (*open) (struct inode *, struct file *);对应上层的 open 函数,打开文件。
int (*release) (struct inode *, struct file *);对应上层的 close 函数,打开文件操作之后一
般需要关闭。
ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);读函数,上层应用从底层读取
函数。
ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);写函数,上层应用向底
层传输数据。
long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);这个函数功能和写
函数稍微有点重合,但是这个函数占用的内存非常小,主要针对 IO 口的控制
#include #include /*驱动注册的头文件,包含驱动的结构体和注册和卸载的函数*/
#include /*注册杂项设备头文件*/
#include /*注册设备节点的文件结构体*/
#include #define DRIVER_NAME "hello_ctl"
#define DEVICE_NAME "hello_ctl123" //杂项节点名称
MODULE_LICENSE("Dual BSD/GPL");
static long hello_ioctl( struct file *files, unsigned int cmd, unsigned long arg){
printk("cmd is %d,arg is %d\n",cmd,arg);
return 0;
}
static int hello_release(struct inode *inode, struct file *file){
printk(KERN_EMERG "hello release\n");
return 0;
}
static int hello_open(struct inode *inode, struct file *file){
printk(KERN_EMERG "hello open\n");
return 0;
}
static struct file_operations hello_ops = { //定义file_operations 参数
.owner = THIS_MODULE,
.open = hello_open,
.release = hello_release,
.unlocked_ioctl = hello_ioctl,
};
static struct miscdevice hello_dev = {
.minor = MISC_DYNAMIC_MINOR, //参数 minor 为 MISC_DYNAMIC_MINOR,也就是 10
.name = DEVICE_NAME,//参数 name 为 DEVICE_NAME,也就是 hello_ctl123
.fops = &hello_ops,//参数 fops 为“hello_ops”
};
static int hello_probe(struct platform_device *pdv){
printk(KERN_EMERG "\tinitialized\n");
misc_register(&hello_dev); 向添加 hello_probe 中添加注册杂项设备的函数 misc_register,如下图所示,
将 miscdevice 参数定义为 hello_dev
return 0;
}
static int hello_remove(struct platform_device *pdv){
printk(KERN_EMERG "\tremove\n");
misc_deregister(&hello_dev);
return 0;
}
static void hello_shutdown(struct platform_device *pdv){
;
}
static int hello_suspend(struct platform_device *pdv,pm_message_t pmt){
return 0;
}
static int hello_resume(struct platform_device *pdv){
return 0;
}
struct platform_driver hello_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;
printk(KERN_EMERG "HELLO WORLD enter!\n");
DriverState = platform_driver_register(&hello_driver);
printk(KERN_EMERG "\tDriverState is %d\n",DriverState);
return 0;
}
static void hello_exit(void)
{
printk(KERN_EMERG "HELLO WORLD exit!\n");
platform_driver_unregister(&hello_driver);
}
module_init(hello_init);
module_exit(hello_exit);
修改makefile函数
#!/bin/bash
obj-m += devicenode_linux_module.o
#源码目录变量,这里用户需要根据实际情况选择路径
KDIR := /home/topeet/android4.0/iTop4412_Kernel_3.0
#当前目录变量
PWD ?= $(shell pwd)
#make命名默认寻找第一个目标
#make -C就是指调用执行的路径
#$(PWD)当前目录变量
#modules要执行的操作
all:
make -C $(KDIR) M=$(PWD) modules
#make clean执行的操作是删除后缀为o的文件
clean:
rm -rf *.o
生成.ko文件
传到 /data目录中
加载驱动 在/dev查看设备节点
已经生成了设备节点
卸载 完成
linux设备和驱动注册,Linux驱动第五篇-----驱动注册和生成设备节点相关推荐
- CCNA-第五篇-基础命令集+设备升级+设备破解密码+IP地址{精髓篇}
** CCNA-第五篇-基础命令集 ** 1.基础命令集 思科设备 : IOS 华为设备: VRP 启动步骤:加电自检-加载系统(IOS/VRP)-运行配置(保留的cfg或者conf文件) 命令行统一 ...
- 嵌入式Linux驱动学习之路(十五)按键驱动-定时器防抖
在之前的定时器驱动程序中,我们发现在连续按下按键的时候,正常情况下应该是一次按下对应一次松开.而程序有时候会显示是两次按下,一次松开.这个问题是因为在按下的时候,因为是机械按键,所以电压信号会产生一定 ...
- 【Linux从青铜到王者】第十五篇:Linux网络编程套接字两万字详解
系列文章目录 文章目录 系列文章目录 前言 一.网络数据的五元组信息 1.理解源IP地址和目的IP地址 2.理解 "端口号" 和 "进程ID" 3.理解源端口号 ...
- 基于GBT28181:SIP协议组件开发-----------第五篇SIP注册流程eXosip2实现(二)
原创文章,引用请保证原文完整性,尊重作者劳动,原文地址http://www.cnblogs.com/qq1269122125/p/3966794.html. 上章节讲解了讲解一个用eXosip2库实现 ...
- 2022-2028全球与中国语音生成设备(SGD)市场现状及未来发展趋势
2021年全球语音生成设备(SGD)市场销售额达到了 亿美元,预计2028年将达到 亿美元,年复合增长率(CAGR)为 %(2022-2028).地区层面来看,中国市场在过去几年变化较快,2021年市 ...
- linux注册函数机制,Linux可信计算机制模块详细分析之函数实现机制(1)字符设备驱动...
原标题:Linux可信计算机制模块详细分析之函数实现机制(1)字符设备驱动 2.3 函数实现机制 2.3.1 Linux 字符设备驱动 在linux 3.5.4中,用结构体cdev描述字符设备,cde ...
- linux字符设备驱动架构,linux驱动开发--字符设备:cdd_cdev结构中private_data使用
private_data改进 为设备驱动支持多个设备个体做准备,针对private_data进行改进 在设备打开操作中通过inode中保存的i_cdev获取代表当前设备的cdev对象 通过代表当前设备 ...
- Linux字符驱动中动态分配设备号与动态生成设备节点
在编写Linux内核驱动程序的时候,如果不动态生成设备号的话,需要自己手动分配设备号,有可能你分配的设备号会与已有设备号相同而产生冲突.因此推荐自动分配设备号.使用下面的函数: int alloc_c ...
- linux字符设备文件的打开操作,Linux字符设备驱动模型之字符设备初始化
因为Linux字符设备驱动主要依赖于struct cdev结构,原型为: 所以我们需要对所使用到的结构成员进行配置,驱动开发所使用到的结构成员分别为:[unsigned int count;].[de ...
最新文章
- 成语json_cocos creator实战(2)成语小秀才ts版
- CentOS生成自签名证书配置Apache https
- 关于 python 的注释
- 前端页面通过web3.eth.accounts无法获取账户信息
- Windows Mobile 5.0新增API介绍(转自MSDN)
- 小项目--猜年龄游戏
- 记tcp网络编程中遇到的readline()方法
- 在飞桨平台做图像分类-1 制作基于飞桨的数据集|CSDN创作打卡
- 【墨墨英语单词库免费开源无偿分享】小学、初中、高中、大学四六级专四专八、考研、托福、雅思等词书文本大合集
- HDU 5478 Can you find it (卡常数)2015 ACM/ICPC Asia Regional Shanghai Online
- 与前端设计师谈响应式设计
- 2018软考中级嵌入式系统设计师复习思路
- Windows下生成SSH密钥
- sphinx使用笔记
- 全新 OceanBase 社区版开发者中心 ODC 核心功能解读
- Worthington核心酶——木瓜蛋白酶的特征及相关应用
- design contains shelved or modified (but not repoured) polygons. the result....继续铺铜还是报警,解决方案如下:
- 【一问一答】错题库整理
- Linux从头学05-系统启动过程中的几个神秘地址,你知道是什么意思吗?
- 应试教育中的孩子长不好