linux驱动学习加强版-5(ioctl的使用)

文章目录

  • 一、添加ioctl控制节点
  • 二、修改测试APP
    • 2.1 测试APP的代码:
    • 2.2 驱动代码:

ioctl是用户空间和内核空间相互交流时候用的比较多的一种手段。
我们也可以在HAL层通过ioctl调到驱动里面。

一、添加ioctl控制节点

先看patch 吧
在这里插入图片描述

这是在驱动中添加的ioctl函数,同样的在ioctl里面去添加操作函数集合

二、修改测试APP

直接上源码:

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

// 我们目前只传递一个参数
static int file_ioctl(unsigned int cmd) {
    return 1;
}

#define FILECTL_READ       _IOR('c',0,unsigned int)   //对文件进行读取的命令
#define FILECTL_WRITE      _IOW('c',0,unsigned int)  //对文件进行写入的命令

int main(int argc,char **argv)
{   
    if(argc <2)
    {
        printf("Usage:%s -w <string>\n",argv[0]);
        printf("Usage:%s -r \n",argv[0]);

        return -1;
    }
    
    int fd;
    char buf[1024];
    fd = open("/dev/filectl",O_RDWR);
    if(fd < 0)
    {
        printf("can not open /dev/filectl\n");
        return -1;
    }
    printf("open /dev/filectl success \n");
    // 屏蔽掉原来的参数
    // if(strcmp(argv[1],"-w")==0 && argc==3)
    // {
    //     int err = write(fd, argv[2], strlen(argv[2]));
    //     if (err < 0 ) {
    //         printf("write /dev/filectl error \n");
    //         return -1;
    //     }
    //     printf("write /dev/filectl success \n");
    // }else
    // {
    //     int err = read(fd,buf,1024);
    //     if (err < 0 ) {
    //         printf("read /dev/filectl error \n");
    //         return -1;
    //     }
    //     printf("read /dev/filectl success \n");
    //     buf[1023] = '\n';
    //}

    // 添加ioctl的函数
    if (strcmp(argv[1] , "ior") == 0 ) { //通过参数比较来获取命令
        int rc = ioctl(fd, FILECTL_READ); // 通过ioctl 函数去传递参数
        if ( rc < 0 ) {
            printf("ioctl read  /dev/filectl error \n");
            return -1;
        }
        printf("ioctl read  /dev/filectl sucess \n");
    } else if ( strcmp(argv[1], "iow") == 0 ) {
        int rc = ioctl(fd, FILECTL_WRITE, argv[2]);
        if ( rc < 0 ) {
            printf("ioctl read  /dev/filectl error \n");
            return -1;
        }
        printf("ioctl read  /dev/filectl sucess \n");
    } else {
        printf("please input right argv[1], 'ior' or 'iow'");
        printf("It will return error\n");
        return -1;
    }
        printf("APP get data %s\n",buf);

    close(fd);
    
    return  0;
}

然后我们加载模块,运行测试app
在这里插入图片描述
在这里插入图片描述

同样的我们还是会存在问题,就是读写的接口这些是有问题的,和之前的逻辑一样,下一步就是完善这个代码逻辑。
目前我们的框架已经是ok的了

话不多说 直接上代码:

2.1 测试APP的代码:

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

#define FILECTL_READ       _IOR('c', 0, unsigned int)   //对文件进行读取
#define FILECTL_WRITE      _IOW('c', 0, unsigned int)  //对文件进行写入

int main(int argc,char **argv)
{   
	int temp = 0;
	char buffer[1024];  // 存放内核拷贝的数据
	if(argc <2)
    {
        printf("Usage:%s -w <string>\n",argv[0]);
        printf("Usage:%s -r \n",argv[0]);

        return -1;
    }
    
    int fd;
    char buf[1024];
    fd = open("/dev/filectl",O_RDWR);
    if(fd < 0)
    {
        printf("can not open /dev/filectl\n");
        return -1;
    }
    printf("open /dev/filectl success \n");

    if(strcmp(argv[1],"-w")==0 && argc==3)
    {
        int err = write(fd, argv[2], strlen(argv[2]));
        if (err < 0 ) {
            printf("write /dev/filectl error \n");
            return -1;
        }
        printf("write /dev/filectl success \n");
        printf("APP set  data %s\n",argv[2]);
    }else if (strcmp(argv[1],"-r")==0) {
        int err = read(fd,buf,1024);
        if (err < 0 ) {
            printf("read /dev/filectl error \n");
            return -1;
        }
        printf("read /dev/filectl success \n");
        printf("APP get  data %s\n", buf);
        buf[1023] = '\n';
    } else if (strcmp(argv[1] , "ior") == 0 ) {
        int rc = ioctl(fd, FILECTL_READ, &buffer); // 将内核传递的数据读取出来
        if ( rc < 0 ) {
            printf("ioctl read  /dev/filectl error \n");
            return -1;
        }
        printf("ioctl read  /dev/filectl sucess \n");
        printf("APP get  data %s\n", buffer);
        buf[1023] = '\n';
    } else if ( strcmp(argv[1], "iow") == 0 ) {
        int rc = ioctl(fd, FILECTL_WRITE, argv[2]); // 写入数据
        if ( rc < 0 ) {
            printf("ioctl write /dev/filectl error \n");
            return -1;
        }
        printf("ioctl read  /dev/filectl sucess \n");
        printf("APP set data %s\n",argv[2]);
    } else {
        printf("please input right argv[1], 'ior' or 'iow'");
        printf("It will return error\n");
        return -1;
    }
    close(fd);

    return  0;
}

