Linux驱动(中断、异步通知):红外对射,并在Qt StatusBus使用指示灯进行显示

本文工作:

1、Linux驱动与应用程序编写:使用了设备树、中断、异步通知知识点,实现了红外对射状态的异步信息提醒

2、QT程序编写:自定义了一个“文本指示灯”类,并放置在QMainWidget的StatusBus中。

3、C与C++混合编程与调试:将Linux C下的面向过程转化为QT C++的面向对象。但是Linux C下signal函数需要使用static函数作为传入参数,但是C++中static的用法与C语言不一样,因此在C++中对抽象出的类进行了适配与修改

参考资料

1、《正点原子:I.MX6U嵌入式Linux驱动开发指南V1.6》

2、C/C++ static关键字详解(最全解析,static是什么,static如何使用,static的常考面试题)-CSDN博客

3、【创龙AM4379 Cortex-A9试用体验】之I/O中断异步通知驱动程序+QT捕获Linux系统信号+测试信号通知 - ARM技术论坛 - 电子技术论坛 - 广受欢迎的专业电子论坛! (elecfans.com)

4、Qt 封装一个简单的LED(指示灯)控件_qt 指示灯-CSDN博客

本文不对基础知识进行讲解,因此阅读本文需要一定的驱动/QT基础。

开发板:IMX6ULL

内核版本:4.1.15

QT版本:5.12

一、项目需求与效果

1、项目需求:

项目中的一个简单传感器:使用红外对射,检查物品是否放入了盒子中,并在QT界面的statusBus中,使用指示灯的形式进行显示与说明。

2、代码效果

红外对射-Linux驱动-QT

代码效果:屏幕左下角文本指示灯的变化

二、Linux驱动与应用程序编写

1、使用引脚说明

本次所使用的引脚为GPIO2_2,查看了I.MX6ULL核心板对GPIO的描述,该引脚可复用到GPIO1_IO02引脚上,因此我们需要先修改下设备树的文件。

2、修改设备树文件

在根节点目录下先添加节点:

gpio_infrared {compatible = "csx-gpio-infrared";pinctrl-names = "default";pinctrl-0 = <&pinctrl_infrared>;infrared-gpio = <&gpio1 2 GPIO_ACTIVE_LOW>;interrupts = < IRQ_TYPE_EDGE_BOTH>;status = "okay";};

项目中,我们需要极度关注是否有物体存入,进拿进取出都需要通知用户,因此需要中断类型使用IRQ_TYPE_EDGE_BOTH。

其中的pinctrl_infrared为:

pinctrl_infrared: infraredgrp {fsl,pins = <MX6UL_PAD_GPIO1_IO02__GPIO1_IO02 0x10B0>;};	

修改完之后,执行make dtbs,更换开发板的设备树之后,我们使用 ls /proc/device-tree查看是否有我们增加的设备树节点。

如上图,设备树修改成功,接下来就是编写驱动文件。

3、驱动文件编写

(1)结构体编写

/* 设备中断结构体 */
struct irq_gpio_infrared{int gpio;				/* gpio */int irqnum;				/* 中断号 */unsigned char value;	/* 读取的值 */char name[10];			/* 名字 */irqreturn_t (*handler)(int,void *); /* 中断服务函数 */};/* gpioinfrared设备结构体 */
struct gpio_infrared_dev{dev_t devid;			/* 设备号 	 */struct cdev cdev;		/* cdev 	*/struct class *class;	/* 类 		*/struct device *device;	/* 设备 	 */int major;				/* 主设备号	  */int minor;				/* 次设备号   */struct device_node	*nd; /* 设备节点 */struct irq_gpio_infrared irqgpioinfrared;	/* 中断结构体 */struct fasync_struct *async_queue; /* 异步相关结构体 */
};struct gpio_infrared_dev gpioinfrared;	/* infrared设备 */

代码中我们需要注意的是,使用了中断结构体,用于红外对射,检测到物体时通知用户,在各种通知方法中,使用异步通知是最可行的,其他方法需要占据大量的cpu资源,不适合本次的应用场景,因此,中断服务其实就是使用异步通知对用户进行通知,因此,我们还需要使用异步通知的结构体。

