当前位置: 首页 > news >正文

DBus快速入门

DBus快速入门

参考链接:

  1. 中文博客:

    https://www.e-learn.cn/topic/1808992

    https://blog.csdn.net/u011942101/article/details/123383195

    https://blog.csdn.net/weixin_44498318/article/details/115803936

    https://www.e-learn.cn/topic/1808992

    https://blog.csdn.net/Dontla/article/details/122530765

  2. D-Bus Specification:

    https://dbus.freedesktop.org/doc/dbus-specification.html

    https://pythonhosted.org/txdbus/dbus_overview.html

    https://dbus.freedesktop.org/doc/dbus-tutorial.html

本文主要记录一下我对dbus的认知,当然可能会存在一些错误,欢迎读者指正。

DBus安装

命令如下:

# 安装dbus
sudo apt-get install dbus# 安装d-feet工具,用于查看 session bus 和 system bus
sudo apt-get install d-feet# 安装glib2.0
sudo apt-get install libgtk2.0-dev# 安装 dbus-glib
apt-get install libdbus-glib-1-dev# for dbus-launch
apt install dbus-x11

c_cpp_properties.json配置:

主要注意includePath

{"configurations": [{"name": "Linux","includePath": ["${workspaceFolder}/**","/usr/include/dbus-1.0/","/usr/include/glib-2.0/","/usr/lib/x86_64-linux-gnu/glib-2.0/include/"],"defines": [],"compilerPath": "/usr/bin/clang","cStandard": "c17","cppStandard": "c++14","intelliSenseMode": "linux-clang-x64"}],"version": 4
}

DBus整体结构

DBus是基于本地套接字实现的IPC框架,可用于进程间的通信或进程与内核的通信。

这里贴一张官方提供的dbus整体架构图:

在这里插入图片描述

DBUS的优点:

  1. 因为DBUS主要应用在同一台机器上,不会跨主机进行IPC通信。所以使用二进制协议,省去序列化的代价。但是如果需要传递像字符串指针的话,就需要通过地址将字符串拷贝到Message中,所以或多或少还是存在一些序列化的过程。

  2. DBUS的“报文”在传递时,避免了往返的开销。并且支持异步操作。

  3. 报文以消息的方式传递而不是(类似于TCP)字节流。

  4. D-Bus 库的封装方式可以让开发人员利用其框架现有的对象/类型系统,而无需学习新的IPC的特点,然后重构他们的项目。

这里简单解释一下dbus整体架构图的一个交互流程:

在DBUS中,一个完整的IPC交互流程包括三个部分:Bus Daemon Process、Client Application Process、Server Application Process。Bus Daemon Process有两类:Session Bus、System Bus,这里本文主要讨论Session Bus,这两类Bus主要区别在于:Session Bus是主要负责应用程序之间的一个交互,而System Bus主要负责内核和应用程序之间的一个交互。Bus Daemon Process在两个应用程序交互之中起路由作用。从图中可以看到所有的应用程序和Bus Daemon Process的连接都是通过本地socket。

主要流程:

  1. app1(client)和app2(server)都通过Bus Daemon Process的套接字地址连接上去。

  2. app1请求一个叫com.app1.client的Bus Name,app2请求一个叫com.app2.server的Bus Name

  3. app1构造一个method calls消息,method calls消息至少包括:Dest Bus Name(目的地址,假设这里是com.app2.server)、Object Path、Interface Name 、Method Name(包括参数,这里假设是int add(int n1, int n2)),然后将消息报文发送给Bus Daemon Process。

  4. Bus Daemon Process根据消息的Dest Bus Name,将消息路由给app2。

  5. app2根据消息的Object Path、Interface Name 、Method Name调用相应的方法(add函数),然后根据返回值以及接收到的method calls消息封装成一条method returns消息,发回给Bus Daemon Process,进而路由给app1。

  6. app1接收到method returns消息后解析出里面的返回值,于此一次交互完成。

dbus中消息有四种类型:

  1. signals:信号,一般用于广播,不会有目的地址和返回值。

  2. method calls:方法调用,定向传播,有目的地址,可能有返回值。

  3. method returns:方法返回,简单理解就是method calls的返回值。

  4. errors:错误,简单理解就是错误码。

上面流程主要用到method calls、method returns两种消息类型。

梳理了一下dbus的交互流程,其实会发现dbus和RPC非常像。不同点在于dbus更像是一种本地专用的RPC。

dbus-daemon的地址保存在环境变量DBUS_SESSION_BUS_ADDRESS中,用于表示当前登录用户的session的dbus-daemon进程的地址,可以使用下面命令查看。

root@lunar-virtual-machine:~# echo $DBUS_SESSION_BUS_ADDRESS
unix:path=/run/user/0/bus

session bus由用户登录时dbus-launch脚本自动启动,当然,你也可以自己在终端启动一个bus-daemon,方便调试:

root@lunar-virtual-machine:~# DBUS_VERBOSE=1 dbus-daemon --session --print-address
unix:abstract=/tmp/dbus-49gl7TnTcs,guid=864158a61bb94df92e3e1ac866936bd1