2.2 驱动代码:

#include <linux/module.h>
#include <linux/fs.h>
#include <linux/major.h>
#include <linux/init.h>
#include <linux/device.h>
#include <linux/stat.h>
#include <linux/tty.h>

static int major = 0; //确定主设备号,0默认系统分配
static struct class *filectl_class;
unsigned char kbuffer[1024]; // 内核空间的buffer
unsigned char ubuffer[1024]; // 申请一段空间用于存放用户数据

/*
  * FILECTL_READ 是和测试传递的参数是一样的才能匹配上 
  * FILECTL_WRITE 同样如此
  */

#define FILECTL_READ       _IOR('c', 0, unsigned int)   //对文件进行读取
#define FILECTL_WRITE      _IOW('c', 0, unsigned int)   //对文件进行写入


static long filectl_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
    int ret;
	printk("[%s %d]1111\n", __FUNCTION__, __LINE__);

	switch(cmd) {
		case FILECTL_READ:
            ret = copy_to_user((void __user *)arg, ubuffer, sizeof(ubuffer)); // 将内核空间的buffer拷贝至用户空间
            if(ret < 0) {
                printk("[%s %d]copy_to_user error\n ",__FUNCTION__, __LINE__);
			}
			printk("[%s %s %d]\n", __FILE__, __func__, __LINE__);
			break;
		case FILECTL_WRITE:
            ret = copy_from_user(ubuffer, (void __user *)arg, sizeof(ubuffer)); 
            if(ret < 0) {
                printk("[%s %d]copy_from_user error \n ",__FUNCTION__, __LINE__);
            }
			printk("[%s %s %d]\n", __FILE__, __func__, __LINE__);
			break;
	}
    return 0;
}

ssize_t filectl_read(struct file *file, char __user *buf, size_t size, loff_t *pops)
{
    int ret;
	printk("[%s %d]\n", __FUNCTION__, __LINE__);
    ret = copy_to_user(buf, kbuffer, size);
    if(ret < 0) {
        printk("[%s %d]copy_to_user error \n ",__FUNCTION__, __LINE__ );
    }
	printk("[%s %s %d]\n", __FILE__, __func__, __LINE__);
    return size;
}

ssize_t filectl_write(struct file *file,const char __user *buf, size_t size, loff_t *pops)
{
    int ret;
	printk("[%s %d]\n", __FUNCTION__, __LINE__);
    ret = copy_from_user(kbuffer, buf, size);
    if(ret < 0) {
        printk("[%s %d]copy_from_user error \n ",__FUNCTION__, __LINE__ );
    }
    return size;
}

int filectl_open(struct inode *inode, struct file *file)
{
	printk("[%s %d]\n", __FUNCTION__, __LINE__);
    return 0;
}

int filectl_close(struct inode *inode, struct file *file)
{
	printk("[%s %d]\n", __FUNCTION__, __LINE__);
    return 0;
}

// 定义自己的驱动的 file_operations
static struct file_operations filectl_ops = {
    .owner	 = THIS_MODULE,
    .read    = filectl_read,
    .write   = filectl_write,
    .open    = filectl_open,
    .release = filectl_close, // 好像没有close这个函数
    .unlocked_ioctl = filectl_ioctl, //添加ioclt操作函数
};

static int __init filectl_init(void)
{
    // 在初始化的时候进行驱动注册, 设备号, 设备名,核心操作函数
    major = register_chrdev(0,"filectl",&filectl_ops); 
    if(major < 0) {
        printk("[%s %d] filectl error\n", __FUNCTION__, __LINE__); // 注册失败
        return -1;
    }

    filectl_class = class_create(THIS_MODULE, "filectl"); // class_create 动态创建dev的类
    // IS_ERR 查看指针是否有错误
    if(IS_ERR(filectl_class)) {
        printk("[%s %d] class_create error\n", __FUNCTION__, __LINE__);
        unregister_chrdev(major,"filectl");
        return -1;
    }
	// 创建字符设备
    device_create(filectl_class, NULL, MKDEV(major, 0),NULL, "filectl");
    printk("[%s %d] filectl driver create success\n", __FUNCTION__, __LINE__);

    return 0;
}