(2)获取设备树节点的信息【设备树API、GPIO子系统API】

	/* 1、获取设备节点:gpioinfrared */gpioinfrared.nd = of_find_node_by_path("/gpio_infrared");if(gpioinfrared.nd == NULL) {printk("gpioinfrared node not find!\r\n");return -EINVAL;} else {printk("gpioinfrared node find!\r\n");}/* 2、 获取设备树中的gpio属性,得到GPIO所使用的编号 */gpioinfrared.irqgpioinfrared.gpio = of_get_named_gpio(gpioinfrared.nd, "infrared-gpio", 0);if(gpioinfrared.irqgpioinfrared.gpio < 0) {printk("can't get infrared-gpio");return -EINVAL;}else{printk("infrared-gpio num = %d\r\n", gpioinfrared.irqgpioinfrared.gpio);}/* 3、初始化使用的gpio */memset(gpioinfrared.irqgpioinfrared.name,0,sizeof(gpioinfrared.irqgpioinfrared.name));sprintf(gpioinfrared.irqgpioinfrared.name,"gpioinfrared%d",i);ret = gpio_direction_input(gpioinfrared.irqgpioinfrared.gpio);if(ret < 0) {printk("can't set gpio!\r\n");}

(3)中断申请

	/* 4、设置中断模式,返回中断号 */gpioinfrared.irqgpioinfrared.irqnum = gpio_to_irq(gpioinfrared.irqgpioinfrared.gpio);printk("gpio:%d,irq:%d",gpioinfrared.irqgpioinfrared.gpio,gpioinfrared.irqgpioinfrared.irqnum);/* 申请中断 */gpioinfrared.irqgpioinfrared.handler = goio_infrared_handler;ret = request_irq(gpioinfrared.irqgpioinfrared.irqnum, gpioinfrared.irqgpioinfrared.handler, IRQF_TRIGGER_FALLING|IRQF_TRIGGER_RISING,gpioinfrared.irqgpioinfrared.name, &gpioinfrared);if(ret < 0){printk("irq %d request fail infrared!\r\n", gpioinfrared.irqgpioinfrared.irqnum);printk("irq_name: %s\r\n",gpioinfrared.irqgpioinfrared.name);return -EFAULT;}if (ret==-EBUSY){printk("irq already apply\r\n");}

(4)编写红外对射的中断函数

/*GPIO红外中断服务函数,用于发送异步信息
*/
static irqreturn_t goio_infrared_handler(int irq,void *dev_id)
{struct gpio_infrared_dev *dev = (struct gpio_infrared_dev *)dev_id;printk("irq happend!\r\n");kill_fasync(&dev->async_queue, SIGIO, POLL_IN);return IRQ_RETVAL(IRQ_HANDLED);
}

如上述所说,就是用于发送异步通信的!在这里还使用内核进行打印输出,方便检测。

(5)编写异步通信函数

static int imx6uirq_fasync(int fd, struct file *filp, int on)
{struct gpio_infrared_dev *dev = (struct gpio_infrared_dev *)filp->private_data;return fasync_helper(fd, filp, on, &dev->async_queue);
}static int imx6uirq_release(struct inode *inode, struct file *filp)
{return imx6uirq_fasync(-1, filp, 0);
}

(6)编写用户层数据接口

/** @description		: 从设备读取数据 * @param - filp 	: 要打开的设备文件(文件描述符)* @param - buf 	: 返回给用户空间的数据缓冲区* @param - cnt 	: 要读取的数据长度* @param - offt 	: 相对于文件首地址的偏移* @return 			: 读取的字节数,如果为负值,表示读取失败*/
static ssize_t infrared_read(struct file *filp, char __user *buf, size_t cnt, loff_t *offt)
{int ret = 0;unsigned char value=-1;struct gpio_infrared_dev *dev = (struct gpio_infrared_dev *)filp->private_data;value = gpio_get_value(dev->irqgpioinfrared.gpio);printk("gpioinfrared read:%d!\r\n",value);ret = copy_to_user(buf, &value, sizeof(value));return ret;
}

重点的内容都介绍完了,接下来就是检查下是否正确驱动编写是否正确了!make生成.ko文件后,传到开发板,使用insmod命令,会有如下输入:

此时,我们将红外进行对射后,就会有如下输出:

即驱动编写正确。接下来,我们先编写应用程序的代码,接收异步通知的提醒。

4、Linux C应用程序代码编写

应用程序接收异步通知需要以下三个步骤:

(1)使用signal函数设置(驱动程序所使用的)信号处理函数;

(2)将当前应用程序的内核号告知内核

