Linux驱动开发(应用程序如何调用驱动)

2023-11-07

1.添加读写接口

(1)在应用代码中:

(2)在驱动代码中:

在这里插入图片描述


2.应用和驱动之间的数据交换

(1)copy_from_user,用来将数据从用户空间复制到内核空间
(2)copy_to_user,用来将数据从内核空间复制到用户空间

(3)write和read函数实现:

读函数:

写函数:


3.应用程序如何调用驱动源码:

应用层:

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


#define FILE	"/dev/test"			// 刚才mknod创建的设备文件名

char buf[100];

int main(void)
{
	int fd = -1;
	
	fd = open(FILE, O_RDWR);
	if (fd < 0)
	{
		printf("open %s error.\n", FILE);
		return -1;
	}
	printf("open %s success..\n", FILE);
	
	// 读写文件
	write(fd, "helloworld2222", 14);
	read(fd, buf, 100);
	printf("读出来的内容是:%s.\n", buf);
	
	// 关闭文件
	close(fd);
	
	return 0;
}

驱动层:

#include <linux/module.h>		// module_init  module_exit
#include <linux/init.h>			// __init   __exit
#include <linux/fs.h>
#include <asm/uaccess.h>

#define MYMAJOR		200
#define MYNAME		"testchar"

int mymajor;

char kbuf[100];			// 内核空间的buf

static int test_chrdev_open(struct inode *inode, struct file *file)
{
	// 这个函数中真正应该放置的是打开这个设备的硬件操作代码部分
	// 但是现在暂时我们写不了这么多,所以用一个printk打印个信息来做代表。
	printk(KERN_INFO "test_chrdev_open\n");
	
	return 0;
}

static int test_chrdev_release(struct inode *inode, struct file *file)
{
	printk(KERN_INFO "test_chrdev_release\n");
	
	return 0;
}

ssize_t test_chrdev_read(struct file *file, char __user *ubuf, size_t count, loff_t *ppos)
{
	int ret = -1;
	
	printk(KERN_INFO "test_chrdev_read\n");
	
	ret = copy_to_user(ubuf, kbuf, count);
	if (ret)
	{
		printk(KERN_ERR "copy_to_user fail\n");
		return -EINVAL;
	}
	printk(KERN_INFO "copy_to_user success..\n");
		
	return 0;
}

// 写函数的本质就是将应用层传递过来的数据先复制到内核中,然后将之以正确的方式写入硬件完成操作。
static ssize_t test_chrdev_write(struct file *file, const char __user *ubuf,
	size_t count, loff_t *ppos)
{
	int ret = -1;
	
	printk(KERN_INFO "test_chrdev_write\n");

	// 使用该函数将应用层传过来的ubuf中的内容拷贝到驱动空间中的一个buf中
	//memcpy(kbuf, ubuf);		// 不行,因为2个不在一个地址空间中
	ret = copy_from_user(kbuf, ubuf, count);
	if (ret)
	{
		printk(KERN_ERR "copy_from_user fail\n");
		return -EINVAL;
	}
	printk(KERN_INFO "copy_from_user success..\n");

	// 真正的驱动中,数据从应用层复制到驱动中后,我们就要根据这个数据
	// 去写硬件完成硬件的操作。所以这下面就应该是操作硬件的代码
	
	return 0;
}


// 自定义一个file_operations结构体变量,并且去填充
static const struct file_operations test_fops = {
	.owner		= THIS_MODULE,				// 惯例,直接写即可
	
	.open		= test_chrdev_open,			// 将来应用open打开这个设备时实际调用的
	.release	= test_chrdev_release,		// 就是这个.open对应的函数
	.write 		= test_chrdev_write,
	.read		= test_chrdev_read,
};


// 模块安装函数
static int __init chrdev_init(void)
{	
	printk(KERN_INFO "chrdev_init helloworld init\n");

	// 在module_init宏调用的函数中去注册字符设备驱动
	// major传0进去表示要让内核帮我们自动分配一个合适的空白的没被使用的主设备号
	// 内核如果成功分配就会返回分配的主设备好;如果分配失败会返回负数
	mymajor = register_chrdev(0, MYNAME, &test_fops);
	if (mymajor < 0)
	{
		printk(KERN_ERR "register_chrdev fail\n");
		return -EINVAL;
	}
	printk(KERN_INFO "register_chrdev success... mymajor = %d.\n", mymajor);

	return 0;
}

