linux驱动:(21)ioctl接口(二)驱动与应用程序传递ioctl命令

news2024/10/6 6:38:06

目录

copy_from_user改为用ioctl接口

修改为ioctl读取无参数命令

测试.c

驱动.c

效果

修改为ioctl读取有参数命令

测试.c

驱动.c

效果

修改为ioctl发送有参数命令

测试.c

驱动.c

效果


copy_from_user改为用ioctl接口

将以前的beep杂项设备中的copy_from_user改为用ioctl接口,修改的代码是   linux驱动:(8)实战:用杂项设备完成蜂鸣器驱动   中的代码

#include <linux/init.h>
#include <linux/module.h>
#include <linux/miscdevice.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/io.h>
 
#define GPIO5_DR 0x020AC00
unsigned int *vir_gpio5_dr;
 
int misc_open(struct inode * inode,struct file * file)
{
    printk("hello misc_open\n");
    return 0;
}
int misc_read(struct file *file,char _user *ubuf,size_t size,loff_t *loff_t)
{
    char kbuf[64] = "heheh";
    if( copy_to_user(ubuf,kbuf,strlen(kbuf))!=0)
    {
        printk("copy_to_user error\n");
        return -1;
    }
    return 0;
}
int misc_write(struct file *file,const char _user *ubuf,size_t size,loff_t *loff_t)
{
    char kbuf[64] = {0};
    if( copy_from_user(kbuf,ubuf,size)!=0)
    {
        printk("copy_from_user error\n");
        return -1;
    }
    printk("kbuf is %s\n",kbuf);
    if(kbuf[0]==1)
    {
        *vir_gpio5_dr |= (1<<1);
    }
    else if
    {
        *vir_gpio5_dr &= ~(1<<1);
    }
    return 0;
}
struct const file_operation misc_fops = {
    .owner = THIS_MODULE,
    .open = misc_open,
    .write= misc_write,
    .read = misc_read
};
struct miscdevice misc_dev = {
    .minor = MISC_DYNAMIC_MINOR,//动态分配
    .name ="hellomisc",//设备节点名字
    .fops =&misc_fops 
};
 
static int misc_init(void)
{
    int ret;
    ret = misc_register(&misc_dev);
    if(ret<0)
    {
        printk("misc registe is error\n");
        return -1;
    }
    vir_gpio5_dr = ioremap(GPIO5_DR,4);
    if(vir_gpio5_dr ==NULL)
    {
        printk("GPIO5_DR ioremap error\n");
        return -EBUSY;
    }
    printk("GPIO5_DR ioremap ok\n");
    return 0;
}
 
static void misc_exit(void)
{
    misc_deregister(&misc_dev);
    iounmap(vir_gpio5_dr );
    printk("misc goodbye");
}
 
module_init(misc_init);
module_exit(misc_exit);
 
MODULE_LICENSE("GPL");

修改为ioctl读取无参数命令

  • 先把关于GPIO5_DR 的部分删掉
  • 编写测试.c,定义发送两个无参数命令
    • ioctl函数中的参数对应驱动中的函数中的参数
  • 在驱动.c中也要定义两个一样的无参数命令
  • 在文件操作集中定义unlocked_ioctl函数
    • 在函数中判断cmd命令是否等于我们自己定义的两个命令

测试.c

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

#define CMD_TEST0 _IO('L',0)
#define CMD_TEST1 _IO('L',1)

int main(int argc,char *argv[])
{
    int fd;
    // 读取设备节点
    fd = open("/dev/hello_misc",O_RDWR);
    if (fd < 0)
    {
        perror("open error\n");
        return fd;
    }
    while (1)
    {
        ioctl(fd,CMD_TEST0);
        sleep(2);
        ioctl(fd,CMD_TEST1);
        sleep(2);
    }
    
    return 0;
}

驱动.c

#include <linux/init.h>
#include <linux/module.h>
#include <linux/miscdevice.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/io.h>
#include <sys/ioctl.h>
 