(3)开启异步通知

signal(SIGIO, sigio_signal_func);   /* 设置信号SIGIO的处理函数     */
fcntl(fd, F_SETOWN, getpid());		/* 设置当前进程接收SIGIO信号   */
flags = fcntl(fd, F_GETFL);			/* 获取当前的进程状态 		  */
fcntl(fd, F_SETFL, flags | FASYNC);	/* 设置进程启用异步通知功能 	  */	
在此处的异步处理函数就很简单了,使用GPIO子系统的API获取当前的引脚数值,但是值得一提的是, signal函数的传入函数必须是使用static进行修饰的,在后面与C++代码对接时,就是因为static增加了不少的限制
/** SIGIO信号处理函数* @param - signum 	: 信号值* @return 			: 无*/
static void sigio_signal_func(int signum)
{int err = 0;unsigned int infrared_value = 0;err = read(fd, &infrared_value, sizeof(infrared_value));if(err < 0) {/* 读取错误 */printf("read error!\r\n");} else {printf("sigio signal:%d!\r\n",infrared_value);}}

接下来,我们在进行交叉编译之后

arm-linux-gnueabihf-gcc infrared_asy.c -o infrared_asy

进行测试一下。

上图所示,测试成功!

三、C++ Qt程序编写

1、自定义LedWithText

 先根据自己的需要,对参考资料第四点对自封装的LED控件进行了简化,类名为QSimpleLed

QSimpleLed.cpp文件