// 模块卸载函数
static void __exit chrdev_exit(void)
{
	printk(KERN_INFO "chrdev_exit helloworld exit\n");
	
	// 在module_exit宏调用的函数中去注销字符设备驱动
	unregister_chrdev(mymajor, MYNAME);
	
}

module_init(chrdev_init);
module_exit(chrdev_exit);

// MODULE_xxx这种宏作用是用来添加模块描述信息
MODULE_LICENSE("GPL");				// 描述模块的许可证
MODULE_AUTHOR("aston");				// 描述模块的作者
MODULE_DESCRIPTION("module test");	// 描述模块的介绍信息
MODULE_ALIAS("alias xxx");			// 描述模块的别名信息

makefile:

#ubuntu的内核源码树,如果要编译在ubuntu中安装的模块就打开这2个
#KERN_VER = $(shell uname -r)
#KERN_DIR = /lib/modules/$(KERN_VER)/build	

		
# 开发板的linux内核的源码树目录
KERN_DIR = /root/driver/kernel

obj-m	+= module_test.o

all:
	make -C $(KERN_DIR) M=`pwd` modules 
	arm-linux-gcc app.c -o app

cp:
	cp *.ko /x210_porting/rootfs/rootfs/driver_test
	cp app /x210_porting/rootfs/rootfs/driver_test
	

.PHONY: clean	
clean:
	make -C $(KERN_DIR) M=`pwd` modules clean
	rm -rf app