static void __exit filectl_exit(void) {
    device_destroy(filectl_class, MKDEV(major, 0));
    class_destroy(filectl_class);
    // 注销字符设备
	unregister_chrdev(major,"filectl");
    printk("[%s %d]goodbye filectl driver\n",  __FUNCTION__, __LINE__);
}

module_init(filectl_init);
module_exit(filectl_exit);
MODULE_LICENSE		("GPL");
MODULE_AUTHOR		("cong.luo");
MODULE_DESCRIPTION	("First file contrl module");

测试结果:
在这里插入图片描述

内核使用两个buf,使用 ioctl 和 之前的读写接口互不影响。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

个人-计算机操作系统第五章

第五章 虚拟存储器 一、章节练习 1.系统抖动是指( )。 A. 使用机器时&#xff0c;千万屏幕闪烁的现象 B. 刚被调出的页面又立刻被调入所形成的频繁调入调出现象 C. 系统盘不净&#xff0c;千万系统不稳定的现象 D. 由于内存分配不当&#xff0c;偶然造成内存不够…

02-神经网络基础

一、从机器学习到神经网络 1. 两层神经网络 - 多层感知机 2. 浅层神经网络特点 (1)需要数据量小、训练速度快; (2)对复杂函数的表示能力有限,泛化能力受到制约。 Kurt Hornik 证明了理论上两层神经网络足以拟合任意函数,而且过去没有足够的数据和计算能力,因此之前的…

兰伯特光照模型(Lambert Lighting)和半兰伯特光照模型(Half-Lanbert)

关于漫反射 光打到凹凸不平的平面上&#xff0c;光线会被反射到四面八方&#xff0c;被称为漫反射 关于这种模型&#xff0c;由于光线由于分散&#xff0c;所以进入人眼的光线强度和观察角度没有区别 在A点和B点接收到的光线强度是一样的 在漫反射下&#xff0c;光线强度只和光…

卫龙携手契约锁,推动人事、采购、销售业务电子签

知名辣味休闲食品企业——卫龙&#xff0c;携手契约锁就印章管控及电子签章技术展开合作&#xff0c;打造覆盖总部及20多家子公司的印章管控平台&#xff0c;以现有泛微OA、钉钉APP为基础&#xff0c;推动人事、采购、销售业务电子签&#xff0c;通过签字、盖章无纸化&#xff…

使用Navicat进行ssh通道连接MySQL数据库

1、正常打开连接窗口&#xff0c;选择SSH&#xff1b; 2、填写完SSH对应参数&#xff0c;重新选择常规&#xff1b; SSH参数&#xff1a; 主机 > 服务器IP 端口 > 22 【一般22&#xff0c;SSH监听端口】 用户名 > 登录服务器账户 密码 > 登录服务器密码常规的参数…

mplfinancet绘制K线图

mplfinancet绘制K线图 1、安装 安装速度快 pip install mplfinance -i https://pypi.tuna.tsinghua.edu.cn/simple C:\Users>pip install mplfinance -i https://pypi.tuna.tsinghua.edu.cn/simple Defaulting to user installation because normal site-packages is not …

35岁的测试工程师被公司强行辞退,感叹道:我以前就该好好努力了

曾经的高薪软件测试工程师&#xff0c;今年35岁了&#xff0c;被公司劝退了&#xff0c;外卖跑到凌晨&#xff0c;很累&#xff0c;但还是有一种想诉说的冲动。哪怕让大家觉得已经说得太多了&#xff0c;烦了&#xff0c;都成祥林嫂了&#xff0c;但是&#xff0c;我是真的想说…

js:手写一个promise

背景 promise 作为前端开发中常用的函数&#xff0c;解决了 js 处理异步时回调地狱的问题&#xff0c;大家应该也不陌生了&#xff0c;今天来学习一下 promise 的实现过程&#xff0c;这样可以加&#xff08;面&#xff09;深&#xff08;试&#xff09;理&#xff08;要&…

第八天并发编程篇

一、简述线程、进程、程序的基本概念&#xff1f; 1.进程&#xff1a; 我们把运行中的程序叫做进程,每个进程都会占用内存与CPU资源,进程与进程之间互相独立. 2.线程&#xff1a; 线程就是进程中的一个执行单元&#xff0c;负责当前进程中程序的执行。一个进程可以包含多个线程…