#define CMD_TEST0 _IO('L',0)
#define CMD_TEST1 _IO('L',1)
int misc_open(struct inode * inode,struct file * file)
{
    printk("hello misc_open\n");
    return 0;
}
int misc_read(struct file *file,char _user *ubuf,size_t size,loff_t *loff_t)
{
    char kbuf[64] = "heheh";
    if( copy_to_user(ubuf,kbuf,strlen(kbuf))!=0)
    {
        printk("copy_to_user error\n");
        return -1;
    }
    return 0;
}
int misc_write(struct file *file,const char _user *ubuf,size_t size,loff_t *loff_t)
{
    char kbuf[64] = {0};
    if( copy_from_user(kbuf,ubuf,size)!=0)
    {
        printk("copy_from_user error\n");
        return -1;
    }
    printk("kbuf is %s\n",kbuf);

    return 0;
}

long misc_ioctl(struct file *file,unsigned int cmd, unsigned long value)
{
    switch (cmd)
    {
    case CMD_TEST0:
        printk("led on\n");
        break;
    case CMD_TEST1:
        printk("led off\n");
        break;
    default:
        break;
    }
    return 0;
}

struct const file_operation misc_fops = {
    .owner = THIS_MODULE,
    .open = misc_open,
    .write= misc_write,
    .unlocked_ioctl= misc_ioctl,
    .read = misc_read
};
struct miscdevice misc_dev = {
    .minor = MISC_DYNAMIC_MINOR,//动态分配
    .name ="hellomisc",//设备节点名字
    .fops =&misc_fops 
};
 
static int misc_init(void)
{
    int ret;
    ret = misc_register(&misc_dev);
    if(ret<0)
    {
        printk("misc registe is error\n");
        return -1;
    }
    vir_gpio5_dr = ioremap(GPIO5_DR,4);

    return 0;
}
 
static void misc_exit(void)
{
    misc_deregister(&misc_dev);
    printk("misc goodbye");
}
 
module_init(misc_init);
module_exit(misc_exit);
 
MODULE_LICENSE("GPL");

效果

  • 编译成模块,烧录到开发板中,加载驱动,运行测试.c
  • 每隔两秒打印led on或者led off

修改为ioctl读取有参数命令

  • 先把关于GPIO5_DR 的部分删掉
  • 编写测试.c,定义发送两个有参数命令
    • ioctl函数中的参数对应驱动中的函数中的参数
  • 在驱动.c中也要定义两个一样的有参数命令
  • 在文件操作集中定义unlocked_ioctl函数
    • 在函数中判断cmd命令是否等于我们自己定义的两个命令

测试.c

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

#define CMD_TEST0 _IOW('L',0,int)
#define CMD_TEST1 _IOW('L',1,int)

int main(int argc,char *argv[])
{
    int fd;
    // 读取设备节点
    fd = open("/dev/hello_misc",O_RDWR);
    if (fd < 0)
    {
        perror("open error\n");
        return fd;
    }
    while (1)
    {
        ioctl(fd,CMD_TEST0,1);
        sleep(2);
        ioctl(fd,CMD_TEST1,0);
        sleep(2);
    }
    
    return 0;
}

驱动.c

#include <linux/init.h>
#include <linux/module.h>
#include <linux/miscdevice.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/io.h>
#include <sys/ioctl.h>
 
#define CMD_TEST0 _IOW('L',0,int)
#define CMD_TEST1 _IOW('L',1,int)
int misc_open(struct inode * inode,struct file * file)
{
    printk("hello misc_open\n");
    return 0;
}
int misc_read(struct file *file,char _user *ubuf,size_t size,loff_t *loff_t)
{
    char kbuf[64] = "heheh";
    if( copy_to_user(ubuf,kbuf,strlen(kbuf))!=0)
    {
        printk("copy_to_user error\n");
        return -1;
    }
    return 0;
}
int misc_write(struct file *file,const char _user *ubuf,size_t size,loff_t *loff_t)
{
    char kbuf[64] = {0};
    if( copy_from_user(kbuf,ubuf,size)!=0)
    {
        printk("copy_from_user error\n");
        return -1;
    }
    printk("kbuf is %s\n",kbuf);

    return 0;
}

long misc_ioctl(struct file *file,unsigned int cmd, unsigned long value)
{
    switch (cmd)
    {
    case CMD_TEST0:
        printk("led on\n");
        printk("value is %d\n",value);
        break;
    case CMD_TEST1:
        printk("led off\n");
        printk("value is %d\n",value);
        break;
    default:
        break;
    }
    return 0;
}