本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Linux驱动开发(应用程序如何调用驱动) 的相关文章

  • Linux嵌入式所有知识点-思维导图-【一口君吐血奉献】

    一 前言 很多粉丝问我 我的Linux和嵌入式当初是如何学习的 其实彭老师在最初学习的过程中 走了相当多的弯路 有些可以不学的花了太多的时间去啃 有些作为基础必须优先学习的 却忽略了 结果工作中用到这些知识时傻眼了 有些需要后面进阶阶段学习
  • Android设备启动时出现pop音

    Android设备启动时出现pop音 Android设备启动时出现pop音 环境介绍 原因定位 Android混音 TEE SINK Android HAL层文件 异常原因 解决方案 解决方案应用 Android设备启动时出现pop音 针对
  • 【003 中断】tasklet和workqueue的区别和底层实现的区别

    一 tasklet和workqueue的区别和底层实现的区别 1 softirq和tasklet都属于软中断 tasklet是softirq的特殊实现 workqueue是普通的工作队列 2 tasklet和workqueue 两者都是中断
  • GDB调试器常用命令

    1 l命令 list 列出所有程序源码 2 b命令 break 用于设置断点 break main 表示在 main 函数处设置断点 break 11 在第 11 行设置断点 3 c命令用于运行到断点处 输入 c 命令程序就会运行 直到下一
  • Linux驱动之系统移植----uboot移植(有设备树版本),完整移植.

    uboot版本 uboot2020 04 开发板 100ask imx6ull pro 拿到官方uboot后第一步先编译烧写测试 查看哪些驱动可用 哪些不可用 根据开发板厂商提供的资料 使用mx6ull 14x14 evk defconfi
  • linux驱动之ioctl详解

    何为ioctl 在linux对文件IO 有打开 读写 关闭 定位等命令 如果需要一些自定义的命令来操作我们写的驱动 ioctl便是传入这些自定义命令的函数 先看看在应用层的函数原型 int ioctl int fd unsigned lon
  • Linux驱动

    一 前言 设备树是每一个Linux驱动工程师都必须掌握的一个知识点 有很多之前做单片机的朋友刚接触Linux驱动时 会一脸懵 其实设备树的使用并没有大家想像的那么复杂 对于大部分工程师来说 只要会修改即可 很多粉丝留言说 希望彭老师提供一个
  • 段错误(核心已转储)问题的分析方法

    问题现象 今天在研究linux kernel中typedef的用法时 写了一个程序test typedef c 内容如下 include
  • make menuconfig 添加新选项

    如何在make menuconfig 界面添加新选项步骤 1 先在Linux内核源码目录下创建个新目录 哪个位置都行 一般添加新驱动时 都会在 drivers目录下创建 这里为了实验的方便就在 源码目录下创建了 mkdir hmq test
  • Linux内核中断

    一 相关函数 框架 int request irq unsigned int irq irq handler t handler unsigned long flags const char name void dev gt irq 要申请
  • 如何修改dmesg log buffer size

    需要修改 Linux 内核源码中的一个控制 log buffer size 的宏 CONFIG LOG BUF SHIFT buffer size 是 2 shift 加大这个就可以 一 配置 make menuconfig General
  • 十九、Linux驱动之虚拟网卡驱动

    1 基本概念 网络设备是完成用户数据包在网络媒介上发送和接收的设备 它将上层协议传递下来的数据包以特定的媒介访问控制方式进行发送 并将接收到的数据包传递给上层协议 与字符设备和块设备不同 网络设备并不对应于 dev目录下的文件 应用程序最终
  • linux-arm电源管理

    一文搞懂ARM SoC功耗控制架构
  • LINUX软中断-ksoftirqd

    前言 在上一篇 LINUX软中断 softirq的描述中 提到过ksoftirqd 这篇文章就介绍ksoftirqd ksoftirqd 是什么 ksoftirqd 是个内核线程 在创建的时候是绑定cpu的 每一个core对应生成一个kso
  • 音频驱动篇之pop音攻略

    接触音频驱动工作也有2年的时间了 这这段时间里深刻感受了手机行业的更新换代是MB的迅速 2年的时间里 从TI到QUALCOMM 从android2 1到4 2 从单核到四核 经我参与的项目就有20款 日子是相当的难过 今天回头来说一些我在研
  • linux支持usb打印机

    配置CONFIG USB PRINTER y inux内核默认运行打印机 核 驱动 直接在配置上CONFIG USB PRINTER y添加上去就好了 make menuconfig 选上USB打印机选项 Device Drivers gt
  • Linux驱动-编译驱动模块的Makefile和脚本

    Makefile内容 ARCH arm CROSS COMPILE arm poky linux gnueabi 也可以同时编译多个模块 obj m export symbol o export symbol1 o export symbo
  • linux驱动调试--段错误之栈信息分析

    转自 http blog chinaunix net xmlrpc php r blog article uid 29401328 id 4923529 接着上一篇来分析一下Oops的栈 s3c2440平台 关于调试源码和整个Oops信息请
  • 【内核驱动】Linux概述

    00 目录 文章目录 00 目录 01 Unix简介 02 Linux简介 03 Linux发展史 04 单内核与微内核区别 05 Linux内核 06 Linux内核组成 07 Linux官方网站 08 附录 01 Unix简介 UNIX
  • 最全的交叉编译Makefile讲解

    最近正在搞交叉编译 参考很多博客 学习了一下Makefile的编写 记录一下Makefile内代码是什么意思 代码如下 简单的hello ko的makefile ifneq KERNELRELEASE obj m hello o else