然后将DBUS_SESSION_BUS_ADDRESS修改为:unix:abstract=/tmp/dbus-49gl7TnTcs,guid=864158a61bb94df92e3e1ac866936bd1,再启动应用程序即可连接到自己启动的dbus-daemon上。

DBus深入理解

先下载一个dbus实例:http://www.fmddlmyy.cn/down2/hello-dbus3-0.1.tar.gz

四步构建并运行dbus服务器

./autogen.sh
./configure
make
./example-service

然后另起一个终端,执行d-feet命令,会弹出一个窗口:

在这里插入图片描述

双击Methods下的Add方法,会弹出一个对话框,输入参数并确认后你就会看到相加的结果。这个具体的交互过程和。上面我们分析的流程是一样的。

下面通过该窗口逐步了解DBUS的相关概念。

Bus Name: 应用和消息总线的连接标识符,有两类,包括:well-known name(熟知名)和unique name(唯一名)

well-known name形如:”org.fmddlmyy.Test“

unique name形如:”:1.114“

well-known name可以被多个连接(非同时)所拥有,unique name在所有连接中是唯一的。一个连接可以同时拥有well-known name和unique name,well-known name,但是唯一名是必须的,但熟知名不是必须的。well-known name可以类比于网络中的域名,unique name可以类比于网络中的IP地址。

当多个应用连接到消息总线,要求提供同一个公共名的服务。消息总线会把这些连接排在链表中,并选择一个连接提供公共名代表的服务。可以说这个提供服务的连接拥有了这个公共名。如果这个连接退出了,消息总线会从链表中选择下一个连接提供服务。

Native Objects and Object Paths: Native Objects类似java中的java.lang.Object、QT中的QObject等等。在最底层的dbus中纯在形式只是一个字符串。

Object Paths形如:”/TestObject“

Methods and Signals(Name): Methods表示被具体调用的方法,而Signals就是信号。Method可以有返回值,Signals一定没有返回值,此外,Signals可以进行广播,应用程序可以向bus订阅要接收的信号的Interface,一旦注册,只要DBUS收到信号,就会根据的信号的接口,将信号广播给相应的应用程序。在最底层的dbus中纯在形式只是一个字符串。

Interfaces(Name): 相当于C++中的纯虚类。每个对象都有一个或者多个接口,一个接口就是多个方法和信号的集合。在最底层的dbus中纯在形式只是一个字符串。

形如:
org.fmddlmyy.Test.Basic