struct const file_operation misc_fops = {
    .owner = THIS_MODULE,
    .open = misc_open,
    .write= misc_write,
    .unlocked_ioctl= misc_ioctl,
    .read = misc_read
};
struct miscdevice misc_dev = {
    .minor = MISC_DYNAMIC_MINOR,//动态分配
    .name ="hellomisc",//设备节点名字
    .fops =&misc_fops 
};
 
static int misc_init(void)
{
    int ret;
    ret = misc_register(&misc_dev);
    if(ret<0)
    {
        printk("misc registe is error\n");
        return -1;
    }
    vir_gpio5_dr = ioremap(GPIO5_DR,4);

    return 0;
}
 
static void misc_exit(void)
{
    misc_deregister(&misc_dev);
    printk("misc goodbye");
}
 
module_init(misc_init);
module_exit(misc_exit);
 
MODULE_LICENSE("GPL");

效果

  • 编译成模块,烧录到开发板中,加载驱动,运行测试.c
  • 每隔两秒打印led on或者led off,并会打印出value的值(0和1)

修改为ioctl发送有参数命令

  • 先把关于GPIO5_DR 的部分删掉
  • 编写测试.c,定义接收一个有参数命令
    • ioctl函数中的参数对应驱动中的函数中的参数
  • 在驱动.c中也要定义一个一样的有参数命令
  • 在文件操作集中定义unlocked_ioctl函数
    • 在函数中判断cmd命令是否等于我们自己定义的一个命令,是就通过copy_to_user进行发送

测试.c

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

#define CMD_TEST0 _IOR('L',0,int)

int main(int argc,char *argv[])
{
    int fd;
    int value;
    // 读取设备节点
    fd = open("/dev/hello_misc",O_RDWR);
    if (fd < 0)
    {
        perror("open error\n");
        return fd;
    }
    while (1)
    {
        ioctl(fd,CMD_TEST0,&value);
        printf("value is %d\n",value);
        sleep(2);
    }
    
    return 0;
}

驱动.c

#include <linux/init.h>
#include <linux/module.h>
#include <linux/miscdevice.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/io.h>
#include <sys/ioctl.h>
 
#define CMD_TEST0 _IOR('L',0,int)
int misc_open(struct inode * inode,struct file * file)
{
    printk("hello misc_open\n");
    return 0;
}
int misc_read(struct file *file,char _user *ubuf,size_t size,loff_t *loff_t)
{
    char kbuf[64] = "heheh";
    if( copy_to_user(ubuf,kbuf,strlen(kbuf))!=0)
    {
        printk("copy_to_user error\n");
        return -1;
    }
    return 0;
}
int misc_write(struct file *file,const char _user *ubuf,size_t size,loff_t *loff_t)
{
    char kbuf[64] = {0};
    if( copy_from_user(kbuf,ubuf,size)!=0)
    {
        printk("copy_from_user error\n");
        return -1;
    }
    printk("kbuf is %s\n",kbuf);

    return 0;
}

long misc_ioctl(struct file *file,unsigned int cmd, unsigned long value)
{
    int val;
    switch (cmd)
    {
    case CMD_TEST0:
        val = 12 ;
        if( copy_to_user((int *)value,&val,sizeof(val))!=0)
        {
            printk("copy_to_user error\n");
            return -1;
        }
        break;
    default:
        break;
    }
    return 0;
}

struct const file_operation misc_fops = {
    .owner = THIS_MODULE,
    .open = misc_open,
    .write= misc_write,
    .unlocked_ioctl= misc_ioctl,
    .read = misc_read
};
struct miscdevice misc_dev = {
    .minor = MISC_DYNAMIC_MINOR,//动态分配
    .name ="hellomisc",//设备节点名字
    .fops =&misc_fops 
};
 
static int misc_init(void)
{
    int ret;
    ret = misc_register(&misc_dev);
    if(ret<0)
    {
        printk("misc registe is error\n");
        return -1;
    }
    vir_gpio5_dr = ioremap(GPIO5_DR,4);

    return 0;
}
 
static void misc_exit(void)
{
    misc_deregister(&misc_dev);
    printk("misc goodbye");
}
 
module_init(misc_init);
module_exit(misc_exit);
 
MODULE_LICENSE("GPL");

