【IMX6ULL驱动开发学习】06.APP与驱动程序传输数据_自动创建设备节点(hello驱动)

news2024/11/16 19:55:58

一、APP与驱动之间传输数据

/*驱动从APP获取数据*/
unsigned long copy_from_user(void *to, const void *from, unsigned long n)

/*驱动传输数据到APP*/
unsigned long copy_to_user(void *to, const void *from, unsigned long n)

二、使用copy_to_user、copy_from_user在APP与hello驱动之间传输数据

测试方式:

./hello_test /dev/hello 1234abc    APP向驱动程序写入数据
./hello_test /dev/hello            APP从驱动程序读出刚才写入的数据

APP与驱动程序传输数据原理:

  1. APP调用open函数打开设备,使用系统IO函数write写入数据到设备
  2. 系统调用驱动程序的写操作函数(通过file_operations结构体指定),将APP中传入的参数传入该写操作函数
  3. 驱动程序的写操作函数调用copy_from_user函数从用户程序中拷贝数据到驱动程序中
  4. APP调用系统IO函数read,读取驱动数据
  5. 系统调用驱动程序的读操作函数(通过file_operations结构体指定),将驱动程序中的数据拷贝到APP

用一张图片形象的表示一下吧
在这里插入图片描述

三、驱动程序自动创建设备节点

第一步:class_create函数 创建设备类

/*
 * @description		: 创建一个class类型的对象
 * @param - owner	: THIS_MODULE
 * @param - name	: 类名字
 * @return 			: 成功,返回struct class的指针;其他 失败
 */
struct class *class_create(struct module *owner, const char *name)

/*举例*/
static struct class *hello_class;
hello_class = class_create(THIS_MODULE, "hello_class");

第二步:device_create函数 在/dev下创建设备节点(无需在开发板端执行mknod命令了)

/*
 * @description		: 生成设备节点并导出到用户空间(在/dev下创建设备节点)
 * @param - class	: 指向该设备应注册到的struct class的指针(上一个class_create函数返回值)
 * @param - parent	: 指向此新设备的父struct设备的指针(如果有),没有填NULL
 * @param - devt	: 要添加的char设备的dev_t(设备号)
 * @param - drvdata	: 要添加到设备中以进行回调的数据(如果有),没有填NULL
 * @param - fmt		: 设备名称的字符串
 * @return 			: 成功,返回struct device指针;其他 失败
 */
struct device *device_create(struct class *class, struct device *parent, 
								dev_t devt, void *drvdata, const char *fmt, ...)
/*举例*/
device_create(hello_class, NULL, MKDEV(major, 0), NULL, "hello");

上代码
hello驱动程序代码:

#include <linux/module.h>
#include <linux/miscdevice.h>
#include <linux/delay.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/capability.h>
#include <linux/init.h>
#include <linux/mutex.h>
#include <asm/mach-types.h>
#include <asm/uaccess.h>
#include <asm/therm.h>
#include <linux/string.h>


static int major;
static unsigned char buff[100];
static struct class *hello_class;

static int hello_open (struct inode *node, struct file *filp)
{
	printk("hello_open\n");
	printk("%s %s %d\n",__FILE__, __FUNCTION__, __LINE__);

	return 0;
}

static ssize_t hello_read (struct file *filp, char *buf, size_t size, loff_t *offset)
{
	size_t len = size > 100 ? 100 : size;
	printk("hello_read\n");
	copy_to_user(buf, buff, len);
	return len;
}

static ssize_t hello_write (struct file *filp, const char *buf, size_t size, loff_t *offset)
{
	size_t len = size > 100 ? 100 : size;
	memset(buff, 0 ,sizeof(buff));
	printk("hello_write\n");
	copy_from_user(buff, buf, len);
	return len;
}

static int hello_release (struct inode *node, struct file *filp)
{
	printk("hello_release\n");
	return 0;
}

/*1.定义 file_operations 结构体*/
static const struct file_operations hello_drv = {
    .owner 		= THIS_MODULE,
	.read		= hello_read,
	.write		= hello_write,
	.open		= hello_open,
	.release    = hello_release,
};

/*3.入口函数*/
static int hello_init(void)
{
	//返回主设备号
	major = register_chrdev(0,"hello_drv",&hello_drv);
	
	printk("hello_open\n");
	printk("%s %s %d\n",__FILE__, __FUNCTION__, __LINE__);

	/*在内核中创建设备*/
	hello_class = class_create(THIS_MODULE, "hello_class");
	if (IS_ERR(hello_class)) {
		printk("hello class create failed!\n");
	}

	/*在设备类下面创建设备*/
	device_create(hello_class, NULL, MKDEV(major, 0), NULL, "hello");
	if (IS_ERR(dev)) {
		printk("hello device_create  failed!\n");
	}
	return 0;
}