org.freedesktop.DBus.Introspectable (由消息总线提供的标准接口

org.freedesktop.DBus.Properties (由消息总线提供的标准接口

在基于C实现的最底层的dbus中的对象、接口、方法、信号等概念可能很难去理解,我最开始也是比较困惑,但是如果你对dbus框架感兴趣的话,可以去了解一下dbus在面向对象的语言在的用法,比如dbus-c++,他里面的这些概念就非常直观。

因为D-BUS的底层接口没有对象相关概念,所以它的Object、Methods、Signals、Interfaces都是以字符串的形式标识。在面向对象的语言对dbus进行封装后,我们可以通过编写XML来定义接口和方法,并且通过我们编写的XML来生成相应的接口代码。接口里面就会包括方法和信号的定义。用户只用去继承这些接口,然后去实现它里面的方法即可。当然用户还需要去根据这些接口去定义相应的对象

这里我故意漏掉了一个概念—Proxies: 代理对象用来表示其他的remote object。当触发了proxy对象的method时,将会在D-Bus上发送一个method_call的消息,并等待答复,根据答复返回。总线上的对象一般通过代理来访问。总线上的对象位于客户进程以外,而客户可以调用本地接口与对象通信,此时,本地接口充当了代理的角色。当触发了代理对象的方法时,将会在D-Bus上发送一个method_call的消息,并等待答复返回,就象使用一个本地对象一样。重点关注最后一句话!代理能够使用户去调用一个本地接口,该本地接口代替你向总线发消息,去调用另一个进程方法,并且接收返回值。简而言之,代理的概念还是要配合面向对象的语言对dbus的封装才好理解。

比如不用代理:

Message message = new Message("/remote/object/path", "MethodName", arg1, arg2); 
Connection connection = getBusConnection();           
connection.send(message);           
Message reply = connection.waitForReply(message);           
if (reply.isError()) {                         
}
else {              Object returnValue = reply.getReturnValue();           
} 

用代理就是:

Proxy proxy = new Proxy(getBusConnection(), "/remote/object/path");           
Object returnValue = proxy.MethodName(arg1, arg2);

dbus规定了一个统一的接口:org.freedesktop.DBus.Introspectable,通过该接口的Introspect方法,可以递归遍历一个连接的对象树,包括server的接口和其方法、信号。另外因为Bus Daemon Process也属于进程,应用进程也可以请求Bus Daemon Process的接口和方法。Bus Daemon Process的Bus Name为:org.freedesktop.DBus,利用总线的org.freedesktop.DBus.Introspectable.Introspect方法我们可以查看消息总线对象支持的接口以及其方法、信号。此外我们还可以调用总线的\对象的org.freedesktop.DBus.ListNames方法,来获取消息总线上已连接的所有连接名,包括所有公共名和唯一名。

这些内容具体细节在https://www.e-learn.cn/topic/1808992有深入讲解,感兴趣的读者可以去看一看。

dbus是支持提供server的应用程序按需启动,在client请求的server应用程序没有启动时,daemon bus首先会依据配置起一个server应用程序。通过总线的/对象的org.freedesktop.DBus.ListActivatableNames方法,可以获取所有能够自启动的服务。

要想让自己的server应用程序自启动,需要添加一个配置文件,如下:

vim /usr/share/dbus-1/services/org.fmddlmyy.Test.service# [D-BUS Service]
# Name=org.fmddlmyy.Test    # 定义Bus Name
# Exec=/home/lvjie/work/dbus/hello-dbus3-0.1/src/example-service    # 提供可执行程序的路径

dbus的方法参数、返回值类型可以是基本类型,也可以是复合类型,具体语法可以参考:https://pythonhosted.org/txdbus/dbus_overview.html。

这里简单列举一下复合类型:

数组:

ai - 32位整型数组

a(ii) - 元素类型为两个32位整型的结构体的数组

aai - 元素类型为32位整型的数组的数组

字典:

a{ss} - key为string,value为string

a{is} - key为32位整数 ⇒ value为string

a{s(ii)} - key为string ⇒ value为包含2个32位整数的数组

a{sa{ss}} - key为string ⇒ value也是字典。

DBus示例代码

Server Application:不断处理来自Client Application的方法调用。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dbus/dbus.h>
#include <unistd.h>void reply_to_method_call(DBusMessage *msg, DBusConnection *conn){DBusMessage *reply;DBusMessageIter arg;char *param = NULL;dbus_bool_t stat = TRUE;dbus_uint32_t level = 2010;dbus_uint32_t serial = 0;//从msg中读取参数if(!dbus_message_iter_init(msg, &arg))printf("Message has noargs\n");else if(dbus_message_iter_get_arg_type(&arg) != DBUS_TYPE_STRING)printf("Arg is notstring!\n");elsedbus_message_iter_get_basic(&arg, &param);if(param == NULL) return;//创建返回消息replyreply = dbus_message_new_method_return(msg);//在返回消息中填入两个参数,和信号加入参数的方式是一样的。这次我们将加入两个参数。dbus_message_iter_init_append(reply, &arg);if(!dbus_message_iter_append_basic(&arg, DBUS_TYPE_BOOLEAN, &stat)){printf("Out ofMemory!\n");exit(1);}if(!dbus_message_iter_append_basic(&arg, DBUS_TYPE_UINT32, &level)){printf("Out ofMemory!\n");exit(1);}//发送返回消息if(!dbus_connection_send(conn, reply, &serial)){printf("Out of Memory\n");exit(1);}dbus_connection_flush(conn);dbus_message_unref(reply);
}void listen_dbus()
{DBusMessage *msg;DBusMessageIter arg;DBusConnection *connection;DBusError err;int ret;char *sigvalue;dbus_error_init(&err);//创建于session D-Bus的连接connection = dbus_bus_get(DBUS_BUS_SESSION, &err);if(dbus_error_is_set(&err)){fprintf(stderr, "ConnectionError %s\n", err.message);dbus_error_free(&err);}if(connection == NULL)return;//设置一个BUS name:test.wei.destret = dbus_bus_request_name(connection, "test.wei.dest", DBUS_NAME_FLAG_REPLACE_EXISTING, &err);if(dbus_error_is_set(&err)){fprintf(stderr, "Name Error%s\n", err.message);dbus_error_free(&err);}if(ret != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)return;//要求监听某个singal:来自接口test.signal.Type的信号dbus_bus_add_match(connection, "type='signal', interface='test.signal.Type'", &err);dbus_connection_flush(connection);if(dbus_error_is_set(&err)){fprintf(stderr, "Match Error%s\n", err.message);dbus_error_free(&err);}while(1){dbus_connection_read_write(connection, 0);msg = dbus_connection_pop_message(connection);if(msg == NULL){sleep(1);continue;}if(dbus_message_is_signal(msg, "test.signal.Type", "Test")){if(!dbus_message_iter_init(msg, &arg))fprintf(stderr, "Message Has no Param");else if(dbus_message_iter_get_arg_type(&arg) != DBUS_TYPE_STRING)fprintf(stderr, "Param isnot string");else{dbus_message_iter_get_basic(&arg, &sigvalue);fprintf(stdout, "[method_call]Got Singal withvalue : %s\n", sigvalue);}}else if(dbus_message_is_method_call(msg, "test.method.Type", "Method")){//我们这里面先比较了接口名字和方法名字,实际上应当现比较路径if(strcmp(dbus_message_get_path(msg), "/test/method/Object") == 0){reply_to_method_call(msg, connection);fprintf(stdout, "[method_call]Got method_call, reply to it!\n");}}dbus_message_unref(msg);}
}int main(int argc, char **argv){listen_dbus();return 0;
}

Client Application:发送Method Call消息或者信号。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dbus/dbus.h>
#include <unistd.h>//建立与session D-Bus daemo的连接,并设定连接的名字,相关的代码已经多次使用过了
DBusConnection* connect_dbus()
{DBusError err;DBusConnection *connection;int ret;//Step 1: connecting session busdbus_error_init(&err);connection = dbus_bus_get(DBUS_BUS_SESSION, &err);if(dbus_error_is_set(&err)){fprintf(stderr, "ConnectionErr : %s\n", err.message);dbus_error_free(&err);}if(connection == NULL)return NULL;//step 2: 设置BUS name,也即连接的名字。ret = dbus_bus_request_name(connection, "test.wei.source", DBUS_NAME_FLAG_REPLACE_EXISTING, &err);if(dbus_error_is_set(&err)){fprintf(stderr, "Name Err :%s\n", err.message);dbus_error_free(&err);}if(ret != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)return NULL;return connection;
}void send_a_method_call(DBusConnection *connection,char *param)
{DBusError err;DBusMessage *msg;DBusMessageIter arg;DBusPendingCall *pending;dbus_bool_t *stat;dbus_uint32_t *level;dbus_error_init(&err);//针对目的地地址,请参考图,创建一个method call消息。Constructs a new message to invoke a method on a remote object.msg = dbus_message_new_method_call("test.wei.dest", "/test/method/Object", "test.method.Type", "Method");if(msg == NULL){fprintf(stderr, "MessageNULL");return;}//为消息添加参数。Appendargumentsdbus_message_iter_init_append(msg, &arg);if(!dbus_message_iter_append_basic(&arg, DBUS_TYPE_STRING, &param)){fprintf(stderr, "Out of Memory!");exit(1);}//发送消息并获得reply的handle。Queues amessage to send, as withdbus_connection_send() , but also returns aDBusPendingCall used to receive a reply to the message.if(!dbus_connection_send_with_reply(connection, msg, &pending, -1)){fprintf(stderr, "Out of Memory!");exit(1);}if(pending == NULL){fprintf(stderr, "Pending CallNULL: connection is disconnected ");dbus_message_unref(msg);return;}dbus_connection_flush(connection);dbus_message_unref(msg);//waiting a reply,在发送的时候,已经获取了methodreply的handle,类型为DBusPendingCall。// block until we recieve a reply, Block until the pendingcall is completed.dbus_pending_call_block(pending);//get the reply message,Gets thereply, or returns NULL if none has been received yet.msg = dbus_pending_call_steal_reply(pending);if (msg == NULL) {fprintf(stderr, "ReplyNull\n");exit(1);}// free the pendingmessage handledbus_pending_call_unref(pending);// read the parametersif(!dbus_message_iter_init(msg, &arg))fprintf(stderr, "Message hasno arguments!\n");else if (dbus_message_iter_get_arg_type(&arg) != DBUS_TYPE_BOOLEAN)fprintf(stderr, "Argument isnot boolean!\n");elsedbus_message_iter_get_basic(&arg, &stat);if (!dbus_message_iter_next(&arg))fprintf(stderr, "Message hastoo few arguments!\n");else if (dbus_message_iter_get_arg_type(&arg) != DBUS_TYPE_UINT32 )fprintf(stderr, "Argument isnot int!\n");elsedbus_message_iter_get_basic(&arg, &level);printf("Got Reply: %d,%d\n", stat, level);dbus_message_unref(msg);
}int send_a_signal(DBusConnection *connection, char *sigvalue)
{DBusError err;DBusMessage *msg;DBusMessageIter arg;dbus_uint32_t  serial = 0;int ret;//步骤3:发送一个信号//根据图,我们给出这个信号的路径(即可以指向对象),接口,以及信号名,创建一个Messageif((msg = dbus_message_new_signal("/test/signal/Object", "test.signal.Type", "Test"))== NULL){fprintf(stderr, "MessageNULL\n");return -1;}//给这个信号(messge)具体的内容dbus_message_iter_init_append(msg, &arg);if(!dbus_message_iter_append_basic(&arg, DBUS_TYPE_STRING, &sigvalue)){fprintf(stderr, "Out OfMemory!\n");return -1;}//步骤4: 将信号从连接中发送if(!dbus_connection_send(connection, msg, &serial)){fprintf(stderr, "Out of Memory!\n");return -1;}dbus_connection_flush(connection);printf("Signal Send\n");//步骤5: 释放相关的分配的内存。dbus_message_unref(msg);return 0;
}int main(int argc, char **argv)
{DBusConnection *connection;connection = connect_dbus();if(connection == NULL)return -1;if (argc > 1) {send_a_method_call(connection,"Hello, D-Bus");} else {send_a_signal(connection, "Hello,world!");}return 0;
}
gcc -Wall -o server server.c -ldbus-1 -I/usr/include/dbus-1.0/ -I/usr/include/glib-2.0/ -I/usr/lib/x86_64-linux-gnu/glib-2.0/include/ -I/usr/lib/x86_64-linux-gnu/dbus-1.0/include/gcc -Wall -o client client.c -ldbus-1 -I/usr/include/dbus-1.0/ -I/usr/include/glib-2.0/ -I/usr/lib/x86_64-linux-gnu/glib-2.0/include/ -I/usr/lib/x86_64-linux-gnu/dbus-1.0/include/

结果如下:

在这里插入图片描述


本章完结

相关文章:

DBus快速入门

DBus快速入门 参考链接&#xff1a; 中文博客&#xff1a; https://www.e-learn.cn/topic/1808992 https://blog.csdn.net/u011942101/article/details/123383195 https://blog.csdn.net/weixin_44498318/article/details/115803936 https://www.e-learn.cn/topic/1808992 htt…...

SQL Server 设置端口号:详细步骤与注意事项

目录 一、了解SQL Server端口号的基础知识 1.1 默认端口号 1.2 静态端口与动态端口 二、使用SQL Server配置管理器设置端口号 2.1 打开SQL Server配置管理器 2.2 定位到SQL Server网络配置 2.3 修改TCP/IP属性 2.4 重启SQL Server服务 三、注意事项 3.1 防火墙设置 3…...

Python面试题:结合Python技术,如何使用NetworkX进行复杂网络分析

NetworkX 是一个强大的 Python 库&#xff0c;用于创建、操作和研究复杂网络的结构、动力学和功能。它提供了丰富的功能来处理图和网络数据&#xff0c;适合用于复杂网络分析。以下是使用 NetworkX 进行复杂网络分析的基本步骤&#xff1a; 安装 NetworkX&#xff1a; pip inst…...

【C#/C++】C#调C++的接口,给C++传结构体数组

C#调C的接口&#xff0c;给C传结构体数组 1、背景2、实现 1、背景 C#软件创建了一个结构体数组用来存储图像的区域信息&#xff0c;分别是矩形框的左上像素的xy坐标和矩形框右下像素的xy坐标。需要传入给调用的C函数的参数列表中&#xff0c;我们选择使用C#传入一个结构体数组…...

ctfshow SSTI注入 web369--web372

web369 这把request过滤了&#xff0c;只能自己拼字符了 ""[[__clas,s__]|join] 或者 ""[(__clas,s__)|join] 相当于 ""["__class__"]举个例子&#xff0c;chr(97) 返回的是字符 a&#xff0c;因为 97 是小写字母 a 的 Unicode 编码…...

Llama + Dify,在你的电脑搭建一套AI工作流

theme: smartblue 点赞 关注 收藏 学会了 本文简介 最近字节在推Coze&#xff0c;你可以在这个平台制作知识库、制作工作流&#xff0c;生成一个具有特定领域知识的智能体。 那么&#xff0c;有没有可能在本地也部署一套这个东西呢&#xff1f;这样敏感数据就不会泄露了&…...

洛谷 P9854 [CCC 2008 J1] Body Mass Index

这题让我们计算出 BMI 值&#xff0c;随后判断属于哪个等级。 BMI 值计算公式&#xff1a; ​​​​​​​ ​​​​​​​ ​​​​​​​ ​​​​​​​ ​​​​​​​。 BMI 范围 对应信息 …...

Redis面试三道题目

针对Redis的面试题&#xff0c;我将从简单到困难给出三道题目&#xff0c;并附上参考答案的概要。 1. 简单题&#xff1a;请简述Redis是什么&#xff0c;以及它的主要优点。 参考答案&#xff1a; Redis简介&#xff1a;Redis是一个开源的、使用ANSI C语言编写、支持网络、可…...

redis的使用场景-分布式锁

使用redis的setnx命令放入数据并用此数据当锁完成业务&#xff08;但是如果用户操作途中出现异常导致超出指定时间会出现问题&#xff09; Service public class StockService {Autowiredprivate StockDao stockDao; //mapper注入Autowiredprivate StringRedisTemplate redisT…...

知识库系统全解析:2024年最佳9款

本文将分享9款优质团队知识库管理工具&#xff1a;PingCode、Worktile、石墨文档、语雀、Wolai 我来、有道云笔记、飞书文档、Confluence、Notion。 在追求高效团队运作的今天&#xff0c;掌握和整合知识成为了企业不可或缺的需求。但面对市场上琳琅满目的知识库管理工具&#…...

猫头虎分享:Numpy知识点一文带你详细学习np.random.randn()

&#x1f42f; 猫头虎分享&#xff1a;Numpy知识点一文带你详细学习np.random.randn() 摘要 Numpy 是数据科学和机器学习领域中不可或缺的工具。在本篇文章中&#xff0c;我们将深入探讨 np.random.randn()&#xff0c;一个用于生成标准正态分布的强大函数。通过详细的代码示…...

QT 关于QTableWidget的常规使用

目录 一、初始化 二、封装功能用法 三、结语 一、初始化 1、设置表头 直接在ui设计界面修改或者使用QT封装的函数修改&#xff0c;代码如下&#xff1a; QStringList recList {"第一列", "第二列", "第三列"}; ui->tableWidget->setH…...

PyCharm 常用 的插件

Material Theme UI Lite&#xff1a;‌提供多种不同的页面风格&#xff0c;‌为PyCharm界面增添个性化元素。‌Chinese (Simplified) Language Pack&#xff1a;‌为中文用户提供简体中文的界面、‌菜单、‌提示信息&#xff0c;‌提升使用体验。‌Tabnine&#xff1a;‌基于人…...

理解 HTTP 请求中 Query 和 Body 的异同

本文将深入探讨HTTP请求中的两个关键要素&#xff1a;查询参数&#xff08;Query&#xff09;和请求体&#xff08;Body&#xff09;。我们将阐明它们之间的差异&#xff0c;并讨论在何种情况下使用每一种。 HTTP 请求概述 HTTP 请求是客户端&#xff08;如浏览器&#xff09…...

【AI大模型】 企业级向量数据库的选择与实战

前言 ChatGPT4相比于ChatGPT3.5,有着诸多不可比拟的优势&#xff0c;比如图片生成、图片内容解析、GPTS开发、更智能的语言理解能力等&#xff0c;但是在国内使用GPT4存在网络及充值障碍等问题&#xff0c;如果您对ChatGPT4.0感兴趣&#xff0c;可以私信博主为您解决账号和环境…...

LangChain开发框架并学会对大型预训练模型进行微调(fine-tuning)

要掌握LangChain开发框架并学会对大型预训练模型进行微调&#xff08;fine-tuning&#xff09;&#xff0c;你需要理解整个过程从数据准备到最终部署的各个环节。下面是这一流程的一个概览&#xff0c;并提供了一些关键步骤和技术点&#xff1a; 1. LangChain开发框架简介 La…...

VMware安装(有的时候启动就蓝屏建议换VM版本)

当你开始使用虚拟化技术来管理和运行多个操作系统时&#xff0c;VMware 是一个强大且广泛使用的选择。本篇博客将指导你如何安装 VMware Workstation Pro&#xff0c;这是一个功能强大的虚拟机软件&#xff0c;适用于个人和专业用户。 一、下载 VMware Workstation Pro 访问官网…...

AV1技术学习:Quantization

量化是对变换系数进行&#xff0c;并将量化索引熵编码。AV1的量化参数 QP 的取值范围是0 ~ 255。 一、Quantization Step Size 在给定的 QP 下&#xff0c;DC 系数的量化步长小于 AC 系数的量化步长。DC 系数和 AC 系数从 QP 到量化步长的映射如下图所示。当 QP 为 0 时&…...

vllm部署记录

1. pip安装 pip install vllm 下载模型在huggingface.co 注意在modelscope上的这个opt-125m好像不行了,我git不下来报错 启动服务 vllm serve opt-125m --model opt-125m --port 8888 第一个opt-125m是名字,可以在vllm支持的模型中查到,第二个是模型存放文件夹及其路径…...

HTML前端 盒模型及常见的布局 流式布局 弹性布局 网格布局

CSDN的文章没有“树状目录管理”&#xff0c;所以我在这里整理几篇相关的博客链接。 操作有些麻烦。 CSS 两种盒模型 box-sizing content-box 和 border-box 流式布局 flow layout 弹性布局 flex layout HTML CSS 网格布局 grid layout HTML CSS...

网络安全 DVWA通关指南 DVWA Command Injection(命令注入)

DVWA Command Injection&#xff08;命令注入&#xff09; 文章目录 DVWA Command Injection&#xff08;命令注入&#xff09;LowMediumHighImpossible Low 1、分析网页源代码 <?php// 当表单提交按钮&#xff08;Submit&#xff09;被触发时执行以下代码 if (isset($_P…...

VUE3学习第三篇:报错记录

1、在我整理好前端代码框架后&#xff0c;而且也启动好了对应的后台服务&#xff0c;访问页面&#xff0c;正常。 2、报错ReferenceError: defineModel is not defined 学到这里报错了 在vue网站的演练场&#xff0c;使用没问题 但是在我自己的代码里就出问题了 3、watchEffec…...

CentOS怎么关闭自动锁屏?

禁止自动锁屏 有时候几分钟不用Centos&#xff0c;系统就自动锁屏了&#xff0c;这是一种安全措施&#xff0c;防止别人趁你不在时使用你的系统。但对于大部分人而言&#xff0c;这是没有必要的&#xff0c;尤其是Centos虚拟机&#xff0c;里面没啥重要的东西&#xff0c;每次…...

vscode 环境

这张截图显示的是在VS Code&#xff08;Visual Studio Code&#xff09;中选择Python解释器的界面。不同的Python解释器及其虚拟环境列出了可选项&#xff0c;用户可以根据需要选择合适的解释器来运行Python代码。以下是对截图中信息的详细解释&#xff1a; 解释器选择界面 当…...

浏览器自动化测试工具selenium——爬虫操作记录

selenium——是一款web自动化测试框架&#xff0c;其能模拟正常的用户操作&#xff0c;比如点击。但selenium并不是浏览器&#xff0c;没有执行js和解析html/css的能力&#xff0c;因此selenium需要和浏览器配合使用。 因为selenium可以模仿用户行为&#xff0c;因此selenium也…...

微信小程序配置访问服务器失败所发现的问题及解决方案

目录 事前现象问题1&#xff1a;问题现象&#xff1a;问题分析&#xff1a; 问题2&#xff1a;问题现象&#xff1a;问题分析&#xff1a;解决方案&#xff1a; 事后现象 事前现象 问题1&#xff1a; 问题现象&#xff1a; 在本地调试时&#xff0c;一切顺利&#xff0c;但一…...

javaEE(1)

一. Web开发概述 Web开发:指的是从网页中向后端程序发送请求,与后端程序进行交互 Web服务器:是一种软件,向浏览器等Web客户端提供文档等数据,实现数据共享,它是一个容器,是一个连接用户和程序之间的中间键 二. Web开发环境搭建 我们要实现前后端交互,首先需要中间键Web服务…...

极简Springboot+Mybatis-Plus+Vue零基础萌新都看得懂的分页查询(富含前后端项目案例)

目录 springboot配置相关 依赖配置 yaml配置 MySQL创建与使用 &#xff08;可拿软件包项目系统&#xff09; 创建数据库 创建数据表 mybatis-plus相关 Mapper配置 ​编辑 启动类放MapperScan 启动类中配置 添加config配置文件 Springboot编码 实体类 mapperc(Dao…...

IPython的Bash之舞:%%bash命令全解析

IPython的Bash之舞&#xff1a;%%bash命令全解析 IPython的%%bash魔术命令为Jupyter Notebook用户提供了一种在单元格中直接执行Bash脚本的能力。这个特性特别适用于需要在Notebook中运行系统命令或Bash特定功能的场景。本文将详细介绍如何在IPython中使用%%bash命令&#xff…...

ST Stellar-E SR5E1 22KW OBC combo 3KW DC-DC汽车充电器解决方案

对于全球的环境保护意识抬头&#xff0c;全球的汽车产业慢慢步入电动化的时代&#xff0c;以减少碳排放。整车系统主要是由电池、电驱、电控的三电所构成&#xff0c;其中电池系统是整车的动力来源&#xff0c;而对电池充电的OBC系统更甚重要。一具高度安全性且高效的OBC系统&a…...

Postman中的A/B测试实践:优化API性能的科学方法

Postman中的A/B测试实践&#xff1a;优化API性能的科学方法 在API开发和测试过程中&#xff0c;A/B测试是一种验证新功能或变更效果的有效方法。通过比较两个或多个版本&#xff08;例如A版本和B版本&#xff09;的性能&#xff0c;可以科学地评估变更的影响。Postman作为API测…...

微信小程序支付流程

前端需要做的事情&#xff1a; 生成平台订单&#xff1a;前端调用接口&#xff0c;向后端传递购买的商品信息、收货人信息&#xff0c;&#xff08;后端生成平台订单&#xff0c;返回订单编号&#xff09;获取预付单信息&#xff1a;将订单编号发送给后端后&#xff0c;&#x…...

Istio 学习笔记

Istio 学习笔记 作者&#xff1a;王珂 邮箱&#xff1a;49186456qq.com 文章目录 Istio 学习笔记[TOC] 前言一、基本概念1.1 Istio定义 二、Istio的安装2.1 通过Istioctl安装2.2 通过Helm安装 三、Istio组件3.1 Gateway3.2 VirtulService3.2.1 route详解3.2.2 match详解3.2.3…...

测试面试宝典(三十三)—— 接口测试有没有测试出什么问题?

在之前的接口测试工作中&#xff0c;确实发现了一些问题。比如&#xff0c;在对某关键业务接口进行测试时&#xff0c;发现当输入的参数值超出正常范围时&#xff0c;接口没有按照预期返回错误提示&#xff0c;而是出现了系统崩溃的情况。 还有一次&#xff0c;在测试一个数据…...

YOLOV8模型转TFJS 在Mac下遇到的版本的坑

1.目的&#xff1a;将训练好的yolov8模型转化成TFJS格式&#xff0c;用于在浏览器中通过tensorflow调用&#xff1b; 遇到问题&#xff1a; A KerasTensor cannot be used as input to a TensorFlow function. 本地环境&#xff1a; python :3.11 自动安装的版本为&#xf…...

vue、react前端框架实现TodoList页面案例

原始TodoList网页&#xff08;主要就是链接里网页应用ndex.html、styles.css、script.js &#xff09;&#xff1a; https://blog.csdn.net/weixin_42357472/article/details/140657576 node、npn安装参考&#xff1a; https://blog.csdn.net/weixin_42357472/article/details/…...

el-date-picker 时间控件校验选择时间必须早于当前时间(带时分秒)

el-date-picker 时间控件校验选择时间必须遭早于当前时间&#xff08;带时分秒&#xff09;&#xff0c;然后监控时间控件&#xff0c;当时间改变的时候&#xff0c;如果不是当天&#xff0c;那时间可以选择全天也就是00-24时&#xff0c;如果是当天&#xff0c;就是当前时间之…...

godot新建项目及设置外部编辑器为vscode

一、新建项目 初次打开界面如下所示&#xff0c;点击取消按钮先关闭掉默认弹出的框 点击①新建弹出中间的弹窗②中填入项目的名称 ③中设置项目的存储路径&#xff0c;点击箭头所指浏览按钮&#xff0c;会弹出如下所示窗口 根据图中所示可以选择或新建自己的游戏存储路径&…...

vue中无法调试

vue.config.js中增加 devtool configureWebpack: {name: name,resolve: {alias: {: resolve(src)}},devtool: "cheap-module-source-map" // add},然后重启即可。 顺便招聘&#xff1a;1.需要会日语。2.Java&#xff0c;JS&#xff0c;Vue&#xff0c;DB任一会者皆…...

python机器学习8--自然语言处理(2)

1&#xff0e;移除用词 在很多情况下&#xff0c;有一些文章内的英文字符、标点符号分词的结果不符合自己的预期&#xff0c;会出现一些不想要的分词&#xff0c;此时就能通过以下的函数自己设定用词&#xff0c;并且删除。 jieba.analyse.set_stop_words("stop_words.tx…...

LinkedList底层原理

节点&#xff08;Node&#xff09;结构 LinkedList 的核心是一个内部类 Node&#xff0c;每个 Node 对象代表链表中的一个元素&#xff0c;并且每个节点包含三个部分&#xff1a; 元素值 (item)&#xff1a;存储实际的数据。前驱节点引用 (prev)&#xff1a;指向当前节点前面…...

CSS技巧专栏:一日一例 11 -纯CSS实现多彩渐变按钮系列特效

CSS技巧专栏:一日一例 11 -纯CSS实现多彩渐变按钮系列特效 本篇,推荐给你几个按钮,先看一下图片 本例图片 案例分析 这是一个系列的按钮,它们具有共同的特点: 底层按钮层,具有一个彩色的渐变边框,上层是依据hover效果需要,可以是渐变,可以时白色。 鼠标hover效果…...

基于微信小程序+SpringBoot+Vue的自助点餐系统(带1w+文档)

基于微信小程序SpringBootVue的自助点餐系统(带1w文档) 基于微信小程序SpringBootVue的自助点餐系统(带1w文档) 基于微信小程序的自助点餐系统前后台分离&#xff0c;让商品订单&#xff0c;用户反馈信息&#xff0c;商品信息等相关信息集中在后台让管理员管理&#xff0c;让用…...

04-Charles中的Map Remote和Map Local介绍

Charles提供了Map Remote和Map Local两个功能。 Map Remote是将指定的网络请求重定向到另一个网址。Map Local是将指定的网络请求重定向到本地文件。 一、Map Remote 假设代码中调用了接口A&#xff0c;但是接口A的响应结果不能满足需求&#xff1b;此时&#xff0c;有另一个…...

R语言优雅的进行广义可加模型泊松回归分析

泊松回归&#xff08;Poisson regression&#xff09;是以结局变量为计数结果时的一种回归分析。泊松回归在我们的生活中应用非常广泛&#xff0c;例如&#xff1a;1分钟内过马路人数&#xff0c;1天内火车站的旅客流动数&#xff0c;1天内的银行取钱人数&#xff0c;一周内的销…...

大模型学习笔记十四:Agent模型微调

文章目录 一、大模型需要Agent技术的原因二、Prompt Engineering可以实现Agent吗&#xff1f;&#xff08;1&#xff09;ReAct原理展示和代码&#xff08;2&#xff09;ModelScope&#xff08;3&#xff09;AutoGPT&#xff08;4&#xff09;ToolLLaMA 三、既然AutoGPT可以满足…...

大疆创新2025校招内推

大疆2025校招-内推 一、我们是谁&#xff1f; 大疆研发软件团队&#xff0c;致力于把大疆的硬件设备和大疆用户紧密连接在一起&#xff0c;我们的使命是“让机器有温度&#xff0c;让数据会说话”。 在消费和手持团队&#xff0c;我们的温度来自于激发用户灵感并助力用户创作…...

搜索引擎项目(四)

SearchEngine 王宇璇/submit - 码云 - 开源中国 (gitee.com) 基于Servlet完成前后端交互 WebServlet("/searcher") public class DocSearcherServlet extends HttpServlet {private static DocSearcher docSearcher new DocSearcher();private ObjectMapper obje…...

声音克隆一键本地化部署 GPT-SoVITS

文章目录 GPT-SoVITS 介绍1:GPT-SoVITS安装2:GPT-SoVITS使用2.1 人声伴奏分离,去混响去延时工具2.2 语音切分工具2.3 语音降噪工具2.4 中文批量离线ASR工具2.5 语音文本校对标注工具GPT-SoVITS 介绍 GPT-SoVITS: 是一个由RVC变声器创始人“花儿不哭”推出的免费开源项目。…...

使用【Easypoi】实现百万数据导出

本文使用easypoi实现百万级数据导出 文章目录 前言一、一般情况下导出二、解决思路三、实现步骤导入依赖重写方法调用实现 结束 前言 下文实现了通过easypoi实现将百万级数据导出 一、一般情况下导出 一般导出流程&#xff08;简单导出&#xff09;&#xff1a; 创建对应的…...