随机推荐

  • JS逆向解析---某知名小说网站内容加密

    该小说网站的全部内容都是经过一个JS的加密 要想爬取这个网站那么将其内容解析是不可避免的 本文将讲解如何对其进行JS的逆向解析 网站 shuqi 随便点开一本书 打开浏览器自带的抓包工具 点击第一个包 但是在这里找不到我们想要的数据 说明不
  • 实现ListView中每行显示进度条,并且各自显示自己的进度

    package com sagaware process list import java util ArrayList import java util HashMap import java util List import java
  • Web2.0网站一些通用业务采用NoSql的解决方案

    首先理解NoSql的划分 Often NoSQL databases are categorized according to the way they store the data and fall under categories su
  • MySQL生产环境高可用架构实战

    分布式技术MongoDB 1 MySQL高可用集群介绍 1 1 数据库主从架构与分库分表 1 2 MySQL主从同步原理 2 动手搭建MySQL主从集群 2 1 基础环境搭建 2 2 安装MySQL服务 2 2 1 初始化MySQL 2 2
  • 仿射密码 affine

    参考链接 https www cnblogs com 0yst3r 2046 p 12172757 html 仿射加密法 在仿射加密法中 字母表的字母被赋予一个数字 例如 a 0 b 1 c 2 z 25 仿射加密法的密钥为0 25直接的数
  • Incorrect integer value: '' for column 'id' at row 1 错误解决办法

    最近一个项目 在本地php环境里一切正常 ftp上传到虚拟空间后 当执行更新操作 我的目的是为了设置id为空 set id 时提示 Incorrect integer value for column id at row 1 解决办法 方法
  • 广工人福利,openwrt+gduth3c通过inode认证,妈妈再也不用担心我要用电脑开wifi了

    刚开校园网的时候 天天都只能用电脑开wifi 用类似于360wifi 猎豹wifi之类的软件要经常开着电脑 而且电脑网卡发射功率又小 上个厕所wifi就断了 睡觉前在床上还没wifi用 超级不爽 于是从家里面拿来了放在自己房间挂迅雷百度云的
  • x86下的C函数调用惯例

    1 从汇编到C 1 1 汇编语言的局限性 汇编语言是一种符号化了的机器语言 machine code 即用指令助记符 符号地址 标号等符号书写程序的语言 汇编语句与机器语句一一对应 它只是把每条指令及数据用便于记忆的符号书写而已 汇编语言
  • 用自己的数据增量训练预训练语言模型

    预训练模型给各类NLP任务的性能带来了巨大的提升 预训练模型通常是在通用领域的大规模文本上进行训练的 而很多场景下 使用预训练语言模型的下游任务是某些特定场景 如金融 法律等 这是如果可以用这些垂直领域的语料继续训练原始的预训练模型 对于下
  • spring配置文件解读——applicationContext.xml

    spring的配置文件 applicationContext xml 听着晴天看星晴的博客 CSDN博客
  • binutils internal struct

    http fossies org dox binutils 2 23 2 structelf internal sym html dl iterate phdr REPAIR RAX inline hook
  • [动态规划] leetcode 416. 分割等和子集

    问题描述 分割等和子集 给你一个只包含正整数的非空数组 nums 请你判断是否可以将这个数组分割成两个子集 使得两个子集的元素和相等 例子 输入nums 1 5 11 5 输出true 动态规划求解 这是一个0 1背包问题的变种 也就是每种
  • Idea工具使用经典总结

    安装教程 下载地址 https www jetbrains com idea download section windows 准备idea ideaIU 2017 2 3 exe 软件与激活包 JetbrainsCrack 2 6 9 r
  • 设备节点如何与设备驱动关联

    1 上层应用如何调用设备驱动 1 在linux中一切皆是文件 设备驱动程序对上层应用程序来说和普通文件没什么差异 2 上层应用程序通过设备节点来访问驱动程序 在驱动程序注册到内核后 用申请到的主次设备号来创建设备节点 2 向内核注册字符驱动
  • 【已解决】Error: Unable to access jarfile .\xxxx.jar

    报错类型 Error Unable to access jarfile xxxx jar 复现工具的时候 通过命令 java jar xxxx jar 运行 jar 包报了这个错误 报错原因是 在命令行中出现的路径下找不到 xxxx jar
  • micro-app在vue-element-admin中一些使用研究

    1 简述 本文承接上一篇micro app在vue element admi中的搭建 对micro app在vue element admin中的一些平时开发中常用的功能做了一些研究 本文代码 2 路由 关于路由 这边从两方面进行研究 一方
  • ass字幕格式

    ssa ass字幕格式全解析 内容 一 概述 二 文件各个部分解析 三 各种类型的行 四 Script Info 部分的标题行 五 v4 Styles 部分的风格行Style 六 Events 事件部分的对话行Dialogue 七 Even
  • 高通功耗调试18之Tsensor中断频繁触发导致低温下待机功耗高的问题

    问题背景 在内核4 9及之后的版本 低于5C环境温度下待机 由于触发了Tsensor的低温保护机制 可能会遇到较频繁 的tsens中断 11 22 07 12 27 914969 0 0 W GICv3 gic show resume ir
  • [echarts]柱状图的点击事件

    先来一段简洁的写echarts图表的代码 这样获取echarts的dom节点是因为 如果将柱状图封装成了一个组件 在一个页面中多次使用 若还是按常规获取dom节点 会报一个警告 let charts echarts getInstanceB
  • Linux驱动开发(应用程序如何调用驱动)

    1 添加读写接口 1 在应用代码中 2 在驱动代码中 2 应用和驱动之间的数据交换 1 copy from user 用来将数据从用户空间复制到内核空间 2 copy to user 用来将数据从内核空间复制到用户空间 3 write和re