/*4.退出函数*/
static int hello_exit(void)
{
	//卸载设备
	unregister_chrdev(major,"hello_drv");

	//销毁设备
	device_destroy(hello_class, MKDEV(major, 0));
	//删除设备类
	class_destroy(hello_class);

	//删除注册的设备号
	// unregister_chrdev_region(major, 1);

	return 0;
}	

module_init(hello_init);
module_exit(hello_exit);
MODULE_LICENSE("GPL");

hello应用程序代码:

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>

int main(int argc, char *argv[])
{
    int len;
    char read_buf[10];

    if(argc < 2){
        printf("please input  at least 2 args\n");
        printf("%s <dev> [string]\n", argv[0]);
        return -1;
    }

    /*open*/
    int fd;
    fd = open(argv[1], O_RDWR);
    if(fd < 0){
        printf("open failed\n");
        return -2;
    }

    /*read*/
    if(argc == 2){  
        read(fd, read_buf, 10);    //调用read函数,只为了触发系统调用hello驱动的read函数
        printf("read operation : %s\n", read_buf);
    }

    /*write*/
    if(argc == 3){
        len = write(fd, argv[2], strlen(argv[2]));   //调用write函数,只为了触发系统调用hello驱动的write函数
        printf("write length = %d \n", len);
    }

    close(fd);

    return 0;
}

测试结果:

[root@100ask:/mnt]# insmod hello_drv.ko  (向内核注册hello驱动)
[root@100ask:/mnt]# cat /proc/devices    (查看驱动设备号)
Character devices:
  1 mem
  4 /dev/vc/0
  4 tty
  5 /dev/tty
  5 /dev/console
  5 /dev/ptmx
  7 vcs
 10 misc
 13 input
 29 fb
 81 video4linux
 89 i2c
 90 mtd
108 ppp
116 alsa
128 ptm
136 pts
166 ttyACM
180 usb
188 ttyUSB
189 usb_device
207 ttymxc
216 rfcomm
226 drm
238 hello_drv
[root@100ask:/mnt]# ls -l /dev/hello       (查看/dev下是否有hello设备节点)
crw------- 1 root root 238, 0 Jan  1 01:37 /dev/hello

#测试hello驱动读写操作
[root@100ask:/mnt]# ./hello_test /dev/hello 1234abc    (向驱动写)
write length = 7 
[root@100ask:/mnt]# ./hello_test /dev/hello            (读驱动)
read operation : 1234abc

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/634731.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

如何把视频声音转成文字?分享三个实用的方法!

在日常学习中&#xff0c;有些小伙伴可能想将视频课程中老师的讲解内容整理出来&#xff0c;但是逐字逐句地打字既低效又耗时。那么&#xff0c;如何将视频声音快速转换为文字呢&#xff1f;答案是使用记灵在线工具&#xff01;下面我将分享几种使用记灵在线工具快速将视频声音…

Raft is not great?

Raft相比于paxos不好的地方有下面这些地方 1.Term raft的逻辑时钟是通过term&#xff0c;和votefor来确定的&#xff0c;同时&#xff0c;raft的votefor只能是None < 有&#xff0c;有的话&#xff0c;就不可比&#xff0c;也就是一个偏序关系。这个不可比的特性会增加选举…

Javaweb学习路线(2)——Maven

一、概念 Maven 是 apache 旗下的一个开源项目&#xff0c;是一款用于管理和构建java项目的工具。 二、作用 依赖管理&#xff1a; 动态管理jar包&#xff0c;避免版本冲突。统一项目结构&#xff1a; 提供标准、统一的项目结构。项目构建&#xff1a; 标准跨平台的自动化项目…

深入探讨软件测试的质量度量指标

本文的目的是介绍项目中使用到主要质量指标&#xff0c;这些质量指标可以分为以下三类&#xff1a; 质量保证过程指标生产事故管理指标度量质量文化指标 质量保证过程指标 质量保证指标可以通过测试覆盖率来度量功能和非功能测试的覆盖率&#xff0c;同时也可以根据测试发现…

shell学习记录(函数)

Shell 函数 linux shell 可以用户定义函数&#xff0c;然后在shell脚本中可以随便调用。 shell中函数的定义格式如下&#xff1a; [ function ] funname [()] { action; [return int;] } 说明&#xff1a; 1、可以带function fun() 定义&#xff0c;也可以直接fun()…

对“java子类不能继承父类构造方法“的理解

目录 子类构造函数&#xff0c;什么时候需要写&#xff0c;什么时候可以不写&#xff1f;为什么要这么设计&#xff1f;子类已经继承父类&#xff0c;为什么就不能继承父类的构造器了&#xff1f;子类直接用父类的构造器不就行了&#xff1f; 子类构造函数&#xff0c;什么时候…

今年适合进入软件测试行业吗?

