加载驱动的指令是: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驱动第五篇-----驱动注册和生成设备节点相关推荐

  1. CCNA-第五篇-基础命令集+设备升级+设备破解密码+IP地址{精髓篇}

    ** CCNA-第五篇-基础命令集 ** 1.基础命令集 思科设备 : IOS 华为设备: VRP 启动步骤:加电自检-加载系统(IOS/VRP)-运行配置(保留的cfg或者conf文件) 命令行统一 ...

  2. 嵌入式Linux驱动学习之路(十五)按键驱动-定时器防抖

    在之前的定时器驱动程序中,我们发现在连续按下按键的时候,正常情况下应该是一次按下对应一次松开.而程序有时候会显示是两次按下,一次松开.这个问题是因为在按下的时候,因为是机械按键,所以电压信号会产生一定 ...

  3. 【Linux从青铜到王者】第十五篇:Linux网络编程套接字两万字详解

    系列文章目录 文章目录 系列文章目录 前言 一.网络数据的五元组信息 1.理解源IP地址和目的IP地址 2.理解 "端口号" 和 "进程ID" 3.理解源端口号 ...

  4. 基于GBT28181:SIP协议组件开发-----------第五篇SIP注册流程eXosip2实现(二)

    原创文章,引用请保证原文完整性,尊重作者劳动,原文地址http://www.cnblogs.com/qq1269122125/p/3966794.html. 上章节讲解了讲解一个用eXosip2库实现 ...

  5. 2022-2028全球与中国语音生成设备(SGD)市场现状及未来发展趋势

    2021年全球语音生成设备(SGD)市场销售额达到了 亿美元,预计2028年将达到 亿美元,年复合增长率(CAGR)为 %(2022-2028).地区层面来看,中国市场在过去几年变化较快,2021年市 ...

  6. linux注册函数机制,Linux可信计算机制模块详细分析之函数实现机制(1)字符设备驱动...

    原标题:Linux可信计算机制模块详细分析之函数实现机制(1)字符设备驱动 2.3 函数实现机制 2.3.1 Linux 字符设备驱动 在linux 3.5.4中,用结构体cdev描述字符设备,cde ...

  7. linux字符设备驱动架构,linux驱动开发--字符设备:cdd_cdev结构中private_data使用

    private_data改进 为设备驱动支持多个设备个体做准备,针对private_data进行改进 在设备打开操作中通过inode中保存的i_cdev获取代表当前设备的cdev对象 通过代表当前设备 ...

  8. Linux字符驱动中动态分配设备号与动态生成设备节点

    在编写Linux内核驱动程序的时候,如果不动态生成设备号的话,需要自己手动分配设备号,有可能你分配的设备号会与已有设备号相同而产生冲突.因此推荐自动分配设备号.使用下面的函数: int alloc_c ...

  9. linux字符设备文件的打开操作,Linux字符设备驱动模型之字符设备初始化

    因为Linux字符设备驱动主要依赖于struct cdev结构,原型为: 所以我们需要对所使用到的结构成员进行配置,驱动开发所使用到的结构成员分别为:[unsigned int count;].[de ...

最新文章

  1. 成语json_cocos creator实战(2)成语小秀才ts版
  2. CentOS生成自签名证书配置Apache https
  3. 关于 python 的注释
  4. 前端页面通过web3.eth.accounts无法获取账户信息
  5. Windows Mobile 5.0新增API介绍(转自MSDN)
  6. 小项目--猜年龄游戏
  7. 记tcp网络编程中遇到的readline()方法
  8. 在飞桨平台做图像分类-1 制作基于飞桨的数据集|CSDN创作打卡
  9. 【墨墨英语单词库免费开源无偿分享】小学、初中、高中、大学四六级专四专八、考研、托福、雅思等词书文本大合集
  10. HDU 5478 Can you find it (卡常数)2015 ACM/ICPC Asia Regional Shanghai Online
  11. 与前端设计师谈响应式设计
  12. 2018软考中级嵌入式系统设计师复习思路
  13. Windows下生成SSH密钥
  14. sphinx使用笔记
  15. 全新 OceanBase 社区版开发者中心 ODC 核心功能解读
  16. Worthington核心酶——木瓜蛋白酶的特征及相关应用
  17. design contains shelved or modified (but not repoured) polygons. the result....继续铺铜还是报警,解决方案如下:
  18. 【一问一答】错题库整理
  19. Linux从头学05-系统启动过程中的几个神秘地址,你知道是什么意思吗?
  20. 应试教育中的孩子长不好

热门文章

  1. cnn 一维时序数据_一时序数据输入维cnn
  2. python实现高校教务管理系统_基于Python技术的教务管理系统的研究与开发
  3. 不会三种编程语言的不算程序员 走近阿里云 MVP烁淼吐槽大佬
  4. bubble气泡特效
  5. Oracle 11g创建Interval分区表
  6. 001 GIt的基本操作
  7. oracle 11g ocp 笔记(22)--调度程序
  8. springboot13 发布和监听事件
  9. Ubuntu16.04 安装配置Caffe
  10. C# string类型和byte[]类型相互转换