效果

  • 编译成模块,烧录到开发板中,加载驱动,运行测试.c
  • 每隔两秒打印驱动传出来的value值12

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

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

相关文章

蓝牙定位的MATLAB仿真程序(基于信号强度,平面内的定位,四个蓝牙基站)

这段代码通过RSSI信号强度实现了蓝牙定位,展示了如何使用锚点位置和测量的信号强度来估计未知点的位置。它涵盖了信号衰减模型、距离计算和最小二乘法估计等基本概念。通过图形化输出,用户可以直观地看到真实位置与估计位置的关系。 文章目录 蓝牙定位原理蓝牙定位的原理优缺…

【综合性渗透利器】- TscanPlus

如果你在寻找一款轻量级、实用且开源的漏洞扫描工具&#xff0c;那么 TscanPlus 绝对值得一试。这款工具由 TideSec 团队打造&#xff0c;以其简洁、高效、易用的特点&#xff0c;广受好评&#xff0c;目前在github上拥有1.5k star。 为什么推荐 TscanPlus&#xff1f; 无论你…

基于Zynq SDIO WiFi移植一(支持2.4/5G)

基于SDIO接口的WIFI&#xff0c;在应用上&#xff0c;功耗低于USB接口&#xff0c;且无须USB Device支持&#xff0c;满足某些应用场景 1 硬件连接 2 Vivado工程配置 3 驱动编译 3.1 KERNRL CONFIG (build ENV) 修改 export KERNELPATH<path of kernel header>export T…

【web安全】——SSRF服务器端请求伪造

1.SSRF漏洞基础 1.1SSRF漏洞概述与成因 SSRF(Server-Side Request Forgery:服务器端请求伪造) 是一种由攻击者构造形成由服务端发起请求的一个安全漏洞。 一般情况下&#xff0c;SSRF攻击的目标是从外网无法访问的内部系统。&#xff08;正是因为它是由服务端发起的&#xf…

Java--IO高级流

缓冲流 缓冲流,也叫高效流&#xff0c;是对4个基本的FileXxx 流的增强&#xff0c;所以也是4个流&#xff0c;按照数据类型分类&#xff1a; 字节缓冲流&#xff1a;BufferedInputStream&#xff0c;BufferedOutputStream 字符缓冲流&#xff1a;BufferedReader&#xff0c;Buf…

Python | Leetcode Python题解之第458题可怜的小猪

题目&#xff1a; 题解&#xff1a; class Solution:def poorPigs(self, buckets: int, minutesToDie: int, minutesToTest: int) -> int:if buckets 1:return 0combinations [[0] * (buckets 1) for _ in range(buckets 1)]combinations[0][0] 1iterations minutesT…

StreamProvider组件的用法