对于“自己适不适合转行做软件测试&#xff1f;”一直都是测试行业里的热门话题。随着近几 年IT互联网行业的快速发展&#xff0c;软件测试岗位也受到越来越多人的关注&#xff0c;因此有很多人都想要从事这一行业&#xff0c;这里主要分为两类人&#xff0c;一种是刚毕业的应届…

【Deno】极简入门

极简系列 极简入门 简介 Deno是一个 JavaScript/TypeScript 的运行时&#xff0c;默认使用安全环境执行代码&#xff0c;有着卓越的开发体验。 Deno建立在 V8、Rust 和 Tokio 的基础上。 优势 适合不喜欢复杂配置开箱即用的人群&#xff08;如本人小溪&#xff09; 安全性…

《微服务实战》 第三十一章 ShardingSphere - ShardingSphere-JDBC

前言 Apache ShardingSphere 是一款分布式的数据库生态系统&#xff0c; 可以将任意数据库转换为分布式数据库&#xff0c;并通过数据分片、弹性伸缩、加密等能力对原有数据库进行增强。 Apache ShardingSphere 设计哲学为 Database Plus&#xff0c;旨在构建异构数据库上层的…

Spring-Bean基础

文章目录 什么是 BeanDefinition如何获取BeanDefinition如何将BeanDefinition注册到容器中Bean的初始化操作Bean的销毁操作 什么是 BeanDefinition BeanDefinition 是 Spring Framework 中定义 Bean 的配置元信息接口&#xff0c;包含如下信息&#xff1a; 如何获取BeanDefin…

STL学习笔记

STL学习笔记 Vector void VectorTest() {vector<int> vect;vect.push_back(1);vect.push_back(20);vect.push_back(12);vect.push_back(12);vect.push_back(12);sort(vect.begin(),vect.end());for(vector<int>::iterator itervect.begin();iter!vect.end();iter…

osg利用setNodeMask和Switch隐藏节点用法说明

目录 1. 用法及差异点说明 2.利用NodeMask隐藏节点 2. Switch节点 3. NodeMask和Switch混用 1. 用法及差异点说明 在osg中使Node隐藏方式有两种&#xff0c;一种是设置NodeMask&#xff0c;另外一种是使用osg的Switch类来控制。两者的区别&#xff1a;前者只是看不到&#…

Java实现文件分片上传

文章目录 Java实现文件分片上传为什么要使用分片上传什么是分片上传&#xff1f;前后端代码 Java实现文件分片上传 为什么要使用分片上传 在需要上传文件时&#xff0c;不可避免地会遇到上传文件内容过大&#xff0c;上传时间太长地问题&#xff0c;采用文件分片上传就可以解…

ARM-M架构移植UCOS操作系统

最近准备面试&#xff0c;把本科到现在的一些比赛相关的东西整理一下。那些年在飞思卡尔在K60单片机上的UCOSII移植&#xff08;哎&#xff0c;心酸...&#xff09; 一、首先看下UCOSII的文件结构&#xff1a; 一些核心的文件解释&#xff1a; 【1、头文件】&#xff1a; inclu…

SQL多表查询常用语句总结

一、多表关系 &#xff08;一&#xff09;概述 项目开发中&#xff0c;在进行数据库表结构设计时&#xff0c;会根据业务需求及业务模块之间的关系&#xff0c;分析并设计表结构&#xff0c;由于业务之间相互关联&#xff0c;所以各个表结构之间也存在着各种联系&#xff0c;…

【MySQL】数据库中表的操作

表的操作 一、创建表 --- create table 表名(列名 类型 ...);1.1 创建表的案例 二、查看表2.1 查看选中数据库的所有表 --- show tables;2.2 查看&#xff08;描述&#xff09;表结构 --- desc 表名;2.3 查看建表信息 --- show create table 表名 \G 三、修改表 --- alter3.1 修…

说说我认为的AI和人类的未来

今天闲来无事&#xff0c;花了半天时间部署了一个Stable Diffusion的开源AI生成图片程序&#xff0c;因为电脑配置的原因&#xff0c;找了一个小模型集测试了一下效果&#xff0c;总的来说还是挺震惊的。上图是通过输入&#xff1a;长发美女森林漫步红色裙子 这三个关键词后花了…

useEffect的基础知识和底层机制

useEffect 是 React 中一个重要的 Hook&#xff0c;用来处理组件的副作用操作。它的基础知识包括两个方面&#xff1a;执行时机和参数。 执行时机&#xff1a; useEff ect 的执行时机包括两种情况&#xff1a; 组件挂载时&#xff0c;即第一次渲染之后。组件更新时&#xff…

pandas---Series与DataFrame索引、切片;多层索引、索引的堆叠

1. Series的索引和切片 1.1 Series的索引&#xff1a; 可以使用中括号取单个索引&#xff08;此时返回的是元素类型&#xff09;&#xff0c;或者中括号里一个列表取多个索引&#xff08;此时 返回的仍然是一个Series类型&#xff09;。分为显示索引和隐式索引&#xff1a; …