#include "qsimpleled.h"#include <QGradient>
#include <QPainter>
#include <QDebug>
#include <QColor>QSimpleLed::QSimpleLed(QWidget *parent, QColor color,int radius): QLabel(parent), mColor(color)
{setMinimumSize(radius, radius);setMaximumSize(radius,radius);
}void QSimpleLed::setStates(QSimpleLed::LEDSTATES states)
{switch (states) {case ON:resetStatus();mStates = ON;break;case OFF:resetStatus();break;case BLINK:resetStatus();if (!mBlinkTimer) {mBlinkTimer = new QTimer(this);connect(mBlinkTimer, &QTimer::timeout, this, &QSimpleLed::onBlinkTimerTimeout);}mBlinkTimer->setInterval(mInterval);mBlinkTimer->start();mStates = BLINK;break;default:qDebug() << "LED - unknown states!!!";}update();
}void QSimpleLed::setColor(QColor color)
{mColor = color;
}void QSimpleLed::paintEvent(QPaintEvent *event)
{Q_UNUSED(event);qreal realSize = qMin(width(), height());QPainter painter(this);painter.setRenderHint(QPainter::Antialiasing);      // 反锯齿painter.translate(width()/2, height()/2);           // 绘点移到控件中心处if(blinkState)painter.setBrush(QBrush(QColor(111,111,111)));elsepainter.setBrush(QBrush(mColor));painter.drawEllipse(QPointF(0, 0), realSize/2, realSize/2);}void QSimpleLed::resizeEvent(QResizeEvent *event)
{Q_UNUSED(event);update();
}void QSimpleLed::onBlinkTimerTimeout()
{blinkState = !blinkState;update();
}void QSimpleLed::resetStatus()
{if (mBlinkTimer && mBlinkTimer->isActive()) {mBlinkTimer->stop();}mStates = OFF;
}

QSimpleLed.h文件

#ifndef QSIMPLELED_H
#define QSIMPLELED_H#include <QLabel>
#include <QTimer>
#include <QColor>class QSimpleLed : public QLabel
{Q_OBJECTpublic:enum LEDSTATES {ON       = 0,OFF      = 1,BLINK    = 2,};QSimpleLed(QWidget *parent = nullptr, QColor color = Qt::green,int radius=16);void setStates(LEDSTATES states);void setInterval(int msec) { mInterval = msec; }void setColor(QColor color);protected:virtual void paintEvent(QPaintEvent *event) override;virtual void resizeEvent(QResizeEvent *event) override;private slots:void onBlinkTimerTimeout();private:void resetStatus();LEDSTATES mStates = OFF;QColor mColor;QTimer *mBlinkTimer = nullptr;int mInterval = 500;bool blinkState = false;};#endif // QSIMPLELED_H

再根据自己的需求,自定义一个widget,用于存放led(左)与text(右),我们在外部只需要传入led的状态、颜色、文本的内容即可,该类的名称为LedWithText。

LedWithText.cpp

#include "ledwithtext.h"
#include <QFont>
#include <QDebug>ledWithText::ledWithText(QWidget *parent, QColor color, const QString &text):QWidget(parent)
{ledLabel = new QSimpleLed(this);ledLabel->setColor(color);
//    ledLabel->setStyleSheet("border-width: 1px;border-style: solid;border-color: rgb(255, 170, 0);");textLabel = new QLabel(text,this);textLabel->adjustSize();textLabel->setAlignment(Qt::AlignVCenter);textLabel->setMinimumHeight(ledLabel->height()+5);textLabel->setVisible(!text.isEmpty());QFont ft;ft.setPointSize(14);textLabel->setFont(ft);layout = new QHBoxLayout(this);layout->addWidget(ledLabel);layout->addWidget(textLabel);layout->setSpacing(5);setLayout(layout);int adjustWith = ledLabel->width()+textLabel->width()+25;int adjustHeight = textLabel->height()+10;
//    qDebug()<<adjustHeight<<adjustWith;setGeometry(0,0,adjustWith,adjustHeight);
}ledWithText::~ledWithText()
{delete  ledLabel;delete  textLabel;
}void ledWithText::setLedColor(QColor color)
{ledLabel->setColor(color);
}void ledWithText::setLedState(QSimpleLed::LEDSTATES states)
{ledLabel->setStates(states);
}void ledWithText::setText(const QString &text)
{textLabel->setText(text);textLabel->adjustSize();textLabel->setVisible(!text.isEmpty());int adjustWith = ledLabel->width()+textLabel->width()+25;int adjustHeight = textLabel->height()+10;setGeometry(0,0,adjustWith,adjustHeight);
}void ledWithText::setTextFontSize(int size)
{QFont ft;ft.setPointSize(size);textLabel->setFont(ft);textLabel->adjustSize();int adjustWith = ledLabel->width()+textLabel->width()+25;int adjustHeight = textLabel->height()+10;setGeometry(0,0,adjustWith,adjustHeight);
}

LedWithText.h

#ifndef LEDWITHTEXT_H
#define LEDWITHTEXT_H
#include <QLabel>
#include <ui_optimize/qsimpleled.h>
#include <QWidget>
#include <QHBoxLayout>class ledWithText:public QWidget
{Q_OBJECT
public:ledWithText(QWidget *parent = nullptr, QColor color = Qt::green, const QString &text = "");~ledWithText();void setLedColor(QColor color);void setLedState(QSimpleLed::LEDSTATES states);void setText(const QString &text);void setTextFontSize(int size);private:QSimpleLed *ledLabel;QLabel *textLabel;QHBoxLayout *layout;
};#endif // LEDWITHTEXT_H

2、使用MainWidget的StatusBus存放文本指示灯

我们要把这些控件放置在状态栏中,不管切换到什么界面都可以看到,就不需要一直重复写代码了,因此,我们需要使用MainWidget的StatusBus,Widget类没有StatusBus!不要用错

void MainWindow::state_bus_init()
{device_connect_label = new ledWithText(this,Qt::green,"设备正在连接");device_connect_label->setLedColor(Qt::blue);device_connect_label->setLedState(QSimpleLed::BLINK);device_connect_label->setTextFontSize(10);ui->statusbar->addWidget(device_connect_label);device_place_label = new ledWithText(this,Qt::green,"设备未放置");device_place_label->setTextFontSize(10);ui->statusbar->addWidget(device_place_label);
}

 就可以看到如下效果了。我们自定义的LedWithText类的效果就显示在左下角了。

3、Qt接受异步通知,并根据结果改变文本指示灯

按道理,最简单的做法,这一步只需要将应用层的代码搬过来就可以,但是在上文我们提到,在Linux C的应用程序中,signal函数需要传入static修饰的函数,但是Qt使用C++语言,想要将其转化为类(而不是面向过程),就需要解决static在C语言和C++的差异。

#include "infrareddev.h"InfraredDev::InfraredDev(QObject *parent) : QObject(parent)
{fd = open(DEVNAME, O_RDWR);if (fd < 0) {qDebug()<<"Can't open file :"<<DEVNAME;}else{register_infrared_asy();qDebug()<<"infrared:init succeed!";}}InfraredDev::~InfraredDev()
{if(fd){close(fd);}
}void InfraredDev::set_dev_name(char *name)
{dev_name = name;
}char *InfraredDev::get_dev_name()
{return dev_name;
}void InfraredDev::setLedWithText(ledWithText *obj)
{infrared_ledWithText = obj;
}void InfraredDev::sigio_signal_func(int signum)
{int err = 0;unsigned int infrared_value = 0;err = read(fd, &infrared_value, sizeof(infrared_value));if(err < 0) {
//        InfraredDev instance; // 创建对象实例
//        emit instance.infraredSignal(infrared_value);/* 读取错误 */infrared_ledWithText->setLedColor(Qt::red);infrared_ledWithText->setLedState(QSimpleLed::BLINK);infrared_ledWithText->setText("获取设备失败");qDebug()<<"infrared:read error!";} else {if(infrared_value==0){infrared_ledWithText->setLedColor(Qt::green);infrared_ledWithText->setText("设备已放置");}else if(infrared_value==1){infrared_ledWithText->setLedColor(Qt::red);infrared_ledWithText->setLedState(QSimpleLed::BLINK);infrared_ledWithText->setText("设备未放置");}qDebug()<<"infrared:sigio signal!"<<infrared_value;}}void InfraredDev::register_infrared_asy()
{int flags = 0;/* 设置信号SIGIO的处理函数 */signal(SIGIO, &InfraredDev::sigio_signal_func);fcntl(fd, F_SETOWN, getpid());		/* 设置当前进程接收SIGIO信号 	*/flags = fcntl(fd, F_GETFL);			/* 获取当前的进程状态 			*/fcntl(fd, F_SETFL, flags | FASYNC);	/* 设置进程启用异步通知功能 	*/
}int InfraredDev::fd = -1; // 初始化为无效的文件描述符
ledWithText *InfraredDev::infrared_ledWithText = nullptr;
#ifndef INFRAREDDEV_H
#define INFRAREDDEV_H#include "stdio.h"
#include "unistd.h"
#include "sys/types.h"
#include "sys/stat.h"
#include "fcntl.h"
#include "stdlib.h"
#include "string.h"
#include "poll.h"
#include "sys/select.h"
#include "sys/time.h"
#include "linux/ioctl.h"
#include "signal.h"#include <QObject>
#include <QDebug>
#include <QFile>
#include <QTextStream>
#include <QString>#include "ui_optimize/ledwithtext.h"#define DEVNAME "/dev/gpio_infrared"class InfraredDev : public QObject
{Q_OBJECT
public:explicit InfraredDev(QObject *parent = nullptr);~InfraredDev();void set_dev_name(char *name);char * get_dev_name();static ledWithText *infrared_ledWithText;static void setLedWithText(ledWithText *obj);private:static int fd;	/* 文件描述符 */static QFile file;char *dev_name;static void sigio_signal_func(int signum);void register_infrared_asy(void);};#endif // INFRAREDDEV_H

因为static修饰的成员变量、成员函数并没有this指针,因此无法读取其他非static成员只允许读取static变量,因此我们需要将fd也需要使用static函数进行修饰,并且函数内不能包含其他no-static的变量。

因此在signal函数,我们就需要根据C++访问静态函数的规则,对参数进行传入了修改,使用通过(类名::静态成员)的方式来访问。

signal(SIGIO, &InfraredDev::sigio_signal_func);

 然后,我们需要让QMainwindow类知道,接收到异步通信了,需要刷新UI了。

(1)信号机制方法

我一开始是照常使用信号机制,定义了信号函数,使用emit函数进行发送,但是因为异步通知处理函数是static类的,无法直接调用其他non-static的成员,无法发送信号,因此我想是实例化一个类,发送类的实例,进而发送信号:

InfraredDev instance; // 创建对象实例
emit instance.infraredSignal(infrared_value);

代码没报错,但是执行过程出错了,在开发板上只能读取第一次的数值,发送后,就无法进行读取,由于是在开发板上进行运行的,无法进行debug,不知道是什么原因,如果有大神知道,还请不吝赐教!

(2)指针传入做法

之后,我看到了参考资料的3的做法,就想直接传入界面的指针,在异步通知里面,直接读取指针,进行界面的修改。因此我就根据,non-static成员函数可以访问static成员变量的特性,对该做法进行了改进。定义了一个设置控件的函数,外部传入一个控件指针,函数内部设置为static类型,因此完美解决了该问题。

void InfraredDev::setLedWithText(ledWithText *obj)
{infrared_ledWithText = obj;
}// 在static函数就可以使用这个static指针进行设置了
void InfraredDev::sigio_signal_func(int signum){......infrared_ledWithText->setLedColor(Qt::red);infrared_ledWithText->setLedState(QSimpleLed::BLINK);infrared_ledWithText->setText("设备未放置");}

在infrared_dev.h中,存在该声明,为static成员变量

 static ledWithText *infrared_ledWithText;

那么,我们在外部只需要传入该控件的指针即可

device_connect_label = new ledWithText(this,Qt::green,"设备正在连接");......
infrared_dev = new InfraredDev();
infrared_dev->setLedWithText(device_place_label);

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【华为数据之道学习笔记】5-4 数据入湖方式

数据入湖遵循华为信息架构&#xff0c;以逻辑数据实体为粒度入湖&#xff0c;逻辑数据实体在首次入湖时应该考虑信息的完整性。原则上&#xff0c;一个逻辑数据实体的所有属性应该一次性进湖&#xff0c;避免一个逻辑实体多次入湖&#xff0c;增加入湖工作量。 数据入湖的方式…

Android Studio好用的插件推荐

目录 一、插件推荐 二、如何下载 1.点击File—>Settings ​2.点击Plugins然后进行搜索下载 三、Android Studio 模板 一、插件推荐 这个插件可以为您自动生成Parcelable代码。Parcelable是一种用于在Android组件之间传递自定义对象的机制&#xff0c;但手动编写Parcela…

RabbitMQ搭建集群环境、配置镜像集群、负载均衡

RabbitMQ集群搭建 Linux安装RabbitMQ下载安装基本操作命令开启管理界面及配置 RabbitMQ集群搭建确定rabbitmq安装目录启动第一个节点启动第二个节点停止命令创建集群查看集群集群管理 RabbitMQ镜像集群配置启用HA策略创建一个镜像队列测试镜像队列 负载均衡-HAProxy安装HAProxy…

从计算机底层深入Golang高并发

从计算机底层深入Golang高并发 1.源码流程架构图 2.源码解读 runtime/proc.go下的newpro() func newproc(fn *funcval) {//计算额外参数的地址argpgp : getg()pc : getcallerpc()//s1使用systemstack调用newproc1 systemstack(func() {newg : newproc1(fn, gp, pc)_p_ : getg…

代码随想录二刷 | 二叉树 | 112. 路径总和

代码随想录二刷 &#xff5c; 二叉树 &#xff5c; 112. 路径总和 题目描述解题思路递归迭代 代码实现递归迭代 题目描述 112.路径总和 给你二叉树的根节点 root 和一个表示目标和的整数 targetSum 。判断该树中是否存在 根节点到叶子节点 的路径&#xff0c;这条路径上所有节…

leetcode-138-随机链表的复制(Java实现)

题目&#xff1a; 给你一个长度为 n 的链表&#xff0c;每个节点包含一个额外增加的随机指针 random &#xff0c;该指针可以指向链表中的任何节点或空节点。 构造这个链表的 深拷贝。 深拷贝应该正好由 n 个 全新 节点组成&#xff0c;其中每个新节点的值都设为其对应的原节点…

【LeetCode刷题】-- 166.分数到小数

166.分数到小数 class Solution {public String fractionToDecimal(int numerator, int denominator) {StringBuilder sb new StringBuilder();HashMap<Long,Integer> map new HashMap<>();//为了防止溢出&#xff0c;将分子和分母都转成64位整数long a numerat…

女生想通过培训转行软件测试类可行吗?

首先&#xff0c;女生转行IT行业做软件测试是可以的&#xff0c;因为软件测试岗&#xff0c;尤其是其中的功能性测试岗&#xff0c;入行门槛并不高&#xff0c;有很多女生在做&#xff0c;且我个人认为还蛮适合女生的&#xff0c;因为女生相对来说更细心&#xff0c;文档能力也…

HashMap构造函数解析与应用场景

目录 1. HashMap简介 2. HashMap的构造函数 2.1 默认构造函数 2.2 指定初始容量和加载因子的构造函数 3. 构造函数参数的影响 3.1 初始容量的选择 3.2 加载因子的选择 4. 构造函数的应用场景 4.1 默认构造函数的应用场景 4.2 指定初始容量和加载因子的构造函数的应用…

Linux(23):Linux 核心编译与管理

编译前的任务&#xff1a;认识核心与取得核心原始码 Linux 其实指的是核心。这个【核心(kernel)】是整个操作系统的最底层&#xff0c;他负责了整个硬件的驱动&#xff0c;以及提供各种系统所需的核心功能&#xff0c;包括防火墙机制、是否支持 LVM 或 Quota 等文件系统等等&a…

FFmpeg的AVcodecParser

文章目录 结构体操作函数支持的AVCodecParser 这个模块是AVCodec中的子模块&#xff0c;专门用来提前解析码流的元数据&#xff0c;为后面的解码做准备&#xff0c;这一点对cuda-NVdec非常明显&#xff0c;英伟达解码器的元数据解析是放在CPU上的&#xff0c;所以就非常依赖这个…

预测性维护对制造企业设备管理的作用

制造企业设备管理和维护对于生产效率和成本控制至关重要。然而&#xff0c;传统的维护方法往往无法准确预测设备故障&#xff0c;导致生产中断和高额维修费用。为了应对这一挑战&#xff0c;越来越多的制造企业开始采用预测性维护技术。 预测性维护是通过传感器数据、机器学习和…

jmeter,取“临时重定向的登录接口”响应头中的cookie

1、线程组--创建线程组&#xff1b; 2、线程组--添加--取样器--HTTP请求&#xff1b; 3、Http请求--添加--后置处理器--正则表达式提取器&#xff1b; 4、线程组--添加--监听器--查看结果树&#xff1b; 5、线程组--添加--取样器--调试取样器。 首先理解 自动重定向 与跟随…

【漏洞复现】红帆OA iorepsavexml.aspx文件上传漏洞

漏洞描述 广州红帆科技深耕医疗行业20余年,专注医院行政管控,与企业微信、阿里钉钉全方位结合,推出web移动一体化办公解决方案——iOffice20(医微云)。提供行政办公、专业科室应用、决策辅助等信息化工具,采取平台化管理模式,取代医疗机构过往多系统分散式管理,实现医…

【Qt】使用QDataStream向QByteArray内读写数据时,输出QByteArray数据为空解决方案

原因 今天写示例时&#xff0c;用到使用QDataStream类向QByteArray读写数据&#xff0c;但打印出来为空。 下面是简化代码&#xff1a; QByteArray ba;QDataStream out(&ba, QIODevice::WriteOnly);out << "helloworld";qDebug().noquote() << &quo…

地图自定义省市区合并展示数据整合

需求一&#xff1a;将省级地图下的两个市合并成一个区域&#xff0c;中间的分割线隐藏。 1、访问下方地址&#xff0c;搜索并下载省级地图json文件。 地址&#xff1a;https://datav.aliyun.com/portal/school/atlas/area_selector 2、切换到边界生成器&#xff0c;上传刚刚下…

手写VUE后台管理系统10 - 封装Axios实现异常统一处理

目录 前后端交互约定安装创建Axios实例拦截器封装请求方法业务异常处理 axios 是一个易用、简洁且高效的http库 axios 中文文档&#xff1a;http://www.axios-js.com/zh-cn/docs/ 前后端交互约定 在本项目中&#xff0c;前后端交互统一使用 application/json;charsetUTF-8 的请…

ubuntu debian mini安装系统 有线选项消失或ens33 ethernet 未托管解决方法

nmcli device status#修改NetworkManager.conf如下 sed s/false/true/ /etc/NetworkManager/NetworkManager.confsed -i s/false/true/ /etc/NetworkManager/NetworkManager.conf#重启生效systemctl restart NetworkManager

[NCTF2019]Fake XML cookbook1

提示 xml注入 一般遇到像登录页之类的就因该想到sql注入、弱口令或者xml等 随便输入抓包 这里明显就是xml注入 这里我们来简单了解一下xml注入 这里是普通的xml注入 xml注入其实和sql注入类似&#xff0c;利用了xml的解析机制如果系统没有将‘<’‘>’进行转义&#xff0…

图扑物联 | WEB组态可视化软件

什么是组态&#xff1f; 组态的概念来自于20世纪70年代中期出现的第一代集散控制系统&#xff08;Distributed Control System&#xff09;&#xff0c;可理解为“配置”、“设置”等&#xff0c;是指通过人机开发界面&#xff0c;用类似“搭积木”的简单方式来搭建软件功能&a…