Matlab在线IDE:计算定积分上限

上一篇文章&#xff1a;Matlab在线IDE&#xff1a;MATLAB Online介绍与计算定积分案例 1、案例介绍 % 定义符号变量 x syms x;% 定义函数 f(x) x f x;% 定义定积分的值 I I 2;% 计算函数 f(x) 在 [0, x] 区间的定积分&#xff0c;并求其反函数 F(x) F finverse(int(f, 0, …

【hello Linux】Linux软件管理器yum

目录 1.Linux软件管理器yum 1.1 关于lrzsz 1.2 使用yum时的注意事项 1.3 查看软件包&#xff1a;yum list 1.4 安装软件&#xff1a;yum install 1.5 卸载软件&#xff1a;yum remove 1.6 更新yum源 1.7 实战项目 Linux&#x1f337; 1.Linux软件管理器yum 在windows系统下有应…

ROS学习——艰辛的环境安装之路一Ubuntu

文章目录Ubuntu安装和下载页面设置安装Vmware Tools安装VSCODE用几个常用命令简单熟悉下UbuntuUbuntu 安装和下载 Ubuntu的安装和下载 看这个链接 Ubuntu安装和下载1 或者这个链接 Ubuntu安装和下载2 页面设置 安装Vmware Tools 看这个链接 VMware Tools的介绍和安装 安装…

超详细从入门到精通,pytest自动化测试框架实战-pytest插件的开发(八)

目录&#xff1a;导读前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09;前言 pytest框架采用的是…

3年测试经验只会“点点点”,不会自动化即将面临公司淘汰?沉淀100天继续做测试

前段时间一个朋友跟我吐槽&#xff0c;说自己做软件测试工作已经3年了&#xff0c;可这三年自己的能力并没有得到提升&#xff0c;反而随着互联网的发展&#xff0c;自己只会“点点点”的技能即将被淘汰。说自己很苦恼了&#xff0c;想要提升一下自己&#xff0c;可不知道该如何…

简单的做一个学校毕业啊项目

前言&#xff1a;相信看到这篇文章的小伙伴都或多或少有一些编程基础&#xff0c;懂得一些linux的基本命令了吧&#xff0c;本篇文章将带领大家服务器如何部署一个使用django框架开发的一个网站进行云服务器端的部署。 文章使用到的的工具 Python&#xff1a;一种编程语言&…

每日一练——Day 13

前言&#xff1a; 小亭子正在努力的学习编程&#xff0c;接下来将开启编程题的练习~~ 分享的文章都是学习的笔记和感悟&#xff0c;如有不妥之处希望大佬们批评指正~~ 同时如果本文对你有帮助的话&#xff0c;烦请点赞关注支持一波, 感激不尽~~ 第一题 题目描述&#xff1a; 刷…

SpringBoot基础学习之(十二):通过spring boot框架连接MySql数据库(通过idea中的工具Database连接Mysql数据库)

Springboot这个系列实现的案例&#xff1a;员工后台管理系统 之前讲解的内容是前后端的交互&#xff0c;并没有涉及到数据库。把员工信息放置在一个数组中&#xff0c;实现的方法则是对数组的增删改查操作&#xff0c;但是从今天开始&#xff0c;实现的功能则是在数据库的基础上…

Qt Quick - ToolTip

Qt Quick - ToolTip使用总结一、概述二、附带的ToolTip三、延迟和超时四、自定义ToolTip五、定制化一、概述 ToolTip 其实就是ToolTip&#xff0c;所谓ToolTip其实就是一段简短的文本&#xff0c;告知用户控件的功能。它通常置于父控件之上或之下。提示文本可以是任何富文本格…

为什么程序员都喜欢开源的软件?

先来感受一下开源与闭源&#xff1a; 当你觉得这个软件有一个缺点影响使用的时候 如果是闭源软件&#xff0c;你如果不想自己模仿着写一个&#xff0c;就只能考虑顺着网线到开发者脖子上逼着他加 但开源软件你可以自己在他的基础上改一改&#xff0c;你改好了还拿回馈回去让…

动力节点王鹤SpringBoot3笔记——第七章 视图技术Thymeleaf

目录 第七章 视图技术Thymeleaf 前言 7.1 表达式 7.2 if-for 第七章 视图技术Thymeleaf 前言 Thymeleaf 是一个表现层的模板引擎&#xff0c; 一般被使用在 Web 环境中&#xff0c;它可以处理 HTML, XML、 JS 等文档&#xff0c;简单来说&#xff0c;它可以将 JSP 作…