文章目录 1 概念介绍2 使用方法3 示例代码我们在上一章回中介绍了通道相关的内容,本章回中将介绍StreamProvider组件.闲话休提,让我们一起Talk Flutter吧。 1 概念介绍 在Flutter中Stream是经常使用的组件,对该组件的监听可void main() {///让状态栏和程序的appBar融为一体…

yub‘s Algorithm Adventure Day6

链表相交 link&#xff1a;面试题 02.07. 链表相交 - 力扣&#xff08;LeetCode&#xff09; 思路分析 看到描述很直接的想到双指针&#xff0c;但是看到题解之后被K佬的神级理解折服&#xff0c;太妙了&#xff01; 双指针 public class Solution {public ListNode getIn…

计算机毕业设计 乡村生活垃圾管理系统的设计与实现 Java实战项目 附源码+文档+视频讲解

博主介绍&#xff1a;✌从事软件开发10年之余&#xff0c;专注于Java技术领域、Python人工智能及数据挖掘、小程序项目开发和Android项目开发等。CSDN、掘金、华为云、InfoQ、阿里云等平台优质作者✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精…

设计模式、系统设计 record part03

创建者模式 1.创建、使用&#xff0c;二者分离 2.降低&#xff0c;耦合度 3.使用者&#xff0c;不用关注&#xff0c;对象的创建细节 工厂模式&#xff1a; 1.对象由工厂生产&#xff0c; 2.使用者与工厂交流&#xff0c;不与对象直接打交道&#xff0c; 3.在工厂里直接更换对象…

使用 Vertex AI Gemini 模型和 Elasticsearch Playground 快速创建 RAG 应用程序

作者&#xff1a;来自 Elastic Jeff Vestal 在这篇博客中&#xff0c;我们将使用 Elastic 的 Playground 和 Vertex AI API 将 Elasticsearch 连接到 Google 的 Gemini 1.5 聊天模型。将 Gemini 模型添加到 Playground 使 Google Cloud 开发人员能够快速建立 LLM、测试检索、调…

开源的云平台有哪些?

开源云平台为用户提供了构建、管理和运行云基础设施及应用的能力&#xff0c;同时允许社区参与开发和改进。以下是一些知名的开源云平台&#xff1a; 1. OpenStack 简介&#xff1a;OpenStack&#xff1a;一个广泛使用的开源云平台&#xff0c;它由多个组件组成&#xff0c;提…

PriorityQueue分析

概述 PriorityQueue&#xff0c;优先级队列&#xff0c;一种特殊的队列&#xff0c;作用是能保证每次取出的元素都是队列中权值最小的&#xff08;Java的优先队列每次取最小元素&#xff0c;C的优先队列每次取最大元素&#xff09;。元素大小的评判可以通过元素本身的自然顺序…

linux信号 | 学习信号四步走 | 透析信号是如何被处理的?

前言&#xff1a;本节内容讲述linux信号的捕捉。 我们通过前面的学习&#xff0c; 已经学习了信号的概念&#xff0c; 信号的产生&#xff0c; 信号的保存。 只剩下信号的处理。 而信号的处理我们应该着重注意的是第三种处理方式——信号的捕捉。 也就是说&#xff0c; 这篇文章…

基于yolov8的100种蝴蝶智能识别系统python源码+pt模型+训练日志+精美GUI界面

【算法介绍】 基于YOLOv8的100种蝴蝶智能识别系统是一个结合了深度学习和人工智能技术的先进工具&#xff0c;旨在提高生物多样性监测和保护领域的效率和精确度。该系统利用YOLOv8深度学习算法&#xff0c;通过9955张图片的训练&#xff0c;能够准确识别100种不同的蝴蝶类型&a…

15分钟学 Python 第37天 :Python 爬虫入门(三)

Day 37 : Python爬虫入门大纲 章节1&#xff1a;Python爬虫概述 1.1 什么是爬虫&#xff1f; 网页爬虫&#xff08;Web Crawler&#xff09;是一种自动访问互联网上网页并提取数据的程序。爬虫的作用包括搜索引擎索引内容、市场调查、数据分析等。 1.2 爬虫的工作原理 发起…

深入探究:在双链表指定元素的后面进行插入操作的顺序

归纳编程学习的感悟&#xff0c; 记录奋斗路上的点滴&#xff0c; 希望能帮到一样刻苦的你&#xff01; 如有不足欢迎指正&#xff01; 共同学习交流&#xff01; &#x1f30e;欢迎各位→点赞 &#x1f44d; 收藏⭐ 留言​&#x1f4dd;惟有主动付出&#xff0c;才有丰富的果…

Redis篇(缓存机制 - 分布式缓存)(持续更新迭代)

目录 一、单点 Redis 的问题 1. 数据丢失问题 2. 并发能力问题 3. 故障恢复问题 4. 存储能力问题 5. 四种问题的解决方案 二、Redis持久化&#xff08;两种方案&#xff09; 1. RDB持久化 1.1. 简介 1.2. 执行时机 save命令 bgsave命令 停机时 触发RDB条件 1.3. …

SpringMVC项目的创建和使用

1.新建module&#xff0c;名称叫02_springmvc &#xfeff; &#xfeff; 2.新建文件夹web &#xfeff; &#xfeff; 3.点击确定&#xff0c;就会看到如下图&#xff0c;idea自动给我们创建了web.xml &#xfeff; &#xfeff; 这时候web文件夹多一个小点点的标识 &am…

OS_过程调用与系统调用

2024.06.25&#xff1a;操作系统过程调用与系统调用学习笔记 第5节 过程调用与系统调用 5.1 过程调用/函数调用/子程序调用5.2 系统调用5.2.1 系统调用汇编层 5.3 过程调用与系统调用的对比 5.1 过程调用/函数调用/子程序调用 &#xff08;过程调用&#xff09;也称为&#xf…